FLV概述
-
FLV(Flash Video)是Adobe公司推出的?種流媒體格式,由于其封裝后的?視頻?件體積?、封裝簡單等特點,?常適合于互聯?上使?。?前主流的視頻?站基本都?持FLV。采?FLV格式封裝的?件后綴為.flv。
-
FLV封裝格式是由?個?件頭(
file header
)和 ?件體(file Body
)組成。其中,FLV body由?對對的(Previous Tag Size字段 + tag)組成。Previous Tag Size字段 排列在Tag之前,占?4個字節。Previous Tag Size記錄了前??個Tag的??,?于逆向讀取處理。FLV header后的第?個Pervious Tag Size的值為0。 -
Tag?般可以分為3種類型:腳本(幀)數據類型、?頻數據類型、視頻數據。FLV數據以?端序進?存儲,在解析時需要注意。
?個標準FLV?件結構如下圖:
FLV?件的詳細內容結構如下圖:
大體的解析框架
FLV header
注:在下?的數據type中,UI表示?符號整形,后?跟的數字表示其?度是多少位。
-
?如UI8,表示?符號整形,?度?個字節。UI24是三個字節,
UI[8*n]
表示多個字節。 -
UB表示位域,UB5表示?個字節的5位。可以參考c中的位域結構體。
-
FLV頭占9個字節,?來標識?件為FLV類型,以及后續存儲的?視頻流。
-
?個FLV?件,每種類型的tag都屬于?個流,也就是?個flv?件最多只有?個?頻流,?個視頻流,不存在多個獨?的?視頻流在?個?件的情況。
FLV頭的結構如下:
Field Type | Comment |
---|---|
UI8 | 簽名 ‘F’ (0x46) |
UI8 | 簽名 ‘L’ (0x4C) |
UI8 | 簽名 ‘V’ (0x56) |
UI8 | FLV 版本。0x01 表示 FLV 版本為 1 |
UB5 | 保留字段,前五位均為 0 |
UB1 | 音頻流標識:1 表示存在音頻流,0 表示不存在 |
UB1 | 保留字段,固定為 0 |
UB1 | 視頻流標識:1 表示存在視頻流,0 表示不存在 |
UI32 | 文件頭大小。 FLV 版本 1 時填寫 9(包括這四個字節),用于后續版本擴展 |
FLV Body
FLV Header
之后,就是FLV File Body
。FLV File Body
是由?連串的back-pointers + tags
構成。Back-pointer
表示Previous Tag Size
(前?個tag的字節數據?度),占4個字節。
FLV Tag
- 每?個Tag也是由兩部分組成:
tag header
和tag data
。 Tag Header
?存放的是當前tag
的類型、數據區(tag data
)的?度等信息。
tag header
tag header
?般占11個字節的內存空間。FLV tag
結構如下:
Field | Type | Comment |
---|---|---|
Tag類型 Type | UI8 | 8: audio ?9: video ?18: Script data(腳本數據) Others: reserved(其他所有值未使用) |
數據區大小 | UI24 | 當前 tag 的數據域的大小,不包含 tag header。 Length of the data in the Data field |
時間戳 Timestamp | UI24 | 當前幀時戳,單位是毫秒。相對值,第一個 tag 的時戳總是為 0 |
時戳擴展字段 TimestampExtended | UI8 | 若時戳大于 0xFFFFFF,將使用該字節。該字節是時戳的高 8 位,前三個字節是低 24 位。 |
StreamID | UI24 | 總是為 0 |
數據域 | UI[8*n] | 數據域數據 |
**注意:
-
flv
?件中Timestamp
和Timestamp Extended
拼出來的是dts
。也就是解碼時間。Timestamp
和Timestamp Extended
拼出來dts
單位為ms
。(如果不存在B
幀,當然dts
等于pts
) -
CompositionTime
表示PTS
相對于DTS
的偏移值, 在每個視頻tag
的第14~16
字節, 顯示時間(pts
) = 解碼時間(tag
的第5~8
字節) +CompositionTime
,CompositionTime
的單位也是ms
-
Script data腳本數據就是描述視頻或?頻的信息的數據,如寬度、?度、時間等等,?個?件中通常只有?個元數據,?頻
tag
和視頻tag
就是?視頻信息了,采樣、聲道、頻率,編碼等信息。
Script Tag Data
結構(腳本類型、幀類型)
該類型Tag?被稱為MetaDataTag,存放?些關于FLV視頻和?頻的元信息,?如:duration
、width
、height
等。通常該類型Tag
會作為FLV
?件的第?個tag
,并且只有?個,跟在File Header
后。該類型Tag Data
的結構如下所示(source.200kbps.768x320.flv?件為例):
1. AMF 的定義與本質
- 全稱:Action Message Format(動作消息格式),是 Adobe 為 Flash 技術棧設計的二進制數據交換格式。
- 作用:在 FLV 中,AMF 包用于封裝腳本數據(對應 FLV 中的
Script Data Tag
,即類型為18
的 Tag),例如視頻元數據、播放控制指令、自定義腳本邏輯數據等。
2. FLV 中 AMF 包的典型應用場景
- 元數據傳輸:
存儲視頻的元信息,如視頻標題、作者、時長、視頻寬高、音頻采樣率等。例如,FLV 文件中常通過 AMF 包傳遞onMetaData
數據,播放器解析這些數據后,可展示視頻相關信息。 - 腳本邏輯交互:
承載 ActionScript 代碼需要的結構化數據,支持復雜對象(如數組、對象嵌套)的傳輸,實現播放流程控制(如跳轉關鍵幀、獲取播放狀態等)。
-
第?個AMF包:第
1
個字節表示AMF包類型,?般總是0x02
,表示字符串。第2-3
個字節為UI16
類型值,標識字符串的?度,?般總是0x000A
(“onMetaData”?度)。后?字節為具體的字符串,?般總為“onMetaData”(6F,6E,4D,65,74,61,44,61,74,61
)。 -
第?個AMF包:第
1
個字節表示AMF包類型,?般總是0x08
,表示數組。第2-5
個字節為UI32
類型值,表示數組元素的個數。后?即為各數組元素的封裝,數組元素為元素名稱和值組成的對。常?的數組元素如下表所示。
值 | Comment | 例如 |
---|---|---|
duration | 時長(秒) | 210.732 |
width | 視頻寬度 | 768.000 |
height | 視頻高度 | 320.000 |
videodatarate | 視頻碼率 | 207.260 |
framerate | 視頻幀率 | 25.000 |
videocodecid | 視頻編碼ID | 7.000 (H264為7) |
audiodatarate | 音頻碼率 | 29.329 |
audiosamplerate | 音頻采樣率 | 44100.000 |
stereo | 是否立體聲 | 1 |
audiocodecid | 音頻編碼ID | 10.000 (AAC為10) |
major_brand | 格式規范相關 | isom |
minor_version | 格式規范相關 | 512 |
compatible_brands | 格式規范相關 | isomiso2avc1mp41 |
encoder | 封裝工具名稱 | Lavf54.63.104 |
filesize | 文件大小(字節) | 6636853.000 |
注:Lavf54.63.104即是 Libavformat version 54.63.104. 即是ffmpeg對于庫的版本
在 AMF 數據結構中,每個數據項(包括鍵值對中的值)的格式都是 字符串名字(2字節)+類型標識(1 字節) + 數據內容。具體來說:
1.字符串名字(2字節)
- 表示每個key的名字,如
duration
等等
1. 類型標識(2 字節)
- 每個數據項的第一個字節固定為 類型標識,用于明確后續數據的格式。例如:
0x02
→ 字符串類型0x00
→ 數值類型(雙精度浮點數)0x01
→ 布爾類型0x03
→ 對象類型- …(其他類型見 AMF 規范)
3. 數據內容
- 根據類型標識的不同,后續數據的格式和長度也不同。例如:
- 字符串類型:
- 第 1 字節:
0x02
- 第 2 - 3 字節:UI16 表示字符串長度(如
0x000A
表示 10 字節) - 后續字節:具體字符(如
onMetaData
共 10 字節)
- 第 1 字節:
- 數值類型(雙精度浮點數):
- 第 1 字節:
0x00
- 后續 8 字節:IEEE 754 雙精度浮點數(如
0x4048000000000000
表示 640.0)
- 第 1 字節:
- 布爾類型:
- 第 1 字節:
0x01
- 第 2 字節:
0x00
(false)或0x01
(true)
- 第 1 字節:
- 字符串類型:
4. 鍵值對的結構
- 在元數據數組中,每個鍵值對的格式為:
- 鍵(字符串):類型標識
0x02
+ 字符串長度 + 字符串內容。 - 值:根據值的類型,以對應類型標識開頭,后跟數據內容。
- 鍵(字符串):類型標識
示例解析
假設元數據數組中有一個鍵值對 "width": 640
,其二進制結構如下:
- 鍵(“width”):
- 字符串長度:2字節
- 類型標識:
0x02
- 長度:
0x0005
(5 字節) - 內容:
77,69,69,6B,74
(ASCII 字符 “width”)
- 類型標識:
- 值(640):
- 類型標識:
0x00
- 雙精度浮點數:
4048000000000000
(對應十進制 640.0)
- 類型標識:
總結
每個數據項(無論是鍵還是值)都嚴格遵循 類型標識 + 數據內容 的格式,解析時只需按順序讀取類型標識,再根據類型讀取對應長度的數據即可
Audio Tag Data結構 (音頻類型)
?頻Tag Data
區域開始的:
- 第?個字節包含了?頻數據的參數信息
- 第?個字節開始為?頻流數據。
(這兩個字節屬于tag的data部分,不是header部分)
第?個字節為?頻的信息(仔細看spec發現對于AAC??,?較有?的字段是SoundFormat),格式如下:
Field | Type | Comment |
---|---|---|
音頻格式 SoundFormat | UB4 | 0 = Linear PCM, platform endian 1 = ADPCM 2 = MP3 3 = Linear PCM, little endian 4 = Nellymoser 16?kHz mono 5 = Nellymoser 8?kHz mono 6 = Nellymoser 7 = G.711 A?law logarithmic PCM 8 = G.711 mu?law logarithmic PCM 9 = reserved 10 = AAC 11 = Speex 14 = MP3 8?Khz 15 = Device?specific sound |
采樣率 SoundRate | UB2 | 0 = 5.5kHz ???1 = 11kHz 2 = 22.05kHz ?3 = 44.1kHz 對于AAC總是3。但實際上AAC是可以支持到48khz以上的頻率(這個參數對于AAC意義不大)。 |
采樣精度 SoundSize | UB1 | 0 = snd8Bit 1 = snd16Bit 此參數僅適用于未壓縮的格式,壓縮后的格式都是將其設為1 |
音頻聲道 SoundType | UB1 | 0 = sndMono 單聲道 1 = sndStereo 立體聲,雙聲道 對于AAC總是1 |
第?個字節開始為?頻數據(需要判斷該數據是真正的音頻數據,還是音頻config信息)
Filed | Type | Comment |
---|---|---|
音頻數據 | UI[8*n] | if SoundFormat == 10 (AAC類型) AAC AUDIO DATA else Sound data—varies by format |
AAC AUDIO DATA
![[Pasted image 20250331203842.png|400]]
如果是AAC數據,如果他是AAC RAW
, tag data[3]
開始才是真正的AAC frame data。
- 配置信息
這兩張表格定義了 AAC 音頻配置信息(AudioSpecificConfig
)及其相關解析邏輯的語法結構,具體解析如下:
Table 1.15 - AudioSpecificConfig() 語法
語法元素 | 位數 | 記憶符 | 說明 |
---|---|---|---|
audioObjectType | - | - | 通過 GetAudioObjectType() 函數獲取,用于標識音頻對象類型(如 AAC 編碼配置)。 |
samplingFrequencyIndex | 4 | bslbf | 采樣率索引,占 4 位。若值為 0xf ,則使用擴展的 samplingFrequency (24 位)。 |
samplingFrequency | 24 | uimsbf | 僅在 samplingFrequencyIndex == 0xf 時出現,存儲具體采樣率數值。 |
channelConfiguration | 4 | bslbf | 聲道配置,占 4 位,標識音頻的聲道數(如單聲道、立體聲等)。 |
sbrPresentFlag /psPresentFlag | - | - | 預留標志位(示例中暫未賦值,實際用于標識 SBR、PS 等擴展功能是否存在)。 |
作用:AudioSpecificConfig()
用于存儲 AAC 音頻的核心配置參數,包括編碼類型、采樣率、聲道數等,是解碼器解析音頻數據的關鍵依據。
Table 1.16 - GetAudioObjectType() 語法
語法元素 | 位數 | 記憶符 | 說明 |
---|---|---|---|
audioObjectType | 5 | uimsbf | 音頻對象類型,占 5 位。若值為 31 ,則通過擴展字段 audioObjectTypeExt 進一步解析。 |
audioObjectTypeExt | 6 | uimsbf | 僅在 audioObjectType == 31 時使用,擴展音頻對象類型(最終值為 32 + audioObjectTypeExt )。 |
作用:GetAudioObjectType()
用于精確解析音頻編碼的具體配置文件(如 AAC LC、HE-AAC 等),通過 5 位基礎值和可能的 6 位擴展值,覆蓋更廣泛的編碼類型。
Video Tag Data結構(視頻類型)
視頻Tag Data開始的:
- 第?個字節包含視頻數據的參數信息,
- 第?個字節開始為視頻流數據。
第?個字節包含視頻信息,格式如下:
Field | Type | Comment |
---|---|---|
幀類型 | UB4 | 1: keyframe (for AVC, a seekable frame)——h264的IDR,關鍵幀 2: inter frame (for AVC, a non-seekable frame)——h264的普通幀 3: disposable inter frame (H.263 only) 4: generated keyframe (reserved for server use only) 5: video info/command frame |
編碼ID | UB4 | 使用哪種編碼類型: 1: JPEG (currently unused) 2: Sorenson H.263 3: Screen video 4: On2 VP6 5: On2 VP6 with alpha channel 6: Screen video version 2 7: AVC |
第?個字節開始為視頻數據 |
Field | Type | Comment |
---|---|---|
視頻數據 | UI[8*n] | If CodecID == 2 H263VIDEOPACKET If CodecID == 3 SCREENVIDEOPACKET If CodecID == 4 VP6FLVIDEOPACKET If CodecID == 5 VP6FLVALPHAVIDEOPACKET If CodecID == 6 SCREENV2VIDEOPACKET if CodecID == 7 (AVC格式) AVCVIDEOPACKET |
AVCVIDEOPACKET
1. AVCPacketType(UI8,無符號 8 位整數)
- 作用:標識 AVC 數據包的類型。
- 取值及含義:
0
:表示 AVC 序列頭(AVC sequence header),通常包含解碼器配置信息(如AVCDecoderConfigurationRecord
)。1
:表示 AVC NALU(網絡抽象層單元),即實際的視頻編碼數據(如視頻幀的切片數據)。2
:表示 AVC 序列結束(AVC end of sequence),此時底層 NALU 序列結束標記可能不需要或不被支持。
2. CompositionTime(SI24,有符號 24 位整數)
- 作用:用于標識視頻幀的合成時間偏移(僅在特定類型下有效)。
- 邏輯:
- 當
AVCPacketType == 1
時,該字段表示 NALU 對應的視頻幀合成時間偏移。 - 其他情況下(
AVCPacketType
為0
或2
),該字段值為0
。
- 當
3. Data(UI8[n]
,無符號 8 位整數數組)
- 作用:存儲不同類型 AVC 數據包的具體數據內容。
- 邏輯:
- 當
AVCPacketType == 0
時,存儲AVCDecoderConfigurationRecord
(解碼器配置記錄,包含編碼參數等信息)。 - 當
AVCPacketType == 1
時,存儲一個或多個 NALU(可以是單個切片,不強制要求完整幀)。 - 當
AVCPacketType == 2
時,該字段為空(Empty
)。
- 當
(1)CompositionTime
- CompositionTime 每個視頻
tag
(整個tag
)的第14~16
字節(如果是tag data偏移位置索引[2]~[4]
)(表示PTS
相對于DTS
的偏移值 )。 - CompositionTime 單位為ms : 顯示時間 = 解碼時間(
tag
的第5~8
字節,位置索引[4]~[7]
)+CompositionTime
(2)AVCDecoderConfigurationRecord
-
AVC sequence header
就是AVCDecoderConfigurationRecord
結構,該結構在標準?檔“ISO-14496-15 AVC file format”
-
video
配置信息
1. AVCDecoderConfigurationRecord
基礎字段
字段名稱 | 字節數 | 說明 |
---|---|---|
configurationVersion | 1 | 配置版本,通常為 1 。 |
AVCProfileIndication | 1 | 指示 H.264 Profile(如 0x66 表示 Baseline Profile)。 |
profile_compatibility | 1 | 兼容性標識。 |
AVCLevelIndication | 1 | 指示 H.264 Level(如 0x1E 表示 Level 3.1)。 |
lengthSizeMinusOne | 1 | NALU 長度字段的字節數減 1(如 3 表示 NALU 長度用 4 字節存儲)。 |
numOfSequenceParameterSets | 1 | SPS 的數量,通常為 1 。 |
2. SPS 數據
sequenceParameterSetLength
:2 字節,標識 SPS 數據的長度。sequenceParameterSetNALUnit
:長度由sequenceParameterSetLength
定義,存放實際的 SPS 字節數據。
3. PPS 數據
numOfPictureParameterSets
:1 字節,PPS 的數量,通常為1
。pictureParameterSetLength
:2 字節,標識 PPS 數據的長度。pictureParameterSetNALUnit
:長度由pictureParameterSetLength
定義,存放實際的 PPS 字節數據。
FLV時間戳計算
題記:時間戳將每?秒分成90000份,即將每?毫秒分成90份 在flv中直接存儲的都是毫秒級,在TS存儲的是時間戳級
- 其中TS、flv?般按照編碼順序排列
- ?個視頻tag?般只包含?幀視頻的碼流
- 其中視頻tag的時間戳對應的是解碼時間戳(DTS/90)
當前序列:
- 編碼順序 I P P B B B…
- 對應幀號 0 1 5 3 2 4…
flv對每?個tag都規定了它將要播放的時間戳,每個時間戳都可以對應轉換特性的時間
-
其中script(腳本)、video(視頻)、audio(?頻)的第?個tag的時間戳值都為0
-
時間戳占4個字節 其中第四個字節是?位 前三個字節是低位(每個tag的5~8字節):如
6E 8D A8 01 = 0x 01 6E 8D A8 = 24022440
-
CompositionTime 每個視頻tag的第14~16字節(共3字節)(表示PTS相對于DTS的偏移值 )
-
CompositionTime 單位為ms 顯示時間 = 解碼時間(tag的第5~8字節(共3字節)) + CompositionTime
例如(注意顯示時間最后?個字節是?位)
- tag0 (腳本) :時間戳為0
- tag1 (視頻) :第?個視頻時間戳 值為0 ?CompositionTime (頭信息)
- tag2 (?頻) :第?個?頻時間戳 值為0
- tag3 (視頻) :00 00 00 00 值:0 00:00:00:00 (解碼時間) CompositionTime:0x 00 00 50 值:80 00:00:00:80 I幀 顯示時間: 00:00:00: 80 poc=0
- tag4 (視頻) :00 00 28 00 值:40 00:00:00:40 (解碼時間) CompositionTime:0x 00 00 50 值:80 00:00:00:80 P幀 顯示時間: 00:00:00: 120 poc=1
- tag5 (視頻) :00 00 50 00 值:80 00:00:00:80 (顯示時間) CompositionTime:0x 00 00 C8 值:200 00:00:00:200 P幀 顯示時間: 00:00:00: 280 poc=5
- tag6 (?頻) :00 00 50 00 值:80 00:00:00:80(顯示時間)
- tag7 (?頻) :00 00 67 00 值:103 00:00:00:103(顯示時間)
- tag8 (視頻) :00 00 78 00 值:120 00:00:00:120 (解碼時間) CompositionTime:0x 00 00 50 值:80 00:00:00:80 B幀 顯示時間: 00:00:00: 200 poc=3
- tag9 (?頻) :00 00 7E 00 值:126 00:00:00:126(顯示時間)
- tag10 (?頻) :00 00 96 00 值:150 00:00:00:150(顯示時間)
- tag11 (視頻) :00 00 A0 00 值:160 00:00:00:160(解碼時間) CompositionTime:0x 00 00 00 值:00 00:00:00:00 b幀 顯示時間: 00:00:00: 160 poc=2
- tag12 (?頻) :00 00 AD 00 值:173 00:00:00:173(顯示時間)
- tag13 (?頻) :00 00 C4 00 值:196 00:00:00:196(顯示時間)
- tag14(視頻) :00 00 C8 00 值:200 00:00:00:200(解碼時間) CompositionTime:0x 00 00 28 值:40 00:00:00:40 b幀 顯示時間: 00:00:00: 240 poc=4 我們可以看到 每個視頻tag相差約40ms 剛好是25fps視頻 每幀視頻的播放時?
在上例中,我們會看到按照解碼時間排列
- 編碼順序
I P P B B B......
- 對應幀號
0 1 5 3 2 4......
更多資料:https://github.com/0voice