2D 视频文件里有什么
一个 MP4 文件不是"很多图片顺序塞在一起"。它更像一个带索引的媒体数据库:轨道、样本、时间戳、编码参数、同步点和显示元数据都被组织在里面。
先看文件内部结构

MP4 是容器,不是编码。H.264 / H.265 / AV1 负责压缩画面,MP4 / MOV / MKV 负责把压缩数据、时间信息和轨道关系组织起来。
1. 容器、轨道、样本三层要分清
| 层级 | 典型对象 | 工程含义 |
|---|---|---|
| container | MP4 / MOV / MKV | 负责文件结构、索引、轨道组织 |
| track | video / audio / subtitle | 每种媒体一条或多条轨道 |
| sample / packet | 一帧或一段编码数据 | demuxer 读出来交给 decoder 的单位 |
| codec bitstream | NAL / OBU / slice | decoder 真正解析的压缩语法 |
播放器打开文件时,先读容器,再选择轨道,再把 sample 转成 packet,最后 decoder 才开始理解 codec bitstream。
2. MP4 里哪些 box 最关键
不同容器细节不一样,但以 MP4 为例,工程上常见关键结构如下:
| Box | 作用 | 出问题的表现 |
|---|---|---|
ftyp |
标识文件品牌和兼容性 | 兼容性判断失败 |
moov |
元数据总入口 | 文件无法打开或索引缺失 |
mdat |
真实媒体数据 | packet 数据读取失败 |
trak |
单条媒体轨道 | 找不到视频/音频轨 |
mdhd |
track 时间尺度和 duration | 时长、同步异常 |
stsd |
sample description / codec config | decoder 初始化失败 |
stts |
decoding time to sample | DTS / duration 错误 |
ctts |
composition time offset | B 帧 PTS 错误 |
stss |
sync sample / keyframe index | seek 后花屏或失败 |
stsz |
sample size | packet 边界错误 |
stco / co64 |
sample 文件偏移 | 读取错位、花屏 |
一个文件"ffprobe 看得到信息"不代表它的 sample table 一定完全正确。seek、变速、截断文件恢复这些场景会更容易暴露封装问题。
3. 编码参数到底保存在哪里
解码器启动前必须拿到 codec config。不同编码的名字不同,但作用相似。
| 编码 | 关键配置 | 用途 |
|---|---|---|
| H.264 / AVC | SPS、PPS、avcC | 宽高、profile、level、参考帧、熵编码模式等 |
| H.265 / HEVC | VPS、SPS、PPS、hvcC | 多层级、CTU、profile、tier、level 等 |
| AV1 | sequence header、av1C | profile、level、bit depth、operating point 等 |
| VP9 | codec private / container fields | profile、bit depth、color 等 |
参数集可以在码流里反复出现,也可以集中放在 extradata 里。移动端硬解尤其依赖初始化参数,如果 extradata 缺失、格式不对,可能表现为软解能播、硬解打不开。
4. 时间信息不只是 PTS
播放器同步靠时间信息,而不是靠"读到第几个 packet"。
| 时间字段 | 作用 | 常见坑 |
|---|---|---|
| time scale / time base | 把整数时间换成秒 | 单位换算错误导致快慢异常 |
| DTS | packet 应该进入 decoder 的时间顺序 | B 帧场景必须单调 |
| PTS | frame 应该显示的时间 | 显示调度核心依据 |
| duration | sample 持续时间 | VFR 视频必须逐帧看 duration |
| edit list | 轨道起始偏移和裁剪 | 开头黑帧、音画偏移 |
| start time | 媒体流起点 | 多轨同步要统一基准 |
固定帧率视频可以看起来很简单;可变帧率、B 帧、edit list、音频 priming delay 混在一起时,时间线才是真正的复杂点。
5. 显示元数据决定"解出来以后怎么画"
decoder 主要关心码流语法,但 renderer 还需要显示相关信息。
| 信息 | 典型来源 | 显示阶段用途 |
|---|---|---|
| rotation matrix | container metadata | 竖屏视频转正 |
| clean aperture / crop | container 或 codec | 去掉编码填充边界 |
| SAR / pixel aspect ratio | codec VUI / container | 计算 DAR,避免比例变形 |
| color primaries | VUI / container | 判断 BT.709 / BT.2020 等色域 |
| transfer characteristics | VUI / HDR metadata | 判断 SDR / PQ / HLG |
| matrix coefficients | VUI | 选择 YUV→RGB 矩阵 |
| mastering display metadata | HDR SEI / container | HDR tone mapping |
| content light level | HDR metadata | 峰值亮度策略 |
很多"解码没错但看着不对"的问题,其实是显示元数据没有被正确传到渲染链路。
6. 解码时用什么,显示时用什么
| 信息 | demuxer | decoder | renderer / display |
|---|---|---|---|
| track index | 选择轨道 | 不关心 | 不关心 |
| sample offset / size | 读 packet | 不关心 | 不关心 |
| codec type | 选择 decoder | 初始化 decoder | 可能用于能力策略 |
| codec extradata | 提取并传递 | 必须使用 | 通常不直接用 |
| DTS | 排 packet | 决定输入顺序 | 间接影响队列 |
| PTS | 传递时间戳 | 输出 frame metadata | 决定显示时刻 |
| color metadata | 传递 | 有时使用 | 必须使用 |
| rotation / crop | 传递 | 通常不用 | 必须使用 |
| keyframe index | seek | flush / restart | 间接影响首帧 |
这张表是排查播放器问题的分界线:先问"这个信息在哪一层被消费",再问"它有没有正确传过去"。
7. 文件异常怎么定位
| 现象 | 优先检查 | 典型工具方向 |
|---|---|---|
| 文件打不开 | moov、track、codec config |
容器解析、ffprobe |
| 只有声音没画面 | video track、decoder init | codec id、extradata、profile |
| seek 后花屏 | stss、IDR、参数集 |
keyframe index、packet 边界 |
| 时长不对 | mdhd、duration、edit list | time scale、start time |
| 变速或卡顿 | DTS / PTS / duration | VFR、B 帧、time base |
| 颜色异常 | VUI、container color tags | matrix、range、transfer |
| 横竖屏错误 | rotation matrix | display matrix 传递链路 |
一句话总结
视频文件的价值不只是保存压缩码流,而是保存"decoder 如何解、renderer 如何画、播放器如何按时间组织"的全部上下文。