轉自:https://www.cnblogs.com/renhui/p/10348629.html
在網絡的直播與點播場景中,FLV也是一種常見的格式,FLV是Adobe發布的一種可以作為直播也可以作為點播的封裝格式,其封裝格式非常簡單,均以FLVTAG的形式存在,並且每一個TAG都是獨立存在的,接下來就詳細介紹一下FLV標准。
一、FLV 格式標准介紹
FLV包括文件頭(File Header)和文件體(File Body)兩部分,其中文件體由一系列的Tag組成。FLV文件的結構如下圖:
1. 文件頭 Header
Header 部分記錄了FLV的類型、版本等信息,是FLV的開頭。一般差不多占9bytes。具體格式如下:
1. 文件標識(3B):總是為”FLV”, 0x46 0x4c 0x56
2. 版本(1B):目前為0x01
3. 流信息(1B):文件的標志位說明。前5位保留,必須為0;第6位為音頻Tag:1表示有音頻;第七位保留,為0; 第8位為視頻Tag:1表示有視頻
4. Header長度(4B):整個Header的長度,一般為9(版本為0x01時);大於9表示下面還有擴展信息。即0x00000009。
下圖是使用工具FlvAnalyzer獲取到的FLV的Header的詳細信息:
2. 文件體 FLV Body
文件體由一系列的Tag組成。
其中,每個Tag前面還包含了Previous Tag Size字段,表示前面一個Tag的大小。Tag的類型可以是視頻、音頻和Script,每個Tag只能包含以上三種類型的數據中的一種。
下圖是使用FlvAnalyzer獲取到的Body信息:
3. Tag
每個Tag由也是由兩部分組成的:Tag Header和Tag Data。Tag Header里存放的是當前Tag的類型、數據區(Tag Data)長度等信息,具體如下:
Tag類型(1):0x08:音頻; 0x09:視頻; 0x12:腳本; 其他:保留
數據區長度(3):數據區的長度
時間戳(3):整數,單位是毫秒。對於腳本型的tag總是0 (CTS)
時間戳擴展(1):將時間戳擴展為4bytes,代表高8位。很少用到
StreamsID(3):總是0
數據區(由數據區長度決定):數據實體
下面是三個Tag類型說明:
-
Audio Tag Data結構(音頻類型) :音頻Tag Data區域開始的第一個字節包含了音頻數據的參數信息,從第二個字節開始為音頻流數據。
- video Tag Data結構(視頻類型):視頻Tag Data開始的第一個字節包含視頻數據的參數信息,從第二個字節開始為視頻流數據。
-
Script Tag Data結構(腳本類型、幀類型):該類型Tag又被稱為MetaData Tag,存放一些關於FLV視頻和音頻的元信息,比如:duration、width、height等。通常該類型Tag會作為FLV文件的第一個tag,並且只有一個,跟在File Header后。
二、FLV 分析工具
在上節的內容中,我們介紹了FLV的格式信息,同時也提到了FlvAnalyzer工具,下面我們就介紹兩個工具,幫助大家整理和學習FLV相關知識:
1. FlvAnalyzer
通過FlvAnalyzer可以很清晰的看到FLV文件的基本結構,這樣能夠結合上面了解的FLV的知識,更清晰的查看FLV的格式及結構。
工具地址:https://github.com/renhui/Thinking-in-AV/blob/master/多媒體格式/FLV/FlvAnalyzer.exe
工具使用如圖:
左側樹狀結構顯示flv的信息,可以清楚了解flv文件的結構;
點擊左側節點,右側顯示對應hex與ascii信息,這樣就不必打開二進制編輯器了;
通過此工具可以查看audio tag與video tag各個字節(精確到bit)的詳細信息,了解每個tag是如何構造的,同時右下角黑色輸出框顯示某個值的意義;
2. FLV Format Analysis 工具
此工具是雷霄驊整理flvparse的開源代碼,制作的flvformatanalysis工具,此工具可以用來幫助學習FLV封裝格式結構。此外它還支持分離FLV中的視頻流和音頻流。
工具地址:https://github.com/renhui/Thinking-in-AV/blob/master/多媒體格式/FLV/SpecialFFLV.exe
工具使用如圖:
三、FLV格式 與 FFmpeg 實戰
1. 使用FFmpeg生成帶關鍵索引信息的FLV
在網絡視頻點播文件為FLV格式文件時,人們經常用工具先對FLV文件進行一次轉換,主要是將FLV文件中的關鍵幀建立一個索引,並將索引寫到Metadata頭中,這個步驟用FFmpeg可以實現,使用參數add_keyframe_index即可:
ffmpeg -i 好漢歌.mp4 -c copy -f flv -flvflags add_keyframe_index out.flv
生成FLV包含了關鍵幀索引信息,這些關鍵幀索引信息並不是FLV的標准字段,但是我們在實際應用中,特別是現在直播的應用中,我們往往需要向FLV格式中寫入關鍵幀索引,並將這些索引文件寫在Metadata 中,這些我們再次播放的時候,可以很快通過這些關鍵幀索引站到對應的位置,然后准確快速渲染播放。
2. 使用ffprobe查看FLV關鍵幀索引相關信息
除了在第二節介紹的兩個工具,我們也可以使用ffprobe來解析FLV文件,並且還能將關鍵幀索引的相關信息打印出來,命令如下:
ffprobe -v trace -i out.flv
輸出如下:
[NULL @ 0x7fc669002a00] Opening 'out.flv' for reading [file @ 0x7fc667f00480] Setting default whitelist 'file,crypto' Probing flv score:100 size:2048 Probing mp3 score:1 size:2048 [flv @ 0x7fc669002a00] Format flv probed with size=2048 and score=100 [flv @ 0x7fc669002a00] Before avformat_find_stream_info() pos: 13 bytes read:32768 seeks:0 nb_streams:0 [flv @ 0x7fc669002a00] type:18, size:1184, last:-1, dts:0 pos:21 [flv @ 0x7fc669002a00] keyframe stream hasn't been created [flv @ 0x7fc669002a00] type:9, size:45, last:-1, dts:0 pos:1220 [flv @ 0x7fc669002a00] keyframe filepositions = 1296 times = 0 [flv @ 0x7fc669002a00] keyframe filepositions = 159283 times = 3000 [flv @ 0x7fc669002a00] keyframe filepositions = 258004 times = 4000 [flv @ 0x7fc669002a00] keyframe filepositions = 272776 times = 4000 [flv @ 0x7fc669002a00] keyframe filepositions = 405340 times = 6000 [flv @ 0x7fc669002a00] keyframe filepositions = 1215104 times = 16000 [flv @ 0x7fc669002a00] keyframe filepositions = 2529035 times = 26000 [flv @ 0x7fc669002a00] keyframe filepositions = 3198814 times = 36000 [flv @ 0x7fc669002a00] keyframe filepositions = 3623757 times = 41000 [flv @ 0x7fc669002a00] keyframe filepositions = 4882191 times = 51000 [flv @ 0x7fc669002a00] keyframe filepositions = 5951597 times = 61000 [flv @ 0x7fc669002a00] keyframe filepositions = 6256906 times = 63000 [flv @ 0x7fc669002a00] keyframe filepositions = 7235927 times = 73000 [flv @ 0x7fc669002a00] keyframe filepositions = 8175324 times = 83000 [flv @ 0x7fc669002a00] keyframe filepositions = 9203399 times = 93000 [flv @ 0x7fc669002a00] keyframe filepositions = 9936528 times = 103000 [flv @ 0x7fc669002a00] keyframe filepositions = 11056393 times = 113000 [flv @ 0x7fc669002a00] keyframe filepositions = 12183978 times = 123000 [flv @ 0x7fc669002a00] keyframe filepositions = 13014068 times = 133000 [flv @ 0x7fc669002a00] keyframe filepositions = 13610750 times = 143000 [flv @ 0x7fc669002a00] keyframe filepositions = 14628601 times = 153000 [flv @ 0x7fc669002a00] keyframe filepositions = 15873046 times = 163000 [flv @ 0x7fc669002a00] keyframe filepositions = 17112198 times = 173000 [flv @ 0x7fc669002a00] keyframe filepositions = 18301365 times = 182000 [flv @ 0x7fc669002a00] keyframe filepositions = 18604436 times = 186000 [flv @ 0x7fc669002a00] 0 17 0 [flv @ 0x7fc669002a00] type:8, size:9, last:-1, dts:0 pos:1280 [flv @ 0x7fc669002a00] 1 AF 0 [flv @ 0x7fc669002a00] type:9, size:2117, last:-1, dts:0 pos:1304 [flv @ 0x7fc669002a00] 0 17 0 [NULL @ 0x7fc668809e00] nal_unit_type: 7, nal_ref_idc: 3 [NULL @ 0x7fc668809e00] nal_unit_type: 8, nal_ref_idc: 3 [NULL @ 0x7fc668809e00] user data:"x264 - core 142 r2 dd79a61 - H.264/MPEG-4 AVC codec - Copyleft 2003-2014 - http://www.videolan.org/x264.html - options: cabac=1 ref=8 deblock=1:-1:-1 analyse=0x1:0x131 me=umh subme=9 psy=1 psy_rd=1.00:0.15 mixed_ref=1 me_range=24 chroma_me=1 trellis=2 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=0 chroma_qp_offset=-3 threads=24 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 stitchable=1 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=2 b_bias=0 direct=3 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=60 rc=2pass mbtree=1 bitrate=680 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 cplxblur=20.0 qblur=0.5 ip_ratio=1.40 aq=1:1.00" [h264 @ 0x7fc668809e00] nal_unit_type: 7, nal_ref_idc: 3 [h264 @ 0x7fc668809e00] nal_unit_type: 8, nal_ref_idc: 3 [h264 @ 0x7fc668809e00] nal_unit_type: 6, nal_ref_idc: 0 [h264 @ 0x7fc668809e00] nal_unit_type: 5, nal_ref_idc: 3 [h264 @ 0x7fc668809e00] user data:"x264 - core 142 r2 dd79a61 - H.264/MPEG-4 AVC codec - Copyleft 2003-2014 - http://www.videolan.org/x264.html - options: cabac=1 ref=8 deblock=1:-1:-1 analyse=0x1:0x131 me=umh subme=9 psy=1 psy_rd=1.00:0.15 mixed_ref=1 me_range=24 chroma_me=1 trellis=2 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=0 chroma_qp_offset=-3 threads=24 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 stitchable=1 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=2 b_bias=0 direct=3 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=60 rc=2pass mbtree=1 bitrate=680 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 cplxblur=20.0 qblur=0.5 ip_ratio=1.40 aq=1:1.00" [h264 @ 0x7fc668809e00] Reinit context to 576x432, pix_fmt: yuv420p [h264 @ 0x7fc668809e00] no picture [flv @ 0x7fc669002a00] type:9, size:1653, last:-1, dts:40 pos:3436 [flv @ 0x7fc669002a00] 0 27 0
(省略......) [flv @ 0x7fc669002a00] 1 AF 0 [flv @ 0x7fc669002a00] type:9, size:88, last:-1, dts:1600 pos:31870 [flv @ 0x7fc669002a00] 0 27 0 [flv @ 0x7fc669002a00] All info found [flv @ 0x7fc669002a00] stream 0: start_time: 0.080 duration: -9223372036854776.000 [flv @ 0x7fc669002a00] stream 1: start_time: 0.080 duration: -9223372036854776.000 [flv @ 0x7fc669002a00] format: start_time: 0.080 duration: 189.440 bitrate=787 kb/s [flv @ 0x7fc669002a00] After avformat_find_stream_info() pos: 31965 bytes read:32768 seeks:0 frames:74 Input #0, flv, from 'out.flv': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 artist : yinyuetai.com album : Yinyuetai date : 04/01/15 15:51:32 comment : Yinyuetai-1TR1026 encoder : Lavf57.83.100 hasVideo : true hasKeyframes : true hasAudio : true hasMetadata : true canSeekToEnd : true datasize : 18639072 videosize : 16303552 audiosize : 2335015 lasttimestamp : 189 lastkeyframetimestamp: 187 lastkeyframelocation: 18603951 Duration: 00:03:09.44, start: 0.080000, bitrate: 787 kb/s Stream #0:0, 41, 1/1000: Video: h264 (Main), 1 reference frame, yuv420p(progressive, left), 576x432, 0/1, 684 kb/s, 25 fps, 25 tbr, 1k tbn, 50 tbc Stream #0:1, 33, 1/1000: Audio: aac (HE-AAC), 44100 Hz, stereo, fltp, 95 kb/s [h264 @ 0x7fc668824400] nal_unit_type: 7, nal_ref_idc: 3 [h264 @ 0x7fc668824400] nal_unit_type: 8, nal_ref_idc: 3 [AVIOContext @ 0x7fc667f005c0] Statistics: 32768 bytes read, 0 seeks
從以上內容可以看到,輸出信息包含了keyframe關鍵幀存儲在文件中的偏移位置及時間戳。