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 后的第一个 Previous Tag Size 值为0。

Tag 一般可以分为三种类型:脚本(帧数)据类型、音频数据类型、视频数据。FLV 数据以大小端序进行存储,在解析时需要注意。一个标准 FLV 文件结构如下图:

image.png

FLV 文件的详细内容结构如下图:

image.png

解析流程图

image.png

FLV header

在下面的数据 type 中,UI 表示无符号整形,后面跟着的数字表示其长度是多少位。比如 UI8表示无符号整型长度为一个字节。UI24是三个字节。UB 表示位域,UB5表示一个字节的5位。(和 C 的结构体中的差不多)
FLV 头占9个字节,用来标识文件为 FLV 类型,以及后续存储的音视频流。一个 FLV 文件,每种 tag 都属于一个流,也就是一个 flv 文件最多只有一个音频流,一个视频流,不存在多个独立的音视频流在一个文件的情况。

FLV 头的结构如下:

Field Type Comment
签名 UI8 ‘F’ (0x64)
签名 UI8 ‘L’ (0x4c)
签名 UI8 ‘V’ (0x56)
版本 UI8 FLV 版本(0x01表示 FLV 版本为1)
保留字段 UB5 前五位都是0
音频流标识 UB1 是否存在音频流
保留字段 UB1 0
视频流标识 UB1 是否存在视频流
文件头大小 UI32 FLV 版本1时填写9,表明是 FLV 头的大小,为后期的 FLV 版本扩展使用。包括这四个字节。数据的起始位置就是从文件开头偏移这么多大小。

FLV Body

FLV Header 之后,就是 FLV FIle Body。FLV File Body 是由一连串的 back-pointers + tags 构成。-pointer 表示 Previous Tag Size(前一个 tag 的字节数据长度),占4个字节。

image.png

FLV Tag

每一个 Tag 也是由两个部分组成:tag header 和 tag data。Tag Header 里存放的是当前 tag 的类型、数据区的长度信息。

tag header

tag header 一般占11个字节的内存空间。FLV tag 结构如下:

Field Type Comment
Tag 类型 UI8 8:audio
9:video
18:script data
other:其他所有值未使用
数据区大小 UI24 当前 tag 的数据域大小,不包含 tag header。
时间戳 Timestamp UI24 当前帧时间戳,单位是毫秒。相对值,第一个 tag 的时间戳总是为0。
时间戳扩展字段 TimestampExtend UI8 如果时间戳大于0xFFFFFF,将会使用这个字节。这个字节是时间戳的高八位,上面的三个字节是低24位。
StreamID UI24 总是为0
数据域 UI[8*n] 数据域数据

注意:

  1. flv 文件中 Timestamp 和 TimestampExtended 拼接出来的是 dts。也就是解码时间,单位是毫秒。(如果不存在 B 帧,当然 dts 等于 pts)
  2. Composition Time 表示 PTS 相对于 DTS 的偏移,在每个视频 tag 的第14-16字节,显示时间(pts)=解码时间(tag 的第5-8字节)+CompositionTime。

Script data 脚本数据就是描述视频或音频的信息的数据,如宽度、高度和时间等。一个文件中通常只有一个元数据,音频 tag 和视频 tag 就是音视频信息了,采样、声道、频率,编码等信息。

Script Tag Data 结构

该类型 Tag 又被称为 MetaData Tag,存放一些关于 FLV 视频和音频的元信息,比如:duration、width、height 等。通常该类型 Tag 会作为 FLV 文件的第一个 tag,并且只有一个,跟在 File Header 后。该类型 Tag Data 的结构如下所示。

image.png

  • 第一个 AMF 包:第1个字节表示 AMF 包类型,一般总是0x02,表示字符串。第2-3个字节为 UI16类型值,标识字符串的长度,一般总是0x000A(“onMetaData”长度)。后面字节为具体的字符串,一般总为“onMetaData”。
  • 第二个 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是 Lib avf ormat version 54.63.104,即是 ffmpeg 对于库的版本

image.png

image.png

Audio Tag Data 结构(音频类型)

音频 Tag Data 区域开始的:

  • 第一个字节包含了音频数据的参数信息
  • 第二个字节开始为音频数据流
    这两个字节属于tag的data部分,不是header部分

第一个字节为音频的信息,格式如下:

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 可以支持到46kHz 以上的频率(这个参数对 AAC 意义不大)
采样精度
SoundSize
UB1 0 = snd8Bit
1 = snd16Bit
这个参数只适合未压缩的格式,压缩后的格式都是1
音频声道
SoundType
UB1 0 = sndMono 单声道
1 = sndStereo 立体声,双声道
对于 AAC 总是1

第二个字节开始为音频数据(需要判断该数据是真的音频数据,还是音频的 config 信息)

Field Type Comment
音频数据 UI[8*n] if SoundFormat == 10 (AAC 类型)
AACAUDIODATA
else
Sound data-varies by format

image.png

如果是 AAC 数据,如果他是 AAC RAW,tag data[3]开始才是真正的 AAC frame data。

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 (H264 only)
4. generated keyframe (reserved for server use only)
5. video info/command frame
编码 ID UB4 使用哪种编码类型:
1. JPEG (currently unused)
2. Sorenson H263
3. Screen video
4. On2 VP6
5. On2 VP6 with alpha channel
6. Screen video version2
7. AVC

第二个字节开始为视频数据:

Field Type Comment
视频数据 UI[8*n] if CodecID == 2
H263VIDEOPACKET
if CodecID == 3
SCRRENVIDEOPACKET
if CodecID == 4
VP6FLVVIDEOPACKET
if CodecID == 5
VP6FLVALPHAVIDEOPACKET
if CodecID == 6
SCREENV2VIDEOPACKET
if CodecID == 7 (AVC)
AVCVIDEOPACKET

image.png