📄 一句话概括
帧间编码参考别的帧,压缩率能到 I 帧的几十分之一——代价是它不能独立解码,出错的影响面也更大。
📝 本节和前面几节的关系
6.4.1 讲了只靠自己的那一类,这一节讲真正把视频压缩比拉上去的那一类。
一、帧间编码是什么
帧间编码的意思是:这一帧参考已经编码过的别的帧。 它利用的是时间冗余——相邻帧里同一位置的像素几乎一样。 参考方向有两种:只看前面(P 帧)、前后都看(B 帧)。 这两类帧不能独立解码,必须等参考帧解完才行。
二、省了多少
以以 I 帧大小为 100% 作基准: I 帧:100%——能独立解码; P 帧:约 30%——只参考前面; B 帧:约 15%——前后都参考。 所以一段视频里 I 帧越少,整体码率越低——但代价在下面。
三、代价是什么
不能独立解码——必须有参考帧在手,所以拖动定位要从 IDR 帧开始。 错误会传播——参考帧坏了,后面一串都跟着花屏。 解码要重排序——B 帧要求先解后面的帧,这就是 DTS 与 PTS 要分开的原因。 所以【压缩率】与【抗错能力】在这里是一对直接的矛盾。
四、和帧内编码的配合
实际码流从来不是【只用一种】,而是两者配合: I 帧放在开头与关键位置,提供可独立解码的落脚点; P/B 帧填在中间,把码率压下来。 两者的比例,就是 6.5.2 要讲的 GOP 长度——这是编码参数里最重要的一个取舍。
五、动手 Demo:三种帧,压缩率差多少
I 帧只靠自己,P 帧参考前面,B 帧参考前后。
rows = [("I 帧", "不参考", "100%", "能"),
("P 帧", "前面的帧", "约 30%", "不能"),
("B 帧", "前后都参考", "约 15%", "不能")]
for a, b, c, d in rows:
print("%-6s %-10s %-8s 能否独立解码:%s" % (a, b, c, d))
实跑输出:
--------------------------------------------------------------------
三种帧,压缩率差多少
--------------------------------------------------------------------
I 帧只靠自己,P 帧参考前面,B 帧参考前后。
帧类型 参考谁 典型大小 能否独立解码
----------------------------------------------------
I 帧 不参考 100% 能
P 帧 前面的帧 约 30% 不能
B 帧 前后都参考 约 15% 不能
一句话记:**I 帧贵、P 帧省、B 帧最省。**
所以一整段视频里,**I 帧越少越小,但出错的恢复代价也越大。**
一句话记:I 帧贵、P 帧省、B 帧最省。 所以一整段视频里,I 帧越少越小,但出错的恢复代价也越大。
30 秒实验
- 用 ffprobe 加
-show_frames看一段视频的帧类型序列。 - 数一下前 60 帧里有几个 I 帧。
常见误区
- 以为 I 帧越少越好。丢包恢复与拖动体验都会变差。
- 以为 B 帧一定优于 P 帧。B 帧要缓存与重排序,延迟更高。
自测三问(点开对答案)
1. 帧间编码利用的是哪一类冗余? —— 时间冗余——相邻帧同一位置的像素很接近。 2. I、P、B 帧的相对大小大概是多少? —— I 帧 100%、P 帧约 30%、B 帧约 15%。 3. 帧间编码的三个代价是什么? —— 不能独立解码、错误会传播、解码要重排序。- ☐ 下一节(6.4.3 运动矢量)
相关笔记
- 帧内编码 — 提供落脚点的那一类
- 运动矢量 — 帧间预测怎么找到参考块
- GOP详细讲解 — 两类帧怎么配比
- 🎬 FFmpeg入门详解 · 索引