视频编码的全部招数归结成一句话:先去掉【多余】,再用尽量少的位数写下【剩下的】——空间冗余靠帧内预测,时间冗余靠帧间预测,频域集中靠变换,不敏感的部分靠量化。
第五章从【用】的角度讲过视频编码,第六章拆开了压缩的五个环节。这一章换个角度——把原理与标准并排放,先从原理最完整的那一块说起。
一、要解决的问题
一份原始视频只有三个数:宽、高、帧率。 1080p30、每像素 3 字节:1920×1080×3×8×30 = 1493 Mbps(约 1.5 Gbps)。 一小时的原始数据 ≈ 670 GB。 编码的目标就一句话:在肉眼看不出来的前提下,把码率压掉两个数量级。
二、四步骨架
把第六章的五步骤换个说法,编码器内部真正在做的事是四件: 预测——先把【能猜到的部分】从数据里拿走,只留残差; 变换——把残差从空间域换到频率域,让能量挤到少数几个系数上; 量化——按人眼不敏感的程度把系数粗化,这一步决定画质与码率; 熵编码——把剩下的符号用最省的位数写下来,无损收尾。 预测与变换不丢信息,只是换了个更好压的表示方式;真正丢东西的只有量化(第 6.3.3 节)。
三、空间冗余与时间冗余,分开处理
两类冗余对应的工具完全不一样: 空间冗余(同一帧内部)→ 帧内预测,用左边和上边的像素猜当前块(第 6.4.1 节)。 时间冗余(帧与帧之间)→ 帧间预测,用前面或后面的帧当参考,配 运动补偿 把整块搬过来(第 6.4.4 节)。 两者的分工很清楚:帧内预测给帧间预测提供【落脚点】,因为帧间预测必须有一个不依赖别的帧的参考帧(第 6.5.1 节的 I 帧)。
四、解码为什么比编码简单得多
这是初学者最容易忽略的一点:编码与解码的工作量严重不对称。 编码端要【找】:在参考帧里搜索最像的那一块,还要试多种分块方式,穷举量极大; 解码端只要【用】:运动矢量已经写在码流里,照着搬就行,几乎不用搜索。 所以现实中的配置是:编码器可以很慢、解码器必须很快。 这也是为什么硬件解码(手机、机顶盒)普及得早,而硬件编码一直做得更吃力。
五、码率控制:编码器的方向盘
同样的编码器,换个码率控制策略,产出的文件完全不同: CBR(固定码率)——每秒码率基本恒定,适合直播;画质会随画面复杂度起伏。 VBR(可变码率)——复杂画面多给、简单画面少给,总大小更小、画质更均匀,适合点播。 调节的旋钮叫 QP(量化参数):QP 越小画质越好、码率越高,这是一条单调的取舍曲线。
六、动手 Demo:一帧一帧看压缩,I/P/B 差近十倍
把一段 12 帧的视频逐帧拆开,看每一帧压完还剩多少。
RAW_KB = int(1920 * 1080 * 1.5 / 1024) # 1080p YUV 4:2:0 一帧
frames = [("1", "I", 75), ("2", "B", 8), ("4", "P", 25)]
total_raw = RAW_KB * 12
total_comp = 75 + 8 * 8 + 25 * 3
print("12 帧原始 %d KB,压缩后 %d KB,压缩比 %.0f : 1"
% (total_raw, total_comp, total_raw * 1.0 / total_comp))
实跑输出:
--------------------------------------------------------------------
一帧一帧看压缩,I/P/B 差近十倍
--------------------------------------------------------------------
把一段 12 帧的视频逐帧拆开,看每一帧压完还剩多少。
帧序 类型 原始 KB 压缩后 KB
----------------------------------------
1 I 3037 75
2 B 3037 8
3 B 3037 8
4 P 3037 25
5 B 3037 8
6 B 3037 8
7 P 3037 25
8 B 3037 8
9 B 3037 8
10 P 3037 25
11 B 3037 8
12 B 3037 8
12 帧合计:原始 36444 KB → 压缩后 214 KB,**平均压缩比约 170 : 1**。
三个关键观察:
一是 同为 1080p,**I 帧 75 KB、B 帧 8 KB,差 9 倍以上**;
二是 **P 帧 25 KB 也不大,因为它能参考前一帧**;
三是 原始一帧就是 3037 KB,30 帧/秒即 **93.3 MB/s(约 746 Mbps)**;
换成 RGB24 则是 1493 Mbps(第 5.1.3 节)——**不压缩根本传不动**。
同为 1080p,I 帧 75 KB、B 帧 8 KB,差 9 倍以上; P 帧 25 KB 也不大,因为它能参考前一帧。 原始一帧就是 3037 KB,30 帧/秒即 93.3 MB/s(约 746 Mbps); 换成 RGB24 则是 1493 Mbps(第 5.1.3 节)——不压缩根本传不动。
30 秒实验
- 用 MediaInfo 看一个本地视频的【平均码率】,再用 宽×高×帧率 估算它的原始码率,两个数字相除。
- 把这个比值与第 5.3.2 节的 187 倍对照,看看你手上这份文件是偏高还是偏低。
常见误区
- 以为【预测和变换也会丢信息】。丢信息的只有量化,预测与变换都是可逆的表示变换。
- 以为编码与解码的工作量差不多。编码端要搜索、要决策,解码端只是照着执行,差一个量级。
- 把 QP 当成【质量旋钮】从 0 开始调。QP 太小会让码率爆炸,而且到某个点之后画质提升已经看不见了。
自测三问(点开对答案)
1. 1080p30 未压缩的码率大约是多少? —— 按 RGB24 算约 1493 Mbps,即 1.5 Gbps 左右。 2. 编码四步里哪一步真正丢信息? —— 量化。预测与变换只是换表示方式,不丢信息。 3. 编码端与解码端谁更费力? —— 编码端——它要在参考帧里搜索最佳预测,解码端只需按码流执行。- ☐ 下一节(7.2 视频采集原理)
相关笔记
- 视频采集原理 — 编码之前的那一段
- 视频编码原理 — 五步流程的原始讲法
- 量化 — 唯一丢信息的那一步
- 运动补偿 — 时间冗余怎么被用掉
- 🎬 FFmpeg入门详解 · 索引