当前位置: 首页 > news >正文

FLV 与 MP4 格式深度剖析:结构、原理

1 FLV格式分析

1.1 定义

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。

在这里插入图片描述

1.2 FLV Header

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,指从文件起始到文件体起始的字节数,方便未来扩展时确定文件体位置

1.3 FLV Body

1.3.2 Previous Tag Size

在 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 则是具体的音视频或脚本数据等内容。

  • 作用

    • 逆向读取:Previous Tag Size 字段(占 4 字节)记录了前一个 Tag 的大小。借助这个信息,程序能够从文件末尾逆向读取,逐一解析每个 Tag。这在某些场景下非常有用,比如需要快速定位到特定时间点的音视频数据时,逆向读取可以提高查找效率。
    • 数据完整性检查:通过比较 Previous Tag Size 字段记录的大小和实际解析出的前一个 Tag 的大小,能够验证数据的完整性。如果两者不一致,可能意味着文件在传输或存储过程中出现了损坏。
  • 与当前 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(以字节为单位)。

1.3.2 FLV Tag

每⼀个Tag也是由两部分组成**:tag header和tag data**。Tag Header⾥存放的是当前tag的类型、数据区(tag data)的⻓度等信息。

Tag Header

字段类型说明
Tag类型UI88表示音频,9表示视频,18表示脚本数据,其他值为预留未用
数据区大小UI24当前tag数据域大小,不包含tag header
时间戳TimestampUI24当前帧时戳,单位毫秒,相对值,首个tag时戳为0
时戳扩展字段TimestampExtendedUI8时戳大于0xFFFFFF时使用,为高8位,与低24位组成完整时戳
StreamIDUI24始终为0
数据域UI[8*n]存放tag实际数据,字节数由“数据区大小”决定

Script Tag Data(脚本数据)
Script Tag Data 也被称为 MetaData Tag,通常作为 FLV 的第一个 Tag 且只有一个,用于存放 FLV 视频和音频的元信息,如 duration(时长)、width(宽度)、height(高度) 等 。其结构由两个 AMF 包组成,具体如下:
第一个 AMF 包

  • 包类型标识:占1字节,一般总是0x02 ,代表字符串类型 。
  • 字符串长度:占2字节(UI16类型 ),一般总是0x000A ,即表示字符串“onMetaData”的长度 。
  • 字符串内容:后续字节为具体字符串,一般为“onMetaData” ,对应的十六进制为6F,6E,4D,65,74,61,44,61,74,61 。 这个包主要用于标识后续数据是关于元信息的描述。

第二个 AMF 包

  • 包类型标识:第1个字节表示AMF包类型,一般总是0x08 ,代表数组类型 。
  • 数组元素个数:第2 - 5个字节为UI32类型值 ,用于表示数组元素的数量 。
  • 数组元素内容: 后续是各数组元素的封装,每个数组元素由元素名称和值组成 。具体表示为:
    • 元素名称长度:用2字节(UI16)表示元素名称的长度,假设为L 。
    • 元素名称:接着是长度为L的字符串,即元素名称 。
    • 元素值类型:第L + 3个字节表示元素值的类型 。
    • 元素值:再后面是对应的值,占用字节数取决于值的类型 。

常见的数组元素及对应含义如下:

元素名称含义示例值
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区域开始的:

  • 第⼀个字节包含了⾳频数据的参数信息,
  • 第⼆个字节开始为⾳频流数据。

第⼀个字节为⾳频的信息

FieldTypeComment
音频格式 SoundFormatUB40 = 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
采样率 SoundRateUB20 = 5.5kHz
1 = 11kHz
2 = 22.05kHz
3 = 44.1kHz
对于AAC总是3。但实际上AAC可支持到48kHz以上的频率(这个参数对于AAC意义不大)
采样精度 SoundSizeUB10 = snd8Bit
1 = snd16Bit
此参数仅适用于未压缩的格式,压缩后的格式都将其设为1
音频声道 SoundTypeUB10 = 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是视频信息/命令帧 。
编码IDUB4用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 == 2H263VIDEOPACKET
If CodecID == 3SCREENVIDEOPACKET
If CodecID == 4VP6FLVIDEOPACKET
If CodecID == 5VP6FLALPHAVIDEOPACKET
If CodecID == 6SCREENV2VIDEOPACKET
If CodecID == 7(AVC格式 )AVCVIDEOPACKET ,后续结构会根据AVC编码规范进一步细分,用于存储视频的具体编码数据 。

1.4 总结

在这里插入图片描述

2 MP4

2.1 MP4 结构

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 用于存放具体的媒体数据,是文件的 “数据仓库”。
在这里插入图片描述

2.2 深入解析关键 Box

在多媒体技术领域,MP4 文件是最常见的存储格式之一。它能将视频、音频、字幕等多种媒体元素整合在一起,实现流畅播放。而这一切的实现,都依赖于其独特的文件结构。MP4 文件采用 “Box” 的嵌套结构来组织数据,每个 Box 都有特定的功能和作用。接下来,我们就对 MP4 文件结构中重要的部分一一进行讲解,并通过示例加深理解。
一、根层级:moov Box
moov Box 是 MP4 文件的 “总指挥部”,存放着整个文件的媒体元数据,几乎所有与媒体轨道相关的关键信息都包含在其内部。它就像是一本书的目录和前言,记录了这本书的整体信息以及各个章节的概要。
moov Box 主要包含两个关键子 Box:

  • mvhd(Movie Header Box):记录全局媒体信息,包括文件的创建时间、修改时间、时间度量标尺(time_scale)、可播放时长等。其中,time_scale是一个非常重要的参数,它定义了时间的基本单位,即 1 秒包含多少个时间刻度。例如,若time_scale为 90000,就表示 1 秒被划分为 90000 个时间刻度。假设一个视频的时长记录为 900000 个刻度,通过计算(900000÷90000),我们就能知道这个视频的时长是 10 秒 。mvhd中的信息是音视频共用的,为整个文件提供了时间基准。
  • trak(Track Box):每个moov Box 中可以包含多个trak,每个trak对应一路独立的媒体轨道,比如一路视频、一路音频,或者一路字幕。以常见的电影视频文件为例,可能会有一个视频轨道用于呈现画面,多个音频轨道用于提供不同语言的配音,以及多个字幕轨道用于显示不同语言的字幕。
    二、轨道层级:trak Box
    trak Box 是媒体轨道的 “专属档案袋”,它内部的结构详细描述了对应媒体轨道的各项属性和数据信息。我们以视频轨道和音频轨道为例进行说明。
    (一)tkhd(Track Header Box)
    tkhd用于定义轨道的基础属性,虽然音频轨道和视频轨道都会用到它,但具体参数有所不同。
  • 视频轨道:包含视频画面的宽度、高度(单位为像素,例如width=1920,height=1080,表示该视频是 1080P 高清视频)、旋转角度(如果视频有旋转效果,会在这里记录旋转角度信息)等视觉相关信息。
  • 音频轨道:侧重于记录采样率(如 44100Hz,表示每秒采集 44100 个音频样本)、声道数(单声道为 1,立体声为 2)、音频时长等声学特性参数 。
    (二)mdia(Media Box)
    mdia Box 是媒体数据的 “信息中心”,它内部包含了mdhd、hdlr和minf等重要子 Box ,从不同方面对媒体数据进行描述和管理。
  • mdhd(Media Header Box):主要存储轨道媒体的时间信息,和mvhd中的时间信息相互配合。其中同样包含time_scale参数,并且还记录了轨道的时间偏移等信息。例如,视频轨道和音频轨道可能会因为编码或制作的原因,在时间上存在微小的偏移,mdhd就可以记录这些偏移量,确保音视频在播放时能够准确同步 。
  • hdlr(Handler Box):指定处理媒体数据的处理器类型,它就像是媒体数据的 “专属翻译”。对于视频流,其handler type可能为 “vide”,表明该视频数据需要由视频解码器来处理;对于音频流,handler type可能是 “soun”,意味着要使用音频解码器来处理此音频数据 。
  • minf(Media Information Box):承载着媒体数据解析所需的核心信息,其中最重要的子 Box 是stbl(Sample Table Box),它负责管理媒体样本的索引、时长、位置等重要元数据。此外,minf还包含dinf(Data Information Box),用于提供媒体数据的来源信息,比如数据是存储在本地文件,还是通过网络传输获取 。
    三、样本管理核心:stbl Box 及其子 Box
    stbl Box 是 MP4 文件中媒体样本管理的 “核心数据库”,它包含的多个子 Box 协同工作,实现对媒体样本的精准定位和高效访问。
    (一)stsd(Sample Description Box)
    stsd详细描述了每个媒体样本(如音频帧或视频帧)的编码格式、尺寸、采样率等关键信息。例如,对于一个 H.264 编码的视频,stsd中会指明编码类型为 “avc1”,并包含 SPS(序列参数集)和 PPS(图像参数集)等编码器配置信息,这些信息是解码器正确解码视频的关键;对于 AAC 编码的音频,stsd会说明编码格式为 “mp4a”,同时给出采样率、声道数等参数 。
    (二)stts(Time to Sample Box)
    stts建立了时间与媒体样本之间的映射关系,以时间戳的形式记录每个样本的持续时间。在一个视频文件中,不同的视频帧可能由于编码方式、内容复杂度等因素,持续时间并不相同。例如,一个视频中,前 10 帧的持续时间可能都是 3 个时间刻度,接下来的 5 帧持续时间为 5 个时间刻度,stts就会精确记录这些信息,播放器根据这些记录就能知道每个视频帧在时间轴上的位置和持续时长,从而实现视频的准确播放 。
    (三)stsc(Sample to Chunk Box)
    stsc将媒体样本组织成块(chunk),定义了每个块包含多少个样本,以及每个块在文件中的起始样本编号。在 MP4 文件中,媒体数据通常不会以单个样本的形式存储,而是多个样本组成一个块进行存储。比如,可能每 10 个视频帧组成一个 chunk,stsc就会记录每个 chunk 包含 10 个样本,以及每个 chunk 对应的起始样本编号,这样可以提高数据读取和处理的效率 。
    (四)stco(Chunk Offset Box)
    stco记录了每个块在文件中的偏移位置。结合stsc提供的块与样本的关系信息,播放器就能快速准确地从文件中定位并读取特定的媒体块。例如,当用户在视频播放过程中拖动进度条时,播放器会根据stco和stsc提供的信息,迅速找到对应时间点的媒体块并开始播放,实现流畅的随机访问 。

2.3 综合示例

假设我们有一个简单的 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实现对音频样本的管理和访问 。

相关文章:

  • 【前端】【业务场景】【面试】在网页开发中,如何优化图片以提高页面加载速度?解决不同设备屏幕适配问题
  • 进阶篇 1:超越基准 - 指数平滑 (ETS) 模型详解
  • http通信之axios vs fecth该如何选择?
  • kubernetes》》k8s》》删除命名空间
  • element-ui cascader 组件源码分享
  • Redis—为何持久化使用子进程
  • dify工作流之text-2-e-sql,大模型写sql并执行
  • 《 C++ 点滴漫谈: 三十四 》从重复到泛型,C++ 函数模板的诞生之路
  • 【C++】vector<bool>特化
  • [二叉树]关于前序、中序、后序、层序序列
  • 【机器学习】决策树算法中的 “黄金指标”:基尼系数深度剖析
  • w~视觉~3D~合集2
  • C# foreach 循环中获取索引的完整方案
  • VIN解析API开发指南:从年检报告构建智能定损系统
  • [创业之路-377]:企业法务 - 有限责任公司与股份有限公司的优缺点对比
  • 【KWDB 创作者计划】KWDB 2.2.0深度解析:架构设计、性能优化与企业级实践全指南
  • Python 爬虫如何伪装 Referer?从随机生成到动态匹配
  • Kotlin集合全解析:List和Map高频操作手册
  • 01-STM32基本知识点和keil5的安装
  • Cyber SpaceGuidance网安学习指南见解
  • 东部战区新闻发言人就美“劳伦斯”号导弹驱逐舰过航台湾海峡发表谈话
  • 展讯:漫游者秦龙和巫鸿的三本书
  • 宁德时代与广汽等五车企发布10款巧克力换电新车型:年内将完成30城1000站计划
  • 重庆市委原常委、政法委原书记陆克华严重违纪违法被开除党籍和公职
  • 五一节,和人民照相馆一起找回“拍照”的仪式感
  • 马上评丨冒名顶替上中专,为何一瞒就是30多年?