🎬 第六章 音视频压缩编码基础
📄 一句话概括

帧间编码参考别的帧,压缩率能到 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 秒实验

  1. 用 ffprobe 加 -show_frames 看一段视频的帧类型序列。
  2. 数一下前 60 帧里有几个 I 帧。

常见误区

  1. 以为 I 帧越少越好。丢包恢复与拖动体验都会变差。
  2. 以为 B 帧一定优于 P 帧。B 帧要缓存与重排序,延迟更高。
自测三问(点开对答案) 1. 帧间编码利用的是哪一类冗余? —— 时间冗余——相邻帧同一位置的像素很接近。 2. I、P、B 帧的相对大小大概是多少? —— I 帧 100%、P 帧约 30%、B 帧约 15%。 3. 帧间编码的三个代价是什么? —— 不能独立解码、错误会传播、解码要重排序。

相关笔记