最近自己動手將H264視頻流和AAC音頻流合成flv檔案,但是沒有採用開源的ffmpeg的api來處理音視頻流。方法就是模仿ffmpeg中libavformat/flvenc.c 檔案寫代碼來完成音視頻的flv格式封裝。在這個封裝過程中,需要非常清楚flv檔案格式。網上有關flv檔案格式的資料非常多,不過大部分資料是互相轉載或者缺乏足夠詳細的資訊(例如:AVDecoderConfigurationRecord和 AudioSpecificConfig的產生)。 因此我就以ffmpeg中libavformat/flvenc.c為基礎分析flv檔案的構成,詳細分析flv檔案中每個位元組的含義。以下每個方格代表一個位元組。其中的數字都是16進位表示(省略0x),格中的字元也可以用相應的16進位數字替代,用字元表示有時候更為直觀。假定flv檔案同時含有視頻和音頻。
接下來就是Metadata的具體資料,由兩個AMF包組成。
Metadata元素個數暫訂為12個 = 音頻5個 + 視頻5個 + 2個(duration和filesize)。 後面還可能會加入其它元素,因此會返回來修改此值。metadata元素的順序不固定,此處採用ffmpeg中的順序。 第二個AMF包中各數組元素封裝形式為:前兩個位元組是元素名稱的長度;後面跟著長度為L的字串;第L+3個位元組表示元素值的類型;後面跟著是對應值,佔用的位元組數取決於值的類型。 以下的(tag->key,tag->value)不一定在所有flv檔案中出現,依據不同版本有所不同。 Remark:以上將flv官方文檔的metadata資訊寫入了Script Tag中。但是在做flv檔案合成的時候,發現網上有的flv檔案將keyframes資訊隱藏在Script Tag中。後來通過網路查一些資料,發現keyframes幾乎是一個非官方的標準,也就是民間標準。 兩個常用的操作metadata的工具是flvtool2和FLVMDI, 都是把keyframes作為一個預設的元資訊項目。在FLVMDI的首頁(http://www.buraks.com/flvmdi/)上有描述: keyframes: (Object) This object is added only if you specify the /k switch. 'keyframes' is known to FLVMDI and if /k switch is not specified, 'keyframes' object will be deleted. 'keyframes' object has 2 arrays: 'filepositions' and 'times'. Both arrays have the same number of elements, which is equal to the number of key frames in the FLV. Values in times array are in 'seconds'. Each correspond to the timestamp of the n'th key frame. Values in filepositions array are in 'bytes'. Each correspond to the fileposition of the nth key frame video tag (which starts with byte tag type 9). 也就是說keyframes中包含著2個內容 'filepositions' and 'times'分別指的是主要畫面格的檔案位置和主要畫面格的PTS。通過keyframes可以建立起自己的Index,然後再seek和快進快退的操作中,快速有效跳轉到你想要找的主要畫面格位置進行處理。