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…