Flv格式解析

4,329 阅读7分钟

一、概述Flv用途

即FlashVideo。目前在播放视频、直播时都可以使用。 其中,直播场景下的使用主要有:

  1. 推流时,rtmp协议
  2. 播放时,rtmp和flv over HTTP

点播场景: 兼容性很好,直接播放

二、FLV文件格式

FLV包括文件头(File Header)和文件体(File Body)两部分。文件结构如图所示:

flv文件总体结构

FLV文件头

header部分记录了flv的类型、版本等信息,是flv的开头,一般都差不多,占9bytes。具体格式如下:

  1. 文件标识(3B):总是为”FLV”,0x46 0x4c 0x56
  2. 版本(1B):目前为0x01
  3. 流信息(1B):文件的标志位说明。前5位保留,必须为0;第6位为音频Tag:1表示有音频;第七位保留,为0; 第8位为视频Tag:1表示有视频。一个flv文件里面只能有一路音频流,一路视频流。
  4. Header长度(4B):整个header的长度,一般为9(版本为0x01时);大于9表示下面还有扩展信息。即0x00000009

FLV文件体

文件体由一系列的Tag组成。其中,每个Tag前面还包含了Previous Tag Size字段,表示前面一个Tag的大小。【注意:flv header后面四个字节就是第一个PreviousTagSize,因为前面是header而不是tag,所以,值填写0。】Tag的类型可以是视频、音频和Script,每个Tag只能包含以上三种类型的数据中的一种。

flv文件body一览
flv tag结构

1).Tag

每个Tag由也是由两部分组成的:Tag Header和Tag Data。Tag Header里存放的是当前Tag的类型、数据区(Tag Data)长度等信息,具体如下:

  • Tag类型(1B):0x08:音频; 0x09:视频; 0x12:脚本; 其他:保留
  • 数据区长度(3B):数据区的长度
  • 时间戳(B3):整数,单位是毫秒。对于脚本型的tag总是0 (CTS)
  • 时间戳扩展(1B):将时间戳扩展为4bytes,代表高8位。很少用到
  • StreamsID(3B):总是0
  • 数据区(由数据区长度决定):数据实体
1.1、Audio Tag Data结构(音频Tag).

FLV文件中的第一个音频tag为AudioSpecficConfig(ASC),保存了音频的解码信息。可以参考AAC格式

音频Tag开始的第1个字节包含了音频数据的参数信息,从第2个字节开始为音频流数据。如图为音频Tag结构:

第1个字节的前4位的数值表示了音频编码类型,第5-6位的数值表示音频采样率,第7位表示音频采样精度,第8位表示音频类型。具体格式如下:

从上图可以看出,FLV封装格式支持的采样率只有5.5 kHz/11 kHz/22 kHz/44 kHz这几种,并不支持48KHz的采样率。

1.2、Video Tag Data结构(视频Tag)

视频Tag也用开始的第1个字节包含视频数据的参数信息,从第2个字节为视频流数据。如图为视频Tag结构:

第1个字节的前4位的数值表示帧类型,第1个字节的后4位的数值表示视频编码类型。具体格式如下:

如果视频编码ID=7,即H264/AVC编码标准,可以参考AVCVideoPacket格式

AVCVideoPacket同样包括Packet Header和Packet Body两部分:

Field type Comment
AVC packet类型 1B 0:AVC序列头
1:AVC NALU单元
2:AVC序列结束。低级别avc不需要。
CTS 3B 如果AVC packet类型是1,则为cts偏移(相对时间戳,见时间戳及音画同步;
AVC packet类型为0或2时,则为0
数据 nB 如果AVC packet类型是0,则是解码器配置,sps,pps。
如果是1,则是nalu单元,可以是多个,具体格式:见下面nalu部分。
如果AVCPacketType=0x02,为空

AVCDecorderConfigurationRecord格式

AVCDecoderConfigurationRecord.包含着是H.264解码相关比较重要的sps和pps信息,再给AVC解码器送数据流之前一定要把sps和pps信息送出,否则的话解码器不能正常解码。而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,都需要重新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个video tag。 具体格式如下:

字段 占长度及解释
cfgVersion 8bits
avcProfile 8bits
profileCompatibility 8bits
avcLevel 8bits
reserved 6bits
lengthSizeMinusOne 2bits
reserved 3bits
numOfSPS 5bits
spsLength 16bits
sps n
numOfPPS 8bits
ppsLength 16bits
pps n
1.3、Script Tag Data结构(控制帧)

该类型Tag又通常被称为Metadata Tag,会放一些关于FLV视频和音频的元数据信息如:duration、width、height等。通常该类型Tag会跟在File Header后面作为第一个Tag出现,而且只有一个。结构如图所示:

第一个AMF包: 第1个字节表示AMF包类型,常见的数据类型如下:

  • 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

FLV文件中,第一个字节一般总是0x02,表示字符串。第2-3个字节为UI16类型值,标识字符串的长度,一般总是0x000A(“onMetaData”长度)。后面字节为具体的字符串,一般总为“onMetaData”(6F,6E,4D,65,74,61,44,61,74,61)。

第二个AMF包:

第1个字节表示AMF包类型,一般总是0x08,表示数组。第2-5个字节为UI32类型值,表示数组元素的个数。后面即为各数组元素的封装,数组元素为元素名称和值组成的对。常见的数组元素如下表:

2)、FLV数据分析示例

  1. 0x46 4c 56字符FLV头,固定字符
  2. 0x01:版本,目前为固定字符
  3. 0x05:01表示有视频,04表示有音频,05表示既有视频又有音频。
  4. 0x00 00 00 09:flv包头长度
  5. 0x00 00 00 00 :这个是第1帧的PreviousTagSize0(前帧长度),因为是第一帧,所以肯定是0;
  6. 0x08:帧开头第一字节:0x08表示音频,0x09表示视频,0x12表示脚本信息,放一些关于FLV视频和音频的参数信息,如duration、width、height等。
  7. 0x00 00 04:帧payload长度:因为音频第一帧是ASC(一些音频解码信息),所以只有4字节,是默认长度,有些情况ASC长度会扩展。
  8. 0x 00 00 00 00:timestamp,时间戳
  9. 0x 00 00 00:streamid,流ID,总是0
  10. 0x AF 00 13 90:音频payload: 【这里用0xaf00开头表示后面是asc flag, 用于音频解码的关键信息。以0xaf01开头的tag才是真正的音频数据】0x13 90,也就是二进制0b0001 0011 1001 0000
    ASC flag格式:xxxx xyyy yzzz z000
    x字符: aac type;
    y字符: sample rate, 采样率, 7表示22050采样率
    z字符: 声道数,2是双声道
  11. 0x 00 00 00 0F 这个还是PreviousTagSize1,上一帧长度15bytes
  12. 0x09 视频类型,新的一帧
  13. 0x00 00 22 视频帧payload长度
  14. 0x00 00 0A 00 时间戳
  15. 0x00 00 00,streamid, 流id,总是0。
  16. 0x 17 00 视频帧开头2字节,这是标识这个是AVCDecorderConfigurationRecord,就是视频解码的关键信息。
  17. sps/pps可以参考前面AVCDecorderConfigurationRecord格式
    17 00 00 00 00 01 42 C0 1F FF
    E1 00 0E 67 42 C0 1F 8C 8D 40
    F0 28 90 0F 08 84 6A 01 00 04 68 CE 3C 80

第12, 13字节: 0x00 0E是spslen,也就是14字节长度。跳过14字节后,0x01是pps开始的标识,跳过它。0x00 04是ppslen,也就是4个字节,最后0x68 ce 3c 80就是pps。

三、flv格式图示

以H264和aac编码标准为例

四、开源项目

五、参考