1. 转码基础:理解视频编码原理、封装格式与编码格式的区别、FFmpeg转码基本流程
各位好,欢迎来到这门课。我是老张,在音视频这行摸爬滚打了十几年。今天咱们聊转码,但别急着敲命令——先把地基打牢。
很多人一上来就问我:“张哥,FFmpeg 转个码是不是就一行命令?” 嗯,是也不是。你确实能用一行命令把 MP4 转成 H.264,但如果你不懂背后发生了什么,遇到花屏、音画不同步、文件体积爆炸这些问题时,你连从哪下手都不知道。
所以第一章,咱们先把概念理清楚。说白了,就是搞明白三件事:视频是怎么编码的、封装和编码到底是不是一回事、FFmpeg 转码时内部到底干了什么。
1.1 视频编码原理:为什么原始视频那么大?
先问个问题:一段 1080p、30fps、时长 10 秒的原始视频,有多大?
算一下:每帧 1920×1080 像素,每个像素用 YUV420 格式存储,每个像素平均 12 bit(1.5 字节)。一帧就是 1920×1080×1.5 ≈ 3.1 MB。30fps 就是 93 MB/s。10 秒就是 930 MB。
一个 10 秒的视频就快 1GB 了,这谁受得了?所以必须压缩。
视频编码的核心思想就两个:
- 空间冗余:同一帧里,相邻像素颜色差不多。比如蓝天背景,没必要每个像素都存一遍,存一块区域+一个颜色值就行。
- 时间冗余:相邻帧之间,大部分内容没变。比如新闻主播,背景不动,只有嘴在动。那我只存变化的部分,没变的直接复用上一帧。
我刚开始做编码优化时,犯过一个低级错误:用最高质量参数压了一个监控视频,结果文件比原始还大。后来才发现,监控场景静态区域太多,编码器反而花了大量 bit 去保留那些根本没人看的细节。这就是没理解“时间冗余”的典型反面教材。
现代编码标准(H.264、H.265、AV1)都是基于混合编码框架的:
- 帧内预测:利用空间冗余,压缩单帧内部数据。
- 帧间预测:利用时间冗余,只编码运动部分。
- 变换量化:把像素数据转到频域,丢掉人眼不敏感的高频细节。
- 熵编码:用更短的码字表示出现频率高的数据。
一句话总结:编码的本质就是“找规律+丢细节”。找得越准,丢得越聪明,压缩率就越高。
1.2 封装格式 vs 编码格式:别再搞混了
这是新手最容易踩的坑。我面试过不少人,问“MP4 和 H.264 有什么区别”,十个有八个答不上来。
咱们打个比方:
- 编码格式(Codec) = 你写的内容。比如 H.264、H.265、VP9、AV1。它决定了视频怎么压缩、质量怎么样。
- 封装格式(Container) = 装内容的信封。比如 MP4、MKV、AVI、TS。它决定了怎么把视频流、音频流、字幕、元数据打包在一起。
同一个 MP4 文件,里面可以装 H.264 视频,也可以装 H.265 视频。同一个 H.264 视频流,可以放进 MP4,也可以放进 MKV。两者没有必然绑定关系。
我遇到过最离谱的事:一个合作方发来的视频,后缀是 .mp4,但 FFmpeg 死活打不开。一查,里面封装的是原始 YUV 数据。这就是典型的“信封写对了,内容放错了”。
下面这张表帮你快速区分:
| 维度 | 编码格式 | 封装格式 |
|---|---|---|
| 作用 | 压缩视频/音频数据 | 组织、存储、同步多路流 |
| 常见例子 | H.264, H.265, AV1, AAC | MP4, MKV, AVI, TS, MOV |
| 文件后缀 | 通常不直接作为后缀 | 直接决定文件后缀 |
| 关注点 | 压缩率、画质、解码性能 | 兼容性、功能(字幕、章节) |
避坑指南:我曾经把一个 H.265 编码的视频直接改了后缀为 .mp4,结果播放器全挂。记住:改后缀不等于转封装,更不等于转编码。
1.3 FFmpeg 转码基本流程:内部到底发生了什么?
好,现在咱们看看 FFmpeg 执行一条转码命令时,内部是怎么跑的。
一条典型的转码命令:
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -c:a aac -b:a 128k output.mp4
这条命令背后,FFmpeg 做了这么几件事:
- 解封装(Demuxing):读取 input.mp4,分离出视频流(H.264 原始码流)和音频流(可能是 AAC 或别的)。
- 解码(Decoding):把压缩的视频流解码成原始 YUV 帧,音频流解码成原始 PCM 采样。
- 滤镜处理(Filtering):可选。比如缩放、裁剪、加水印。这一步在原始数据上操作。
- 编码(Encoding):把原始 YUV 帧重新压缩成新的编码格式(这里指定了 libx264)。
- 封装(Muxing):把新的视频流和音频流打包进 output.mp4。
整个过程可以画成下面这张图:
这里有个关键点很多人会忽略:解码再编码是有损的。哪怕你用了“无损”参数,只要经过了 YUV 转换和量化,信息就丢了。所以如果你只是想换个封装格式(比如 MP4 转 MKV),千万别用上面的命令——那等于把视频解压再压缩一遍,质量损失不说,还慢得要命。
正确的做法是直接流复制:
ffmpeg -i input.mp4 -c:v copy -c:a copy output.mkv
这条命令只做解封装和封装,不解码也不编码。速度飞快,质量零损失。
警告:流复制只适用于同一种编码格式。如果你想把 H.264 转成 H.265,必须走完整的解码→编码流程。别想着用 copy 参数“偷懒”,那只会得到一个没转码的假结果。
1.4 本章小结
咱们把这一章的核心点串一下:
- 视频编码靠的是消除空间冗余和时间冗余,核心是“找规律+丢细节”。
- 封装格式和编码格式是两码事。编码管压缩,封装管打包。别搞混。
- FFmpeg 转码流程是:解封装→解码→(滤镜)→编码→封装。每一步都有代价。
- 如果只是换封装,用
-c:v copy -c:a copy,别傻傻地重新编码。
这些概念看着简单,但我在实际项目中见过太多人栽在上面。尤其是封装和编码的区别,几乎每周都有人问。记住今天这张图、这张表,后面咱们聊参数调优、质量评估、效率优化时,你才不会晕头转向。