《Rust MP4视频技术开发》第七章:MP4文件的分片
一、分片相关盒(moof/traf/trun)详细参数说明
分片 MP4(Fragmented MP4,简称 fMP4)是专为流媒体传输设计的格式,核心是将完整视频拆分为多个独立 “分片(Fragment)”,每个分片包含 “元数据(moof)+ 媒体数据(mdat)”,支持 “边下载边播放”(无需等待整个文件下载完成)。以下是分片核心盒子的详细参数、数据结构及流媒体适配逻辑:
1. moof(Movie Fragment Box,电影片段盒)
核心定位:
每个分片的 “迷你元数据容器”,类似完整 MP4 中的moov,但仅存储当前分片的局部元数据,而非全局信息。一个分片对应一个moof盒,与一个mdat盒(该分片的媒体数据)成对出现。
关键参数:
- 无直接参数,核心作用是承载分片内的子盒(
mfhd、traf),将分片的元数据组织成结构化单元。
数据结构(简化):
moof
├─ mfhd(分片头盒,必需)
└─ traf(轨道片段盒,至少1个,对应每个轨道的分片)
├─ tfhd(轨道片段头盒,必需)
└─ trun(样本运行盒,可选但常用)
实际作用:
- 作为分片的 “元数据外壳”,将分片的序号、轨道参数、样本信息封装在一起,方便播放器按分片粒度解析;
- 与后续的
mdat盒绑定,形成 “分片元数据 + 分片数据” 的独立单元,支持下载一个分片就播放一个分片。
2. mfhd(Movie Fragment Header Box,电影片段头盒)
核心定位:
moof的核心子盒,负责标识分片的顺序,确保播放器按正确顺序拼接分片(避免播放错乱,如分片 2 在分片 1 之前播放)。
关键参数:
sequence_number(分片序列号):32 位整数,从 1 开始递增(如第 1 个分片序号 = 1,第 2 个 = 2,以此类推)。
数据结构(简化):
| 字段名 | 类型 | 示例值 | 说明 |
|---|---|---|---|
version |
u8 | 0 | 盒子版本,通常为 0 |
flags |
u32 | 0 | 标志位,无特殊含义时为 0 |
sequence_number |
u32 | 5 | 第 5 个分片 |
实际作用:
- 播放器下载分片后,通过
sequence_number排序(如按 1→2→3→… 的顺序),再拼接播放; - 若网络传输中分片丢失(如缺失序号 3),播放器可暂停播放并请求重传,或跳过丢失分片(根据容错策略),保证播放连续性。
3. traf(Track Fragment Box,轨道片段盒)
核心定位:
moof的子盒,对应单个轨道的分片(如视频轨的第 5 个分片、音频轨的第 5 个分片)。一个moof中会有多个traf盒(与轨道数量一致),分别管理不同轨道的分片数据。
关键参数:
- 无直接参数,核心作用是承载轨道分片的子盒(
tfhd、trun),将单个轨道分片的元数据组织成单元。
数据结构(简化):
plaintext
traf
├─ tfhd(轨道片段头盒,必需)
├─ trun(样本运行盒,可选但常用)
└─ 其他可选子盒(如tfdt、uuid等,用于时间戳、扩展信息)
实际作用:
- 隔离不同轨道的分片数据(如视频分片和音频分片分开管理),避免轨道信息混淆;
- 每个
traf仅关联当前轨道的一个分片,播放器可独立解析音 / 视频轨道的分片,再通过时间戳同步播放。
4. tfhd(Track Fragment Header Box,轨道片段头盒)
核心定位:
traf的核心子盒,记录轨道分片的基础配置,包括该分片对应的 “母轨道”(完整轨道)ID、样本默认参数(如大小、偏移量),确保分片与主轨道的参数兼容。
关键参数(核心字段):
| 字段名 | 类型 | 示例值 | 说明 |
|---|---|---|---|
track_id |
u32 | 2 | 对应主轨道的 ID(如 2 表示该分片属于视频轨,与moov中trak的track_id一致) |
default_sample_size |
u32 | 15000 | 分片中样本的默认大小(字节),若trun中未单独指定样本大小,则使用此值 |
default_sample_duration |
u32 | 36 | 分片中样本的默认持续时长(单位:轨道时间刻度),trun未指定时使用 |
flags |
u32 | 0x000001 | 标志位,用于标识哪些参数有效(如 0x000001 表示track_id有效) |
数据结构(简化,基于flags标识有效参数):
plaintext
tfhd
├─ version: 0
├─ flags: 0x000007(表示track_id、default_sample_size、default_sample_duration均有效)
├─ track_id: 2(对应视频轨)
├─ default_sample_size: 15000(默认样本大小15KB)
└─ default_sample_duration: 36(默认样本持续36个时间单位,若轨道时间刻度=1000,则为36ms)
实际作用:
- 通过
track_id关联主轨道(如视频轨),确保分片数据能正确 “拼接” 到主轨道的播放流中; - 提供样本默认参数(大小、时长),减少
trun盒的重复数据(若分片中所有样本参数一致,trun无需逐个记录),节省分片元数据体积。
5. trun(Track Run Box,样本运行盒)
核心定位:
traf的核心子盒,记录分片中每个样本的具体信息(如大小、时间偏移、是否为关键帧),是支持 “边下载边播放” 的关键 —— 无需依赖全局stbl盒,仅通过trun就能解析分片中的样本,实现即时播放。
关键参数(核心字段,基于flags标识是否存在):
| 字段名 | 类型 | 示例值 | 说明 |
|---|---|---|---|
sample_count |
u32 | 8 | 分片中的样本数量(如该分片包含 8 个视频帧) |
data_offset |
i32 | 120 | 样本数据在mdat中的偏移量(相对于trun盒的起始位置,正数表示在trun之后) |
sample_size(数组) |
u32[] | [14800, 15200, ...] | 每个样本的大小(字节),若tfhd指定默认值且此处未填,则用默认值 |
sample_duration(数组) |
u32[] | [36, 36, ...] | 每个样本的持续时长(时间单位),同理可使用tfhd默认值 |
sample_flags(数组) |
u32[] | [0x000001, 0x000000, ...] | 样本标志位(如 0x000001 表示该样本是关键帧) |
数据结构(简化,包含 8 个样本):
plaintext
trun
├─ version: 0
├─ flags: 0x00001F(表示sample_count、data_offset、sample_size、sample_duration、sample_flags均有效)
├─ sample_count: 8(8个样本)
├─ data_offset: 120(样本数据在mdat中,位于trun盒之后120字节处)
├─ sample_size: [14800, 15200, 14500, 15100, 14900, 15300, 14700, 15000](每个样本大小)
├─ sample_duration: [36, 36, 36, 36, 36, 36, 36, 36](每个样本持续36ms)
└─ sample_flags: [0x000001, 0x000000, 0x000000, 0x000000, 0x000001, 0x000000, 0x000000, 0x000000](第1、5个是关键帧)
实际作用(流媒体核心逻辑):
- 无需全局
stbl:传统 MP4 需先读取完整moov(包含stbl)才能定位样本,而 fMP4 的trun直接记录分片中样本的大小、位置、时间,下载完moof(含trun)后即可解析mdat中的样本,实现 “下载一个分片播一个分片”; - 关键帧标记:通过
sample_flags标记关键帧,播放器可在分片内快速定位关键帧,即使分片下载中断,也能从最近的关键帧恢复播放; - 灵活适配网络:若网络带宽不足,可动态调整分片大小(如减少每个分片的样本数量),降低单次下载的数据量,减少卡顿。
分片盒子协同逻辑总结(边下边播实现流程)
- 分片下载:播放器从服务器请求视频分片(按
sequence_number顺序,如先下载序号 1,再下载序号 2); - 分片解析:下载完
moof后,通过mfhd确认分片序号(如序号 1),通过traf的tfhd找到对应的轨道(如视频轨track_id=2); - 样本定位:通过
trun获取分片中样本的数量、大小、时间偏移,结合data_offset定位到mdat中的样本数据(如第 1 个样本起始于mdat的 120 字节处,大小 14800 字节); - 解码播放:解码器使用
stsd(来自主moov的全局编码参数)解析样本,结合trun的sample_duration控制播放时间,实现边下载边播放; - 分片拼接:播放完分片 1 后,继续下载分片 2,重复步骤 2-4,通过
sequence_number确保顺序拼接,通过时间戳(sample_duration累加)确保音视频同步。
分片 MP4 与传统 MP4 的核心差异
| 对比维度 | 传统 MP4(非分片) | 分片 MP4(fMP4) |
|---|---|---|
| 元数据位置 | moov(全局元数据)+ stbl(全局样本索引) |
moov(基础参数)+ 每个分片moof(局部元数据) |
| 播放条件 | 需下载完整moov才能开始播放 |
下载第一个分片的moof即可播放 |
| 适用场景 | 本地播放、小文件传输 | 流媒体(如直播、在线视频) |
| 网络适应性 | 差(文件大时下载慢,易卡顿) | 好(分片下载,动态适配带宽) |
二、主moov扩展盒与分片时间戳同步详细说明
在分片 MP4(fMP4)中,主moov盒里的mvex/trex盒与分片的moof/traf/trun盒并非独立工作 ——mvex/trex负责提供分片的全局默认配置,而moof内的盒子基于这些默认值补充局部差异,两者配合实现分片的高效解析与播放。同时,分片的时间戳同步依赖tfdt盒(轨道片段解码时间盒)与全局时间基准的对齐,确保多个分片、多轨道的播放连续性。
(一)、主moov扩展盒(mvex/trex)与分片盒子的联动
mvex(Movie Extends Box)和trex(Track Extends Box)是主moov中为分片 MP4 预留的 “全局配置中心”,作用是定义所有分片的基础默认参数,避免每个moof/traf重复存储相同信息(如轨道 ID、编码描述索引),减少分片元数据体积。
1. mvex(Movie Extends Box,电影扩展盒)
核心定位:
主moov的子盒,是分片 MP4 的 “扩展开关”—— 仅当 MP4 为分片格式时,mvex才存在,其核心作用是承载trex盒(每个轨道对应一个trex),统一管理所有轨道的分片默认配置。
数据结构(简化):
plaintext
mvex(主moov的子盒)
└─ trex(Track Extends Box,每个轨道1个)
├─ track_id: 1(对应音频轨)
├─ default_sample_description_index: 1
├─ default_sample_duration: 32
├─ default_sample_size: 12000
└─ default_sample_flags: 0x000000
└─ trex(对应视频轨)
├─ track_id: 2
├─ default_sample_description_index: 1
├─ default_sample_duration: 36
├─ default_sample_size: 15000
└─ default_sample_flags: 0x000001
实际作用:
- 作为
trex的 “容器”,将所有轨道的分片默认参数集中存储在主moov中,播放器只需读取一次mvex,就能获取所有轨道的分片基础配置; - 告诉播放器 “该 MP4 是分片格式”,需按分片逻辑解析(而非传统 MP4 的全局
stbl索引)。
2. trex(Track Extends Box,跟踪扩展盒)
核心定位:
mvex的子盒,每个轨道对应一个trex(如音频轨 1 个、视频轨 1 个),存储该轨道所有分片的 “默认参数模板”。当分片的tfhd/trun未指定某参数时,自动使用trex的默认值,减少重复数据。
关键参数(与tfhd参数对应,形成 “默认 - 覆盖” 关系):
| 参数名 | 类型 | 示例值(视频轨) | 说明 |
|---|---|---|---|
track_id |
u32 | 2 | 对应主轨道的 ID(与moov中trak的track_id一致,关联轨道) |
default_sample_description_index |
u32 | 1 | 默认样本编码描述索引(关联stsd中的编码参数,如 H.264 的avc1) |
default_sample_duration |
u32 | 36 | 样本默认持续时长(单位:轨道时间刻度,如 36=36ms,与trun的sample_duration对应) |
default_sample_size |
u32 | 15000 | 样本默认大小(字节,与trun的sample_size对应) |
default_sample_flags |
u32 | 0x000001 | 样本默认标志位(如 0x000001 = 关键帧,与trun的sample_flags对应) |
与分片盒子的联动逻辑(以视频轨为例):
- 默认参数继承:若某分片的
tfhd未指定default_sample_size,则自动使用trex的15000字节;若trun未单独指定某样本的sample_duration,则使用trex的36时间单位; - 局部参数覆盖:若分片的
trun中某样本大小为16000字节(不同于默认的15000),则以trun的局部值为准,实现 “默认统一 + 局部灵活” 的配置; - 作用:减少每个
moof/traf的参数存储量(如无需重复记录track_id、编码索引),尤其对大量小分片的直播场景,能显著降低元数据传输成本。
(二)、分片时间戳同步实现(tfdt盒与全局时间对齐)
分片 MP4 的时间同步核心是让每个分片的样本时间戳与全局时间轴对齐—— 传统 MP4 通过stts累加计算全局时间,而分片 MP4 通过tfdt(Track Fragment Decode Time Box)提供分片的 “时间基准点”,再结合trun的sample_duration计算每个样本的全局时间。
1. tfdt(Track Fragment Decode Time Box,轨道片段解码时间盒)
核心定位:
traf的可选子盒(但分片同步必需),为当前轨道分片提供起始解码时间(全局时间轴上的位置),是分片时间与全局时间对齐的 “锚点”。
关键参数:
base_media_decode_time(基础媒体解码时间):64 位整数,表示该分片的第一个样本在全局时间轴上的起始解码时间(单位:轨道时间刻度)。
数据结构(简化):
| 字段名 | 类型 | 示例值(视频轨分片 5) | 说明 |
|---|---|---|---|
version |
u8 | 1 | 版本 1 支持 64 位时间戳,版本 0 支持 32 位(推荐版本 1,避免时间溢出) |
flags |
u32 | 0 | 标志位,无特殊含义时为 0 |
base_media_decode_time |
u64 | 18000 | 该分片第一个样本的全局起始解码时间(轨道时间刻度,若刻度 = 1000,则为 18 秒) |
核心作用:
- 解决分片 “时间孤岛” 问题:每个分片的
trun仅记录样本的 “相对时间”(如分片内第 1 个样本持续 36ms,第 2 个也持续 36ms),而tfdt的base_media_decode_time告诉播放器 “该分片的时间起点在全局时间轴的哪里”; - 示例:若视频轨时间刻度 = 1000(1 单位 = 1ms),分片 5 的
base_media_decode_time=18000(18 秒),则:- 分片 5 第 1 个样本解码时间 = 18000ms(18 秒);
- 第 2 个样本解码时间 = 18000+36=18036ms(18.036 秒);
- 以此类推,确保分片 5 的时间与前 4 个分片的时间轴无缝衔接。
2. 时间戳同步完整流程(以视频轨为例)
步骤 1:获取全局时间基准(主moov的mvhd)
mvhd的timescale(全局时间刻度)=1000(1 单位 = 1ms),duration=480000(总时长 480 秒 = 8 分钟);- 轨道的
mdhd(媒体头盒)的timescale=1000(与全局刻度一致,确保时间单位统一)。
步骤 2:解析分片tfdt的时间基准
- 分片 5 的
tfdt中base_media_decode_time=18000(轨道时间刻度 = 1000→18 秒); - 该值是分片 5 所有样本的 “时间起点”,由服务器生成时确保与前一分片(分片 4)的最后一个样本时间衔接(如分片 4 最后一个样本时间 = 17999ms,分片 5 起点 = 18000ms,无间隙)。
步骤 3:计算分片中每个样本的全局时间
trun中sample_count=8,每个样本sample_duration=36(36ms);- 样本 1 全局解码时间 = 18000ms(18 秒);
- 样本 2 全局解码时间 = 18000+36=18036ms(18.036 秒);
- ...
- 样本 8 全局解码时间 = 18000+36×7=18252ms(18.252 秒)。
步骤 4:视频与音频轨道的时间同步
- 音频轨分片 5 的
tfdt中base_media_decode_time=18000(与视频轨一致); - 音频样本
sample_duration=32(32ms,对应 44100Hz 采样率的音频段); - 音频样本 1 全局解码时间 = 18000ms,与视频样本 1 的时间一致,实现音视频同步播放。
3. 时间戳同步的关键保障
- 时间刻度统一:主
moov的mvhd、轨道的mdhd、tfdt/trun的时间单位需一致(如均为 1000,即 ms),若不一致需进行转换(如轨道刻度 = 90000,全局刻度 = 1000,则 1 轨道单位 = 1/90 秒≈11.11ms); base_media_decode_time连续:服务器生成分片时,需确保下一个分片的base_media_decode_time= 前一个分片最后一个样本的全局时间 + 1,避免时间间隙或重叠;- 音视频
tfdt对齐:同一序号的音视频分片(如音频分片 5、视频分片 5)的base_media_decode_time需相同,确保同一时间点播放对应的音频和视频样本。
(三)、完整分片 MP4 的盒子层级与协同逻辑(补充mvex/tfdt后)
plaintext
MP4 文件(分片格式)
├─ ftyp(文件类型盒,必需)
├─ moov(主电影盒,必需)
│ ├─ mvhd(全局头盒,必需)
│ ├─ mvex(电影扩展盒,必需)
│ │ ├─ trex(音频轨扩展盒,必需)
│ │ └─ trex(视频轨扩展盒,必需)
│ └─ trak(音频轨/视频轨盒,必需)
│ ├─ tkhd(轨道头盒)
│ ├─ mdia(媒体盒)
│ │ ├─ mdhd(媒体头盒)
│ │ ├─ hdlr(处理者盒)
│ │ └─ minf(媒体信息盒)
│ │ └─ stbl(样本表盒,仅存编码参数stsd,无全局样本索引)
│ │ └─ stsd(编码描述盒,avc1/mp4a,必需)
├─ moof(分片1元数据盒,必需)
│ ├─ mfhd(分片头盒,sequence_number=1)
│ ├─ traf(音频轨分片1盒)
│ │ ├─ tfhd(轨道片段头盒,track_id=1)
│ │ ├─ tfdt(解码时间盒,base_media_decode_time=0)
│ │ └─ trun(样本运行盒,8个音频样本)
│ └─ traf(视频轨分片1盒)
│ ├─ tfhd(轨道片段头盒,track_id=2)
│ ├─ tfdt(解码时间盒,base_media_decode_time=0)
│ └─ trun(样本运行盒,8个视频样本)
├─ mdat(分片1媒体数据盒,存储分片1的音视频样本)
├─ moof(分片2元数据盒,sequence_number=2)
│ ├─ mfhd(sequence_number=2)
│ ├─ traf(音频轨分片2盒,tfdt=256ms)
│ └─ traf(视频轨分片2盒,tfdt=288ms)
├─ mdat(分片2媒体数据盒)
└─ ...(更多分片moof+mdat)
协同逻辑总结:
- 初始化:播放器读取
ftyp确认是分片 MP4,读取moov的mvhd获取全局时间刻度,读取mvex的trex获取各轨道的分片默认参数,读取stsd获取编码参数; - 分片解析:下载分片 1 的
moof,通过mfhd确认序号 1,通过traf的tfhd关联轨道(如track_id=2对应视频轨),通过tfdt获取分片 1 的时间起点(0ms); - 样本播放:通过
trun获取样本大小、时长,结合mdat定位样本数据,解码器用stsd参数解码,按tfdt+sample_duration计算的全局时间播放; - 分片衔接:下载分片 2,通过
mfhd序号 2 确认顺序,通过tfdt的base_media_decode_time=288ms(分片 1 最后一个样本时间 = 287ms)实现无缝衔接,重复步骤 3-4 直至播放结束。
总结
mvex/trex是分片 MP4 的 “全局配置模板”,通过提供默认参数减少分片元数据冗余,与tfhd/trun形成 “默认 - 覆盖” 的高效配置模式;tfdt是分片时间同步的 “锚点”,通过base_media_decode_time将分片的局部时间映射到全局时间轴,确保分片间、音视频轨道间的时间对齐;- 整个分片系统围绕 “边下载边播放” 设计,从参数配置到时间同步,每一步都为降低延迟、提升网络适应性服务,这也是 fMP4 成为流媒体主流格式的核心原因。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)