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 文件结构如下图:
FLV 文件的详细内容结构如下图:
解析流程图
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个字节。
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] | 数据域数据 |
注意:
- flv 文件中 Timestamp 和 TimestampExtended 拼接出来的是 dts。也就是解码时间,单位是毫秒。(如果不存在 B 帧,当然 dts 等于 pts)
- 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 的结构如下所示。
- 第一个 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 对于库的版本
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 |
如果是 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 |
评论