视频文件并不是一段单独的“视频数据”,而是一个容器,内部可以同时装载视频、音频、字幕、章节、封面、时间戳和元数据等内容。
1. 先建立最重要的理解:视频文件像一个快递箱
可以把一个视频文件想象成快递:
-
文件扩展名是快递箱外面的标签,例如
.mp4、.mkv。 -
容器格式是箱子的结构,例如 MP4、Matroska、AVI。
-
视频流是箱子中的画面内容。
-
音频流是箱子中的声音内容。
-
字幕流是箱子中的字幕。
-
编码格式是内容的压缩规则,例如 H.264、HEVC、VP9、AAC。
-
编码器和解码器是压缩、还原这些内容的工具。
例如,一个名为 movie.mp4 的文件可能是:
movie.mp4
└── MP4 容器
├── 视频流
│ ├── 编码:H.264
│ ├── 分辨率:1920×1080
│ ├── 帧率:30 fps
│ ├── 像素格式:yuv420p
│ └── 比特率:4 Mbps
│
├── 音频流
│ ├── 编码:AAC
│ ├── 采样率:48 kHz
│ ├── 声道:立体声
│ └── 比特率:192 kbps
│
├── 字幕流
│ └── 格式:mov_text
│
├── 元数据
│ ├── 标题
│ ├── 作者
│ └── 创建时间
│
└── 索引与时间戳
另一个同样名为 .mp4 的文件,内部的视频却可能采用 HEVC 或 AV1,音频可能采用 AAC、MP3 或 ALAC。
因此:
文件扩展名只能说明外层容器的大致类型,不能完整说明内部视频和音频采用了什么编码。
2. 文件扩展名和容器格式
2.1 文件扩展名
扩展名是文件名最后的部分,例如:
video.mp4
video.mov
video.mkv
video.webm
video.avi
操作系统和应用通常通过扩展名初步判断文件类型,但扩展名本身不会改变文件内容。
例如,把:
video.mkv
直接重命名成:
video.mp4
只是更换了文件名。文件内部仍然是 Matroska 容器,并没有变成 MP4 容器。
有些播放器会检查文件的真实内容,因此重命名后仍有可能播放;另一些播放器依赖扩展名,可能直接提示文件损坏。无论播放器能否打开,这都不是真正的格式转换。
2.2 容器格式
容器负责组织不同的媒体流,并保存:
-
视频流
-
音频流
-
字幕流
-
每条流的时间戳
-
音视频同步关系
-
章节信息
-
标题、作者等元数据
-
快速定位播放位置所需的索引
-
部分容器支持的封面、字体和附件
常见容器包括:
常见扩展名
容器
主要特点
.mp4
MPEG-4 Part 14
播放兼容性较好,常用于网站、移动设备和普通视频文件
.mov
QuickTime File Format
常见于 Apple 设备、相机和专业制作软件
.mkv
Matroska
可以容纳多视频、多音轨、多字幕、章节和附件
.webm
WebM
基于 Matroska,主要面向网页媒体
.avi
Audio Video Interleave
较早的微软容器,结构和时间戳能力相对有限
.m4v
MPEG-4 系列容器
通常与 MP4 结构接近,常用于视频内容
.wmv
通常指 ASF 容器
经常包含 WMV 视频和 WMA 音频
.flv
Flash Video
过去常用于网页 Flash 视频
.ts
MPEG Transport Stream
常见于广播、录像、直播和 HLS 分片
FFmpeg 将读取容器的组件称为“解封装器”,将媒体流写入容器的组件称为“封装器”。不同 FFmpeg 构建实际启用的封装和解封装能力可能不同。
3. 什么是媒体流
容器内部的每一组独立媒体数据称为一条流。
一个视频文件不一定只有“一段视频和一段声音”。它可能包含:
输入文件
├── 视频流 #0:主画面
├── 视频流 #1:备用角度
├── 音频流 #0:中文
├── 音频流 #1:英文
├── 音频流 #2:导演评论
├── 字幕流 #0:中文字幕
├── 字幕流 #1:英文字幕
└── 附件:字幕字体
3.1 视频流
视频流保存连续的画面数据。为了减小文件体积,画面通常会经过视频编码器压缩;少数专业制作或中间文件也可能保存未压缩视频。
常见视频编码格式包括:
-
H.264/AVC
-
H.265/HEVC
-
VP8
-
VP9
-
AV1
-
MPEG-2 Video
-
MPEG-4 Part 2
-
ProRes
-
DNxHD/DNxHR
-
Theora
-
WMV/VC-1
视频流还包含或关联:
-
宽度和高度
-
帧率
-
像素格式
-
色彩空间
-
色深
-
HDR 信息
-
编码档次 Profile
-
编码级别 Level
-
时间基准
-
关键帧信息
3.2 音频流
音频流保存连续的声音数据,可以是 AAC、MP3 等压缩数据,也可以是 PCM 等未压缩采样数据。
常见音频编码格式包括:
-
AAC
-
MP3
-
Opus
-
Vorbis
-
AC-3
-
E-AC-3
-
DTS
-
FLAC
-
ALAC
-
PCM
-
WMA
音频流还具有:
-
采样率,例如 44.1 kHz、48 kHz
-
声道数,例如单声道、立体声、5.1 声道
-
采样格式
-
比特率
-
声道布局
-
时间戳
3.3 字幕流
字幕也可能是文件内部的一条媒体流,主要分为两类:
-
文本字幕:保存文字和时间信息,例如 SRT、ASS、WebVTT、mov_text。
-
图像字幕:字幕以图片形式保存,例如 DVD Subtitle、PGS。
不同容器支持的字幕类型不同。例如,MKV 可以容纳 ASS 等字幕,而 MP4 通常不能直接保存完全相同的 ASS 字幕数据。因此,字幕是否能作为独立媒体流存在,也与文件所使用的容器有关。
3.4 其他流
除视频、音频和字幕外,容器还可能保存其他类型的流,例如:
-
相机或拍摄设备记录的传感器数据
-
直播或广播中的节目数据
-
时间码轨道
-
缩略图或封面图
-
用于描述画面位置、方向或运动的信息
这些数据不一定直接形成画面或声音,但可能被剪辑软件、播放器或专业设备使用。
4. 编码数据、包和帧
视频文件中的媒体数据并不是简单地按照“一张图片、一段声音”的形式连续排列。理解编码数据、包和帧之间的关系,才能看清文件内部真正保存了什么。
4.1 编码格式
未经压缩的视频由大量像素组成,未经压缩的音频由连续的采样值组成,直接保存会占用很大空间。编码格式规定如何组织和压缩这些数据,例如:
-
H.264、HEVC、VP9、AV1 是视频编码格式。
-
AAC、MP3、Opus、FLAC 是音频编码格式。
编码格式是一套数据规则,不是具体的软件:
-
编码器按照规则把原始画面或声音转换为编码数据。
-
解码器按照相同规则把编码数据还原为可显示的画面或可播放的声音。
-
同一种编码格式可以由不同的软件编码器或硬件编码器实现。
因此,“MP4”和“H.264”不属于同一层概念:MP4 是容器,H.264 是可能装在容器中的视频编码格式。
4.2 包(Packet)
容器把每条媒体流的编码数据划分为一个个包。每个包通常会记录:
-
属于哪一条流
-
对应的时间戳
-
持续时间
-
是否包含关键帧数据
-
实际的编码数据
音频包和视频包通常会按照时间交错写入文件,例如:
视频包 V0
音频包 A0
音频包 A1
视频包 V1
字幕包 S0
音频包 A2
视频包 V2
……
交错存储让播放器不必先读完整条视频流,再返回读取音频流,而是可以按播放进度连续取得各类数据。
一个包不一定正好对应一个画面帧:
-
一个视频帧的数据可能跨越多个包。
-
一个包也可能包含多个较小的音频帧。
-
包的边界由容器和编码格式共同决定。
4.3 帧(Frame)
帧是解码器处理和输出的媒体单位。
对于视频:
-
解码后的帧是一张完整的像素图像。
-
帧通常具有宽度、高度、像素格式和显示时间。
-
压缩视频中的帧可能依赖前后其他帧才能被完整还原。
对于音频:
-
解码后的音频帧是一段连续的 PCM 采样。
-
音频帧包含采样率、声道布局、采样格式和采样数量等信息。
-
音频帧代表一小段声音,而不是一张图像。
“包”和“帧”不能混为一谈:
对比项
包(Packet)
帧(Frame)
所在阶段
容器解封装之后、解码之前
解码之后
主要内容
已编码的数据
原始像素或音频采样
是否带时间戳
通常带有 PTS、DTS、duration
通常具有对应的显示或播放时间
是否可以直接显示或播放
通常不可以
可以交给渲染器或音频设备
4.4 视频帧之间的依赖关系
许多视频编码格式会利用相邻画面的相似性减少数据量。常见帧类型可以简单理解为:
-
I 帧:可以相对独立地解码,常被用作关键帧。
-
P 帧:需要参考之前已经解码的画面。
-
B 帧:可能同时参考之前和之后的画面。
这意味着文件中不需要为每个时刻保存一张完整图片。编码器可以保存“哪些区域发生了变化、应参考哪一帧”等信息,由解码器重新构建完整画面。
5. 时间戳与音画同步
视频文件可能同时包含视频、音频和字幕。它们产生数据的频率不同,不能依靠“第几个包”来确定播放时刻,必须依靠时间戳。
5.1 时间基
时间戳通常以整数保存,再通过时间基换算为秒。
例如:
时间基:1/1000 秒
时间戳:2500
实际时间:2500 × 1/1000 = 2.5 秒
不同媒体流可以使用不同的时间基,因此比较音频和视频时间时,需要先换算到统一时间单位。
5.2 PTS、DTS 和持续时间
名称
含义
主要作用
PTS
Presentation Timestamp,呈现时间戳
表示画面应何时显示、声音应何时播放
DTS
Decoding Timestamp,解码时间戳
表示数据应何时送入解码器
duration
持续时间
表示包或帧覆盖多长时间
如果视频包含 B 帧,解码顺序可能与显示顺序不同,因此同一个包的 DTS 和 PTS 可能不同。
播放器通常会:
-
按照 DTS 顺序把数据交给解码器。
-
根据 PTS 安排解码后帧的呈现时间。
-
以统一时钟为基准,对齐视频、音频和字幕。
解封装器提供的是压缩包的解码顺序,渲染器需要的是帧的呈现顺序。帧重排缓冲根据 PTS 调整解码器输出,避免含 B 帧的视频按照错误顺序显示。
5.3 文件时长
文件时长不一定等于“视频帧数量 ÷ 标称帧率”。它可能由以下信息共同决定:
-
各条流的开始时间
-
最后一个包或帧的时间戳
-
包或帧的持续时间
-
容器头部记录的总时长
-
是否存在可变帧率
-
音频和视频是否具有不同长度
因此,一个文件可能出现音频比视频略长、视频比音频略长,或者容器时长与某条媒体流时长不完全相同的情况。
6. 容器中的辅助结构
媒体流是视频文件的核心内容,但完整容器还需要一些辅助结构,帮助播放器识别、定位和解释这些内容。
6.1 文件头和轨道描述
文件头通常用于说明:
-
容器类型和版本
-
文件整体时长
-
使用的时间尺度
-
包含多少条轨道或媒体流
-
每条流的类型和编码格式
-
解码器初始化所需的参数
播放器通常先读取这些信息,确认文件结构和所需解码能力,然后再读取具体媒体包。
6.2 索引
索引用于记录时间位置与文件位置之间的关系。
例如,用户把进度条拖到 10 分钟处时,播放器需要通过索引快速找到附近可以开始解码的关键帧,而不是从文件开头逐包读取到 10 分钟。
索引会影响:
-
打开文件后的定位速度
-
拖动进度条的响应速度
-
随机跳转播放
-
部分剪切和分段处理
索引缺失或损坏时,文件可能仍能顺序播放,但定位速度变慢,甚至无法正确跳转。
6.3 元数据
元数据用于描述文件或某条媒体流,但它通常不等同于画面像素或音频采样。
常见元数据包括:
-
标题、作者和描述
-
创建时间
-
视频或音轨语言
-
轨道名称
-
默认音轨和默认字幕标记
-
拍摄设备信息
-
旋转方向
-
色彩和 HDR 描述信息
元数据可以分为:
-
容器级元数据:描述整个文件。
-
流级元数据:只描述某一条视频、音频或字幕流。
例如,一段竖屏视频的编码尺寸可能以横向方式保存,再由旋转元数据告诉播放器应如何显示。忽略这项元数据时,画面方向就可能出现错误。
6.4 章节、封面和附件
部分容器还可以保存:
-
章节名称和章节起止时间
-
封面图
-
字幕使用的字体
-
菜单或导航信息
-
与媒体内容相关的附件
这些内容不是所有视频文件都具备,也不是所有容器都支持。它们属于视频文件的附加组成部分。
7. 从文件到画面和声音的完整链路
播放器打开视频文件后,通常会经历以下过程:
各组成部分在这条链路中的作用是:
-
文件扩展名帮助系统初步判断文件类型。
-
容器规定文件内部的组织结构。
-
文件头描述容器、轨道和解码参数。
-
媒体流分别承载视频、音频、字幕或其他数据。
-
媒体包保存已编码数据及其时间信息。
-
解码器把媒体包还原为视频帧或音频帧。
-
时间戳让不同媒体流保持同步。
-
索引帮助播放器快速定位目标时间。
-
元数据补充方向、语言、标题、色彩等描述。
一个完整视频文件的组成关系可以概括为:
视频文件
├── 文件名与扩展名
└── 容器
├── 文件头
├── 媒体流
│ ├── 视频流
│ │ └── 视频编码数据包
│ ├── 音频流
│ │ └── 音频编码数据包
│ ├── 字幕流
│ └── 其他数据流
├── 时间戳
│ ├── PTS
│ ├── DTS
│ └── duration
├── 索引
├── 元数据
├── 章节
└── 封面与附件
因此,视频文件并不等于某一种视频编码,也不只是画面本身。它是由容器结构、媒体流、编码数据、时间信息、索引和描述信息共同组成的完整媒体数据集合。