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后的第⼀个Pervious Tag Size的值为0。
FLV头占9个字节,⽤来标识⽂件为FLV类型,以及后续存储的⾳视频流。⼀个FLV⽂件,每种类型的tag都属于⼀个流,也就是⼀个flv⽂件最多只有⼀个⾳频流,⼀个视频流,不存在多个独⽴的⾳视频流在⼀个⽂件的情况。
字段 | 长度 | 说明 |
---|---|---|
签名 | 3 字节 | 固定为 “F”“L”“V”,对应十六进制 0x46、0x4C、0x56,是 FLV 文件重要标识 |
版本 | 1 字节 | 如 0x01 代表 FLV 版本 1,助程序明确格式规范并采用对应解析策略 |
保留字段 | 5 位 | 前 5 位必须为 0,为未来格式扩展预留 |
音频流标识 | 1 位 | 1 表示文件含音频数据,0 表示无音频流 |
保留字段 | 1 位 | 值为 0,为后续功能扩展预留 |
视频流标识 | 1 位 | 1 代表有视频数据,0 代表无视频流 |
文件头大小 | 4 字节 | FLV 版本 1 中通常为 9,指从文件起始到文件体起始的字节数,方便未来扩展时确定文件体位置 |
在 FLV(Flash Video)文件格式里,“Previous Tag” 指的是 FLV 文件体(FLV Body)中,当前 Tag 之前的那个 Tag。为了更清晰地理解它,下面从它的含义、作用、与当前 Tag 的关联等方面详细介绍:
含义
在 FLV 文件的结构中,文件体由一连串的 “Previous Tag Size 字段 + Tag” 组合构成。这里的 “Previous Tag” 就是前一个完整的 “Tag”,它包含了自己的 Tag Header 和 Tag Data 两部分。Tag Header 一般占 11 字节,包含 Tag 类型、数据区大小、时间戳等信息;Tag Data 则是具体的音视频或脚本数据等内容。
作用
与当前 Tag 的关联
在文件中,每个 Tag 前面都有一个 Previous Tag Size 字段,它指向当前 Tag 的前一个 Tag。通过这种方式,文件中的各个 Tag 形成了一个类似链表的结构,程序可以按顺序依次解析每个 Tag。例如,在解析当前 Tag 时,通过读取它前面的 Previous Tag Size 字段,就可以知道前一个 Tag 的大小,从而正确定位到前一个 Tag 的起始位置进行解析。
示例说明
假设 FLV 文件体中有连续的两个 Tag:Tag1 和 Tag2。在解析 Tag2 时,会先读取 Tag2 前面的 Previous Tag Size 字段,这个字段的值就是 Tag1 的大小。通过这个值,程序可以准确找到 Tag1 的起始位置,进而对 Tag1 进行解析。如果 Tag1 的大小是 500 字节,那么 Previous Tag Size 字段的值就是 500(以字节为单位)。
每⼀个Tag也是由两部分组成**:tag header和tag data**。Tag Header⾥存放的是当前tag的类型、数据区(tag data)的⻓度等信息。
Tag Header
字段 | 类型 | 说明 |
---|---|---|
Tag类型 | UI8 | 8表示音频,9表示视频,18表示脚本数据,其他值为预留未用 |
数据区大小 | UI24 | 当前tag数据域大小,不包含tag header |
时间戳Timestamp | UI24 | 当前帧时戳,单位毫秒,相对值,首个tag时戳为0 |
时戳扩展字段TimestampExtended | UI8 | 时戳大于0xFFFFFF时使用,为高8位,与低24位组成完整时戳 |
StreamID | UI24 | 始终为0 |
数据域 | UI[8*n] | 存放tag实际数据,字节数由“数据区大小”决定 |
Script Tag Data(脚本数据)
Script Tag Data 也被称为 MetaData Tag,通常作为 FLV 的第一个 Tag 且只有一个,用于存放 FLV 视频和音频的元信息,如 duration(时长)、width(宽度)、height(高度) 等 。其结构由两个 AMF 包组成,具体如下:
第一个 AMF 包
第二个 AMF 包
常见的数组元素及对应含义如下:
元素名称 | 含义 | 示例值 |
---|---|---|
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 ) |
在 FLV 文件的视频 Tag 中,Timestamp(3 字节 )和 TimestampExtended(1 字节 )共同构成解码时间戳(DTS),单位为 ms ;CompositionTime 表示显示时间戳(PTS)相对于解码时间戳(DTS)的偏移值 ,位于每个视频 tag 的第 14 - 16 字节 ,通过 “显示时间 (pts) = 解码时间(tag 的第 5 - 8 字节) + CompositionTime” 公式来计算最终用于播放显示的时间,从公式及相关原理可知,其单位与其他时间参数统一,为 ms 。
Script data脚本数据就是描述视频或⾳频的信息的数据,如宽度、⾼度、时间等等,⼀个⽂件中通常只有⼀个元数据,⾳频tag和视频tag就是⾳视频信息了,采样、声道、频率,编码等信息。
Audio Tag Data结构(⾳频类型)
⾳频Tag Data区域开始的:
第⼀个字节为⾳频的信息
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可支持到48kHz以上的频率(这个参数对于AAC意义不大) |
采样精度 SoundSize | UB1 | 0 = snd8Bit 1 = snd16Bit 此参数仅适用于未压缩的格式,压缩后的格式都将其设为1 |
音频声道 SoundType | UB1 | 0 = sndMono 单声道 1 = sndStereo 立体声,双声道 对于AAC总是1 |
第⼆个字节开始为⾳频数据(需要判断该数据是真正的⾳频数据,还是⾳频config信息)
若AACPacketType为0 ,表示这部分数据是AAC sequence header ,存放的是AudioSpecificConfig结构(在“ISO - 14496 - 3 Audio”中有相关描述 ),属于音频配置信息,用于告知解码器如何解码后续的AAC音频数据。
若AACPacketType为1 ,则第二个字节开始直接就是AAC原始帧数据(Raw AAC frame data ),可直接进行解码播放等处理 。 对于其他非AAC格式的音频,这部分数据则依据其对应的音频格式规范进行组织和存储 。
AAC 原始帧数据(Raw AAC frame data )
- 定义:指经过 AAC 编码后,未添加额外传输或配置相关头部信息的纯粹音频编码数据 。它是 AAC 音频内容的核心部分,包含了实际用于还原声音的编码采样点等信息 。
- 作用:是音频解码的直接对象,解码器根据 AAC 编码规则对其进行处理,将编码数据转换为可播放的音频信号 。但单独的原始帧数据缺少一些播放控制和格式说明等关键信息,通常不能直接被播放器识别播放
Video Tag Data结构(视频类型)
这张表格介绍了FLV格式中视频标签(Video Tag)相关结构:
视频标签首字节结构
字段 | 类型 | 说明 |
---|---|---|
帧类型 | UB4 | 用4位无符号整数表示。1代表关键帧(对于AVC编码,等同于h264的IDR帧,可用于随机访问 );2代表普通帧(对于AVC编码,是不可随机访问的帧 );3是仅H.263有的可丢弃普通帧 ;4是仅供服务器使用的生成关键帧 ;5是视频信息/命令帧 。 |
编码ID | UB4 | 用4位无符号整数表示编码类型。1为JPEG(目前未使用 );2是Sorenson H.263 ;3是Screen video ;4是On2 VP6 ;5是带alpha通道的On2 VP6 ;6是Screen video version 2 ;7是AVC 。 |
视频流数据
视频标签首字节之后是视频数据部分,视频数据的结构根据编码ID不同而有差异:
条件 | 视频数据结构 |
---|---|
If CodecID == 2 | H263VIDEOPACKET |
If CodecID == 3 | SCREENVIDEOPACKET |
If CodecID == 4 | VP6FLVIDEOPACKET |
If CodecID == 5 | VP6FLALPHAVIDEOPACKET |
If CodecID == 6 | SCREENV2VIDEOPACKET |
If CodecID == 7(AVC格式 ) | AVCVIDEOPACKET ,后续结构会根据AVC编码规范进一步细分,用于存储视频的具体编码数据 。 |
MP4 文件格式基础
MP4 文件格式,正式名称为 MPEG-4 Part 14,源自 MPEG-4 标准第 14 部分。它是一种多媒体格式容器,就像是一个多功能的收纳盒,可以把视频、音频数据流、海报、字幕以及元数据等各种多媒体元素整合在一起。当下流行的视频编码格式 AVC/H264 就定义在 MPEG-4 Part 10 中,这也从侧面反映了 MP4 格式强大的兼容性和广泛的应用场景。而且,MP4 文件格式是基于 Apple 公司的 QuickTime 格式发展而来的,所以 QuickTime File Format Specification 是研究 MP4 的重要参考资料。
MP4 文件的基本结构 ——Box 的世界
MP4 文件的基本组成单元是 Box,整个文件就像是由各种各样 Box 搭建起来的 “积木城堡”,这些 Box 有父 Box,也有子 Box,它们相互嵌套,形成了复杂而有序的结构。每个 Box 都分为 Header 和 Data 两部分,Header 部分包含 Box 的类型和大小信息,Data 部分则存放着子 Box 或者具体的数据。
比如,在一个典型的 MP4 文件中,常见的 Box 有 ftyp、moov、mdat 等。ftyp Box 一般位于文件开头,它描述了文件的版本、兼容协议等信息,就像是文件的 “身份铭牌”;moov Box 则包含了文件中所有媒体数据的宏观描述信息以及每路媒体轨道的具体信息,是文件的 “信息中枢”;mdat Box 用于存放具体的媒体数据,是文件的 “数据仓库”。
在多媒体技术领域,MP4 文件是最常见的存储格式之一。它能将视频、音频、字幕等多种媒体元素整合在一起,实现流畅播放。而这一切的实现,都依赖于其独特的文件结构。MP4 文件采用 “Box” 的嵌套结构来组织数据,每个 Box 都有特定的功能和作用。接下来,我们就对 MP4 文件结构中重要的部分一一进行讲解,并通过示例加深理解。
一、根层级:moov Box
moov Box 是 MP4 文件的 “总指挥部”,存放着整个文件的媒体元数据,几乎所有与媒体轨道相关的关键信息都包含在其内部。它就像是一本书的目录和前言,记录了这本书的整体信息以及各个章节的概要。
moov Box 主要包含两个关键子 Box:
假设我们有一个简单的 MP4 视频文件,它包含一路视频轨道和一路音频轨道。打开这个文件,在moov Box 中,mvhd记录了文件的创建时间为 2024 年 1 月 1 日,time_scale为 90000,总时长为 1800000 个刻度(即 20 秒);trak中有两个,分别对应视频和音频轨道。
在视频轨道的tkhd中,记录了视频的宽度为 1280 像素,高度为 720 像素;mdia中的hdlr指定了视频的处理器类型为 “vide”;stbl中的stsd表明视频采用 H.264 编码,stts记录了每个视频帧的持续时间,stsc和stco则帮助播放器定位和读取视频数据块。
音频轨道的tkhd记录了采样率为 44100Hz,声道数为 2;mdia中的hdlr指定音频的处理器类型为 “soun”;stbl中的stsd说明了音频采用 AAC 编码,同样通过stts、stsc和stco实现对音频样本的管理和访问 。