PythonはFLVビデオのつなぎ合わせ機能を実現します。


記事の要約
本論文では、FLVファイルのフォーマットを簡単に説明し、これを出発点としてPythonを用いてFLVビデオのスティッチングを実現する。
一.FLVファイルフォーマット
FLVファイルフォーマットの解析ネット上には多くの文章がありますが、ここでは分かりやすい部分を簡単に紹介して、読者が各セグメントのコードの機能をよりよく理解するようにします。
FLVファイルは、ファイルヘッダとファイルボディ(Body)が順にスティッチングされます。FLVコンテンツを審査する場合は、コンテンツをバイナリで読み出す。
Header:ファイルヘッダは、ファイルのパッケージフォーマットがFLVであることを示し、格納対象はオーディオ、ビデオまたは両方である。
以下はFLVファイルのHeaderで、合計9バイト:
b'FLV\x 01\x 05\x 00\x 00\t'
前の3バイト(FLV)は、FLVファイルであると説明しています。
4番目のバイト(\x 01)はバージョン番号で、1に固定されています。
5番目のバイト(\x 05)は、格納対象がバイナリ(0000101)に変換される必要があることを示し、左、右の1は、それぞれファイルがオーディオとビデオを含むことを表している。
後の4バイト(\x 00\x 00\x 00\t)はファイルヘッダの長さを表し、その値は9に固定されています。
Body:ファイル体はいくつかのTagから構成されています。最初を除いて、各Tagはヘッダ(11バイト)、本体(不定長)、および末尾(4バイト)から構成されています。最初のTagは尾だけです。
Tagはまた3種類に分けられ、シナリオ、オーディオ、ビデオ(video)があります。通常、2番目のTagはシナリオタイプであり、1つしかなく、後続は音声ビデオタイプである。
脚本Tagの部分を例として紹介します。
頭:b'\x 12\x 00\tb\x 00\x 00\x 00\x 00\x 00\x 00\x 00\x 00\x 00\x 00'
1番目のバイト(\x 12)はTagタイプを表し、スクリプトタイプの対応値は18、オーディオは8、ビデオは9です。
2バイト目(\x 00\tb)はTag本体の長さを表します。ここで2402です。
5バイト目(\x 00\x 00\x 00\x 00)はタイムスタンプで、スクリプトタイプのタイムスタンプは通常0です。
8番目のバイト(\x 00)はタイムスタンプの拡張です。現在3バイトが足りない場合はこのバイトを大端として使います。
後3バイト(\x 00\x 00\x 00\x 00)はStream idで、0に固定されています。
主体:脚本Tagの主体はFLVビデオの基本情報を含んでいます。例えば、時間が長い、サイズ、解像度など、複雑です。ここでは紹介しません。
尾部:b'\x 00\x 00\tm'
4バイトを固定して、Tagの頭に本体の長さを加えるという意味で、11+2402=2413です。
二.FLVビデオスティッチング
複数のFLVビデオを正常に再生できるビデオに合成することで、ほとんどの需要を満たすことができる。したがって、次のスティッチングの過程では、FLVを細かく調整しないで、基本的な要求を達成すればいいです。
リーダーを設定する
リーダーはファイルの内容を読みやすくすることができます。

class Reader():
  def __init__(self, content): # content (bytes):FLV        
    self.content = content
    self.start = 0
    self.eof = False #            
    self.length = len(self.content)
    
  def read(self, n=1):
    #    if           
    if self.length > (self.start + n):
      out = self.content[self.start:self.start + n]
      self.start += n
    else:
      out = self.content[self.start:]
      self.eof = True
    return out
新規FLVファイルにHeaderとTagを書き込みます。
ここでは、スティッチングするビデオの基本的な情報が似ていると仮定します。すなわち、音声ビデオ、解像度、符号率などが同じまたは近いです。
通常再生可能なFLVビデオを生成するためには、HeaderとTagが必要である。最初のFLVのファイルヘッダを選択して新しいFLVに書き込み、その後順次タイムスタンプを修正したTagを書き込みます。

def add_flv(flv, target, videoTimeStamp, audioTimeStamp): #       Tag    
  with open(flv, 'rb') as f:
    content = f.read()
  reader = Reader(content)
  header = reader.read(13)
  with open(target, 'ab') as f:
    while not reader.eof: #         ,   reader.eof = True
      dataType = reader.read(1)
      dataSize = reader.read(3)
      timeStamp = int.from_bytes(reader.read(3), 'big') #   3        
      headerRemained = reader.read(4)
      if dataType == b'\t': #   
        timeStamp += videoTimeStamp
        videoTS = timeStamp
      if dataType == b'\x08': #   
        timeStamp += audioTimeStamp
        audioTS = timeStamp
      timeStamp = timeStamp.to_bytes(3, 'big') #        3   
      tagHeader = dataType + dataSize + timeStamp + headerRemained
      tagData_andSize = reader.read(int.from_bytes(dataSize, 'big') + 4)
      f.write(tagHeader)
      f.write(tagData_andSize)
  return videoTS, audioTS
def merge_flv(flvs, target): #    
  videoTS = 0
  audioTS = 0
  for i, flv in enumerate(flvs):
    with open(flv, 'rb') as f:
      content = f.read()
    reader = Reader(content)
    
    header = reader.read(13) # flvHeader + tagSize0
    if i == 0: #     1  FLV      
      with open(target, 'wb') as f:
        f.write(header)
        
    videoTS, audioTS = add_flv(flv, target, videoTS, audioTS)
つづり合わせ

import time
since = time.time()
flvs = ['m1.flv', 'm2.flv', 'm3.flv', 'm4.flv'] #     :45MB,20MB,59MB,54MB
target = 't.flv'
merge_flv(flvs, target)
end = time.time()
print('Merging flvs takes {:.2f} s'.format(end - since))
# Merging flvs takes 0.88 s
4つの合計178 MBのビデオをつなぎ合わせて0.88秒使うことができます。
締め括りをつける
FLVファイルのフォーマットはやはり比較的に簡明で、データに対する要求も比較的にゆったりしていて、たとえScripptsの中のパラメーターに対して調整を行っていないとしても、つなぎ合わせた後のビデオは依然として正常に再生することができます。
しかし、つなぎ合わせのビデオには多くの隠し問題があります。動画の終わりになると、音画の不同期(0.5秒ぐらい)が発生する可能性があります。また、完全なビデオとオーディオを簡単に分離することができません。
以上は小编が绍介したPythonがFLVビデオのつなぎ合わせの机能を実现しました。皆さんに助けてほしいです。もし何か疑问があれば、メッセージをください。小编はすぐに皆さんに返事します。ここでも私たちのサイトを応援してくれてありがとうございます。
本文があなたのためになると思ったら、転載を歓迎します。出所を明記してください。ありがとうございます。