Flv封装格式

1,478 阅读7分钟

FLV(Flash Video)是Adobe公司设计开发的一种流行的流媒体格式,由于其视频文件体积轻巧、封装简单等特点,使其很适合在互联网上进行应用。此外,FLV可以使用Flash Player进行播放,而Flash Player插件已经安装在绝大部分浏览器上,这使得通过网页播放FLV视频十分容易。FLV封装格式的文件后缀通常为“.flv”。

FLV整体结构

整体来看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag组成。因此一个FLV文件结构如下图所示:

Flv整体结构
其中,每个Tag前面包含一个Previous Tag Size字段,表示前面一个Tag的大小。Tag的类型可以是视频、音频和Script,每个Tag有且只能是三种类型中的一种。FLV的详细结构如下所示:

Flv详细结构

Flv File Header

Field Type Comment
Signature UI8 Signature byte always 'F' (0x46)
Signature UI8 Signature byte always 'L' (0x4C)
Signature UI8 Signature byte always 'V' (0x56)
Version UI8 File version (for example, 0x01 for FLV version 1)
TypeFlagsReserved UB[5] 0
TypeFlagsAudio UB[1] 1 : Audio Tags are present
TypeFlagsReserved UB[1] 0
TypeFlagsVideo UB[1] 1 : Video Tags are present
DataOffset UI32 The length of this flv file header in bytes
  • Signature:FLV文件的前3个字节固定为FLV,用来标识当前文件是flv格式。若发现前3个字节为“FLV”,就认为它是flv文件。
  • Version:第4个字节表示flv版本号,目前固定为1。
  • Flags:第5个字节中的第0位和第2位(从低位数),分别表示是否存在视频和音频Tag。(1表示存在,0表示不存在)
  • DataOffset:最后4个字节表示FLV File Header的长度,目前固定为00 00 00 09

所以一般情况下,同时包含音频和视频的Flv File Header的16进制(大端模式)为46 4C 56 01 05 00 00 00 09

Flv Tag

Flv的主体是Tag序列,Flv Tag的前11字节是固定的Tag Header,详细结构如下所示:

Field Type Comment
Reserved UB[2] Reserved for FMS, should be 0
Filter UB[1] Indicates if packets are filtered.
0 : No pre-processing required.
1 : Pre-processing (such as decryption) of the packet is required before it can be rendered.
Shall be 0 in unencrypted files, and 1 for encrypted tags.
TagType UB[5] Tag Type , 8 : audio , 9 : video , 18 : script data
DataSize UI24 Length of the Tag Body.
Number of bytes after StreamID to end of Tag (length of tag – 11)
Timestamp UI24 Time in milliseconds at which the data in this tag applies.
This value is relative to the first tag in the FLV file, which always has a timestamp of 0.
TimestampExtended UI8 Extension of the Timestamp field to form a SI32 value. This field represents the upper 8 bits,
while the previous Timestamp field represents the lower 24 bits of the time in milliseconds.
StreamID UI24 Always 0
XXTagHeader AudioTagHeader (TagType == 8)
VideoTagHeader (TagType == 9)
音频Header or 视频Header
Data AudioData(TagType == 8)
VideoData(TagType == 9)
ScriptData(TagType == 18)
Data specific for each media type
  • TagType: Flv Tag第1个字节的低5位表示该Tag的类型,audio:8, video:9, Script:18。
  • DataSize: StreamID之后的数据长度.
  • Timestamp和TimestampExtended组成了这个TAG包数据的PTS信息,真正数据的PTS = Timestamp | TimestampExtended << 24.
  • 从开始到StreamID为止正好是11字节,后面的数据结构则取决于TagType,下面我们一个个的介绍。

Flv Script Tag

Flv File Header之后紧跟的第一个Tag一般是Script Tag,有且只有一个。该类型Tag又通常被称为Metadata Tag,存储一些关于Flv音频和视频的元数据信息,如:duration、width、height等,其结构如下所示:

Script Tag

第一个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类型值,表示数组元素的个数。后面即为各数组元素的封装,数组元素为名称和值组成的Key-Value。常见的数组元素如下所示:

Key Type Value
duration Number 时长
filesize Number 文件大小
width Number 视频帧宽度
height Number 视频帧高度
videodatarate Number 视频码率
framerate Number 视频帧率
videocodecid Number 视频编码方式,如:Avc、Hevc
audiocodecid Number 音频编码方式
audiodatarate Number 音频码率
audiosamplerate Number 音频采样率
audiosamplesize Number 音频采样位数
audiochannels Number 音频单通道 or 双通道
stereo Boolean 是否为立体声,1:立体声(双声道)

有一点特别重要:Script Tag的两个AMF数据是紧跟在Script Tag11字节的Tag Header后面的。

Flv Audio Tag

参考之前Flv Tag的结构,若TagType等于8,则表示当前是音频Tag,StreamID之后的数据就是AudioTagHeader,AudioTagHeader结构如下:

Field Type Comment
SoundFormat UB[4] Format of SoundData. The following values are defined:
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
Formats 7, 8, 14 and 15 are reserved.
AAC is supported in Flash Player 9.0 and higher.
Speex is supported in Flash Player 10 and higher.
SoundRate UB[2] Sampling rate. The following values are defined:
0 : 5.5 kHz
1 : 11 kHz
2 : 22 kHz
3 : 44 kHz
SoundSize UB[1] Size of each audio sample. This parameter only pertains to uncompressed formats.
0 : 8-bit samples
1 : 16-bit samples
SoundType UB[1] Mono or stereo sound
0 : Mono sound
1 : Stereo sound
AACPacketType UI8 (if SoundFormat == 10) What the following values are ?
0 : AAC sequence header
1 : AAC raw

AudioTagHeader的第1个字节,也就是紧跟在StreamID后面的1个字节包含着音频类型、采样率、采样位数、声道等基本信息。 AudioTagHeader之后就是AudioData数据了。但是这里有个特例,如果音频格式(SoundFormat)是10(AAC),AudioTagHeader中会多出1字节的AACPacketType结构,这个字段表示AACAudioData的类型:

  • 0 : AAC sequence header
  • 1 : AAC raw

如果AACPacketType等于0,那么紧跟在AudioTagHeader后面的Data就是AAC sequence header,AAC sequence header包含了AudioSpecificConfig,AudioSpecificConfig包含着一些更加详细的音频信息。 一般情况下,AAC sequence header只会出现1次,而且是第一个Audio Tag。为什么需要这种Tag,因为如果是AAC音频,需要在每帧AAC ES流前面添加7字节的ADST头,这是解码器通用的格式,就是要把AAC的纯ES流打包成ADST格式的AAC文件,解码器才能正常播放。在打包ADST的时候,需要samplingFrequencyIndex信息,而samplingFrequencyIndex最准确的信息就在AudioSpecificConfig中,所以就需要对AudioSpecificConfig进行解析得到samplingFrequencyIndex。

如果AACPacketType等于1,那么紧跟在AudioTagHeader后面的Data就是AAC raw,即音频ES流。

有一点特别重要:Audio Tag的数据是紧跟在Audio Tag11字节的Tag Header后面的。

Flv Video Tag

参考之前Flv Tag的结构,若TagType等于9,则表示当前是视频Tag,StreamID之后的数据就是VideoTagHeader,VideoTagHeader结构如下:

Field Type Comment
Frame Type UB[4] Type of video frame. The following values are defined:
1 : key frame (for AVC, a seekable frame)
2 : inter frame (for AVC, a non-seekable frame)
3 : disposable inter frame (H.263 only)
4 : generated key frame (reserved for server use only)
5 : video info/command frame
CodecID UB[4] Codec Identifier. The following values are defined:
2 : Sorenson H.263
3 : Screen video
4 : On2 VP6
5 : On2 VP6 with alpha channel
6 : Screen video version 2
7 : AVC
AVCPacketType UI8(if CodecID == 7) The following values are defined:
0 : AVC sequence header
1 : AVC NALU
2 : AVC end of sequence (lower level NALU sequence ender is not required or supported)
CompositionTime SI24(if CodecID == 7) IF AVCPacketType == 1
Composition time offset
else
0

VideoTagHeader的第1个字节,也就是紧跟在StreamID后面的1个字节包含着视频帧类型及视频编码信息。 VideoTagHeader之后就是VideoData数据了,当然就像音频AAC一样,这里也有特例:如果视频格式是AVC(H.264),VideoTagHeader中会多出4个字节信息:AVCPacketType和CompositionTime。其中,AVCPacketType表示AVCVideoData的类型:

  • 0 : AVCDecoderConfigurationRecord(AVC sequence header)
  • 1 : One or more NALUs (Full frames are required)
  • 2 : AVC end of sequence

如果AVCPacketType等于0,那么紧跟在VideoTagHeader后面的Data就是AVCDecoderConfigurationRecord,它包含着解码H264至关重要的sps和pps信息,再给AVC解码器送数据流之前一定要把sps和pps信息送出,否则解码器就不能正常解码。AVCDecoderConfigurationRecord在FLV文件中一般情况也只出现1次,也就是第一个Video Tag。

如果AVCPacketType等于1,那么紧跟在VideoTagHeader后面的Data就是NALU了(可能包含多个NALU),NALU存储的是Slice,多个Slice构成一帧图像,一个Video Tag必须至少包含一个完整的帧图像。

有一点特别重要:Video Tag的数据是紧跟在Video Tag11字节的Tag Header后面的。

参考文档

  1. FLV文件格式详解
  2. 视音频编解码学习工程:FLV封装格式分析器