FLV(Flash Video)是一種流媒體格式,因其體積小、協議相對簡單,很快便流行開來,並獲得普遍的支持。php
常見的HTTP-FLV直播協議,就是使用HTTP流式傳輸經過FLV封裝的音視頻數據。對想要了解HTTP-FLV的同窗來講,瞭解FLV協議頗有必要。ios
歸納地說,FLV 由 FLV header 跟 FLV file body 兩部分組成,而 FLV file body 又由多個 FLV tag組成。數組
FLV = FLV header + FLV file body FLV file body = PreviousTagSize0 + Tag1 + PreviousTagSize1 + Tag2 + ... + PreviousTagSizeN-1 + TagNbash
FLV tag又分爲3種類型:less
在實際講解FLV協議前,首先對單位進行約定:ide
類型 | 定義 |
---|---|
0x... | 16進制數據 |
SI8 | 有符號8位整數 |
SI16 | 有符號16位整數 |
SI24 | 有符號24位整數 |
SI32 | 有符號32位整數 |
STRING | Sequence of Unicode 8-bit characters (UTF-8), terminated with 0x00 (unless otherwise specified) |
UI8 | 無符號8位整數 |
UI16 | 無符號16位整數 |
UI24 | 無符號24位整數 |
UI32 | 無符號32位整數 |
xxx [ ] | 類型爲xxx的數組 |
xxx [n] | 類型爲xxx的數組,數組長度爲n |
FLV header由以下字段組成,其中:學習
字段 | 字段類型 | 字段含義 |
---|---|---|
Signature | UI8 | 簽名,固定爲'F' (0x46) |
Signature | UI8 | 簽名,固定爲'L' (0x4c) |
Signature | UI8 | 簽名,固定爲'V' (0x56) |
Version | UI8 | 版本,好比 0x01 表示 FLV 版本 1 |
TypeFlagsReserved | UB[5] | 全爲0 |
TypeFlagsAudio | UB[1] | 1表示有audio tag,0表示沒有 |
TypeFlagsReserved | UB[1] | 全爲0 |
TypeFlagsVideo | UB[1] | 1表示有video tag,0表示沒有 |
DataOffset | UI32 | FLV header的大小,單位是字節 |
FLV file body頗有規律,由一系列的TagSize和Tag組成,其中:ui
字段 | 字段類型 | 字段含義 |
---|---|---|
PreviousTagSize0 | UI32 | 老是0 |
Tag1 | FLVTAG | 第1個tag |
PreviousTagSize1 | UI32 | 前一個tag的大小,包括tag header |
Tag2 | FLVTAG | 第2個tag |
... | ... | ... |
PreviousTagSizeN-1 | UI32 | 第N-1個tag的大小 |
TagN | FLVTAG | 第N個tag |
PreviousTagSizeN | UI32 | 第N個tag的大小,包含tag header |
FLV tag由 tag header + tag body組成。this
tag header以下,總共佔據11個字節:編碼
字段 | 字段類型 | 字段含義 |
---|---|---|
TagType | UI8 | tag類型 8:audio 9:video 18:script data 其餘:保留 |
DataSize | UI24 | tag body的大小 |
Timestamp | UI24 | 相對於第一個tag的時間戳(單位是毫秒) 第一個tag的Timestamp爲0 |
TimestampExtended | UI8 | 時間戳的擴展字段,當 Timestamp 3個字節不夠時,會啓用這個字段,表明高8位 |
StreamID | UI24 | 老是0 |
Data | 取決於根據TagType | TagType=8,則爲AUDIODATA TagType=9,則爲VIDEODATA TagType=18,則爲SCRIPTDATAOBJECT |
In playback, the time sequencing of FLV tags depends on the FLV timestamps only. Any timing mechanisms built into the payload data format are ignored.
定義以下所示:
字段 | 字段類型 | 字段含義 |
---|---|---|
SoundFormat | UB[4] | 音頻格式,重點關注 **10 = AAC ** 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 | UB[2] | 採樣率,對AAC來講,永遠等於3 0 = 5.5-kHz 1 = 11-kHz 2 = 22-kHz 3 = 44-kHz |
SoundSize | UB[1] | 採樣精度,對於壓縮過的音頻,永遠是16位 0 = snd8Bit 1 = snd16Bit |
SoundType | UB[1] | 聲道類型,對Nellymoser來講,永遠是單聲道;對AAC來講,永遠是雙聲道; 0 = sndMono 單聲道 1 = sndStereo 雙聲道 |
SoundData | UI8[size of sound data] | 若是是AAC,則爲 AACAUDIODATA; 其餘請參考規範; |
備註:
If the SoundFormat indicates AAC, the SoundType should be set to 1 (stereo) and the SoundRate should be set to 3 (44 kHz). However, this does not mean that AAC audio in FLV is always stereo, 44 kHz data. Instead, the Flash Player ignores these values and extracts the channel and sample rate data is encoded in the AAC bitstream.
當 SoundFormat 爲10時,表示音頻採AAC進行編碼,此時,SoundData的定義以下:
字段 | 字段類型 | 字段含義 |
---|---|---|
AACPacketType | UI8 | 0: AAC sequence header 1: AAC raw |
Data | UI8[n] | 若是AACPacketType爲0,則爲AudioSpecificConfig 若是AACPacketType爲1,則爲AAC幀數據 |
The AudioSpecificConfig is explained in ISO 14496-3. Note that it is not the same as the contents of the esds box from an MP4/F4V file. This structure is more deeply embedded.
僞代碼以下:參考這裏
5 bits: object type
if (object type == 31)
6 bits + 32: object type
4 bits: frequency index
if (frequency index == 15)
24 bits: frequency
4 bits: channel configuration
var bits: AOT Specific Config
複製代碼
定義以下:
字段 | 字段類型 | 字段含義 |
---|---|---|
AudioObjectType | UB[5] | 編碼器類型,好比2表示AAC-LC |
SamplingFrequencyIndex | UB[4] | 採樣率索引值,好比4表示44100 |
SamplingFrequencyIndex | UB[4] | 採樣率索引值,好比4表示44100 |
ChannelConfiguration | UB[4] | 聲道配置,好比2表明雙聲道,front-left, front-right |
定義以下:
字段 | 字段類型 | 字段含義 |
---|---|---|
FrameType | UB[4] | 重點關注一、2: 1: keyframe (for AVC, a seekable frame) —— 即H.264的IDR幀; 2: inter frame (for AVC, a non- seekable frame) —— H.264的普通I幀; 3: disposable inter frame (H.263 only) 4: generated keyframe (reserved for server use only) 5: video info/command frame |
CodecID | UB[4] | 編解碼器,主要關注 7(AVC) 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 |
VideoData | 取決於CodecID | 實際的媒體類型,主要關注 7:AVCVIDEOPACKE 2: H263VIDEOPACKET 3: SCREENVIDEOPACKET 4: VP6FLVVIDEOPACKET 5: VP6FLVALPHAVIDEOPACKET 6: SCREENV2VIDEOPACKET 7: AVCVIDEOPACKE |
當 CodecID 爲 7 時,VideoData 爲 AVCVIDEOPACKE,也即 H.264媒體數據。
AVCVIDEOPACKE 的定義以下:
字段 | 字段類型 | 字段含義 |
---|---|---|
AVCPacketType | UI8 | 0: AVC sequence header 1: AVC NALU 2: AVC end of sequence |
CompositionTime | SI24 | 若是AVCPacketType=1,則爲時間cts偏移量;不然,爲0 |
Data | UI8[n] | 一、若是若是AVCPacketType=1,則爲AVCDecoderConfigurationRecord 二、若是AVCPacketType=1=2,則爲NALU(一個或多個) 三、若是AVCPacketType=2,則爲空 |
這裏有幾點稍微解釋下:
PPS、SPS這裏先不展開。
Script Data Tags一般用來存放跟FLV中音視頻相關的元數據信息(onMetaData),好比時長、長度、寬度等。它的定義相對複雜些,採用AMF(Action Message Format)封裝了一系列數據類型,好比字符串、數值、數組等。
字段 | 字段類型 | 字段含義 |
---|---|---|
Objects | SCRIPTDATAOBJECT[] | 任意數目的 SCRIPTDATAOBJECT |
SCRIPTDATAOBJECTEND | UI24 | 永遠是9,標識着Script Data的結束 |
SCRIPTDATAOBJECT 定義以下:
字段 | 字段類型 | 字段含義 |
---|---|---|
ObjectName | SCRIPTDATASTRING | 對象的名字 |
ObjectData | SCRIPTDATAVALUE | 對象的值 |
SCRIPTDATAVALUE 的定義以下:
字段 | 字段類型 | 字段含義 |
---|---|---|
Type | SCRIPTDATASTRING | 變量類型: 0 = Number type 1 = Boolean type 2 = String type 3 = Object type 4 = MovieClip type 5 = Null type 6 = Undefined type 7 = Reference type 8 = ECMA array type 10 = Strict array type 11 = Date type 12 = Long string type |
ECMAArrayLength | 若是Type爲8(數組),則爲UI32 | 數組長度 |
ScriptDataValue | If Type == 0 DOUBLE If Type == 1 UI8 If Type == 2 SCRIPTDATASTRING ...(有點長,能夠參考規範) |
變量的值 |
ScriptDataValueTerminator | 若是Type==3,則爲SCRIPTDATAOBJECTEND 若是 Type==8,則爲SCRIPTDATAVARIABLEEND |
Object、Array的結束符 |
能夠看到,Script Data Tag 的定義相對複雜,下面經過onMetaData進行進一步講解。
onMetaData中包含了音視頻相關的元數據,封裝在Script Data Tag中,它包含了兩個AMF。
第一個AMF:
第二個AMF:
更多onMetaData字段的定義:
字段 | 字段類型 | 字段含義 |
---|---|---|
duration | DOUBLE | 文件的時長 |
width | DOUBLE | 視頻寬度(px) |
height | DOUBLE | 視頻高度(px) |
videodatarate | DOUBLE | 視頻比特率(kb/s) |
framerate | DOUBLE | 視頻幀率(幀/s) |
videocodecid | DOUBLE | 視頻編解碼器ID(參考Video Tag) |
audiosamplerate | DOUBLE | 音頻採樣率 |
audiosamplesize | DOUBLE | 音頻採樣精度(參考Audio Tag) |
stereo | BOOL | 是否立體聲 |
audiocodecid | DOUBLE | 音頻編解碼器ID(參考Audio Tag) |
filesize | DOUBLE | 文件總得大小(字節) |
FLV協議自己不算複雜,理解上的困難,更多時候來自音視頻編解碼相關的知識,好比H.26四、AAC相關知識,建議不懂的時候自行查下。此外,FLV的字節序爲大端序,在作協議解析的時候必定要注意。
本文爲講解方便,部份內容可能不夠嚴謹,若有錯漏敬請指出。
video_file_format_spec_v10.pdf www.adobe.com/content/dam…
MPEG-4 Part 3 en.wikipedia.org/wiki/MPEG-4…
flv文件分析 www.jianshu.com/p/e290dca02…
H.264再學習 -- 詳解 H.264 NALU語法結構 blog.csdn.net/qq_29350001…