一文讲清 I 帧、P 帧、B 帧、GOP 与视频预测结构

前言:为什么很多人背过 I / P / B 帧,还是不理解视频编码

只要开始学 H.264 / H.265,几乎一定会碰到这些词:

  • I 帧
  • P 帧
  • B 帧
  • GOP
  • 参考帧
  • 预测结构

很多人对它们并不陌生,甚至在面试前也背过很多次。

但真正一问:

  • 为什么要分 I / P / B 帧
  • B 帧到底“厉害”在哪
  • GOP 为什么不是越长越好
  • 为什么 B 帧会让系统更复杂
  • 低延迟场景为什么经常要少用甚至不用 B 帧

就会开始发虚。

我觉得根本原因是:

很多人记住了名词,却没有真正理解“预测结构”这件事。

而视频编码真正的核心,不只是“把视频压小”,而是:

尽量不要每一帧都从零开始存。

这句话一旦理解透,I / P / B 帧的存在意义、GOP 的作用、编码延迟和系统复杂度,都会顺很多。

所以这篇文章的目标,不是把你变成标准文档阅读器,而是把这几个最核心的问题讲明白:

  • I / P / B 帧到底分别在做什么
  • 参考关系为什么能大幅提升压缩效率
  • GOP 本质上在组织什么
  • 为什么压缩率、延迟、复杂度和兼容性会被这些结构直接影响

而且这次我会明显多放结构图和时序图,把“帧之间的关系”尽量讲得有画面感。


一、先给一句最重要的话:I / P / B 帧,本质上是在决定“当前帧到底要不要依赖别人”

如果让我先用一句话概括 I / P / B 帧的区别,我会这样说:

I / P / B 帧,本质上是在决定当前帧的编码时,到底要不要参考其他帧,以及参考谁。

可以先粗略记成:

  • I 帧:尽量独立编码,不依赖别的帧
  • P 帧:参考前面的帧
  • B 帧:可以同时参考前后帧

注意,这里最关键的词不是“关键帧”“预测帧”“双向预测帧”这些定义本身,而是:

依赖关系。

一旦你把“依赖关系”这条主线抓住,后面很多现象都会变得合理:

  • 为什么 I 帧更大
  • 为什么 P 帧通常更省
  • 为什么 B 帧压缩率高但系统更复杂
  • 为什么解码顺序和显示顺序可能不一样

二、先看总图:视频编码为什么不能每一帧都从零开始存

假设有一段视频,是一个人站在镜头前轻微移动。

如果每一帧都完全独立编码,会发生什么?

  • 前后帧里大量内容其实几乎一样
  • 系统会重复存储很多相同信息
  • 数据量会非常不划算

所以编码器真正聪明的地方在于:

它不总是“把当前帧完整记下来”,而是尽量只记录“当前帧和参考帧有什么不同”。

先看一张抽象图。

flowchart LR
    A[前一帧] --> B[当前帧]
    B --> C[后一帧]

    A --> D[大量信息相似]
    B --> D
    C --> D

    D --> E[编码器尝试记录差异而不是重复内容]

这就是视频预测结构的出发点。

所以从本质上说,I / P / B 帧并不是“人为硬分类型”,而是编码器为了更高效利用帧间冗余,采用的不同策略。


三、I 帧到底是什么,为什么它最“稳”但也最“贵”

3.1 I 帧的本质

I 帧可以理解成:

一帧尽量独立编码的图像。

它不依赖前后其他帧的运动信息来完成主要重建。

注意,这里的“不依赖”是指不依赖别的帧,不代表它内部什么预测都不用。

在实际编码器里,I 帧内部仍然可能使用帧内预测,但它不依赖其他时间上的参考帧。

3.2 为什么 I 帧重要

因为它是整条预测链路的“锚点”。

有了 I 帧,解码器即使没有前面的参考历史,也能从这里重新开始把图像还原出来。

所以 I 帧通常承担这些角色:

  • 随机访问起点
  • GOP 的起始点
  • 丢包或错误恢复的重新同步点

3.3 为什么 I 帧通常更大

因为它没有利用时间上的参考关系,只能更多依赖当前帧自身信息来表达画面。

所以在相同画质条件下,I 帧往往比 P / B 帧大。

3.4 一张图看懂 I 帧的角色

flowchart TD
    A[I 帧] --> B[独立起点]
    A --> C[随机访问更方便]
    A --> D[错误恢复更容易]
    A --> E[通常码率开销更高]

所以你可以把 I 帧理解成:

最稳、最独立、但也最贵的一类帧。


四、P 帧到底是什么,为什么它是视频压缩里的主力

4.1 P 帧的本质

P 帧可以理解成:

当前帧参考前面的某一帧或多帧,只记录差异信息来完成编码。

这里最常见的直觉是:

  • 如果画面大部分没变,就没必要全存
  • 只要告诉解码器“和前面那帧相比哪里变了”,就能省很多数据

4.2 P 帧为什么更省

因为它利用了时间冗余。

连续视频帧之间通常不会完全无关,所以很多内容都可以从前面的参考帧推导出来。

编码器只需要记录:

  • 当前块参考了哪一块
  • 移动了多少
  • 剩余误差是多少

这就是为什么 P 帧通常比 I 帧更小。

4.3 P 帧的代价是什么

代价就是:

它不再独立。

一旦参考帧丢了、坏了,后面的 P 帧恢复也会受影响。

4.4 一张图看懂 P 帧

flowchart LR
    A[I / P 参考帧] --> B[P 帧]
    B --> C[记录和前面参考帧的差异]
    C --> D[码率更低]
    C --> E[依赖链变长]

所以 P 帧可以理解成:

通过参考过去来换取更高压缩率。


五、B 帧到底是什么,为什么它压缩率高但系统复杂度也更高

5.1 B 帧的本质

B 帧可以理解成:

当前帧在编码时,可以同时参考前面的帧和后面的帧。

这就是所谓“双向预测”。

换句话说,编码器在看当前帧时,不只是能问:

  • 它和前一帧像不像

还可以问:

  • 它和后一帧像不像
  • 两边一起参考会不会更省

5.2 为什么 B 帧更省

因为多了“前后都能参考”的自由度,编码器更容易找到更合适的预测方式。

于是:

  • 残差更小
  • 压缩效率更高
  • 平均码率可能进一步下降

5.3 为什么 B 帧更复杂

因为它会带来非常重要的系统副作用:

  • 编码器要看到“后面的帧”才能决定怎么编码当前 B 帧
  • 输入顺序、编码顺序、显示顺序可能不再一致
  • 解码缓存和时间戳处理会更复杂
  • 延迟通常会上升

5.4 一张图看懂 B 帧的参考关系

flowchart LR
    A[前参考帧] --> B[B 帧]
    C[后参考帧] --> B
    B --> D[双向预测]
    D --> E[更高压缩率]
    D --> F[更高复杂度与更高延迟]

所以 B 帧可以理解成:

最会省码率,但也最会增加系统复杂度的一类帧。


六、一张对比图,把 I / P / B 帧一次讲清楚

flowchart TD
    A[I 帧] --> A1[不依赖其他帧]
    A --> A2[更独立]
    A --> A3[更大]

    B[P 帧] --> B1[参考过去帧]
    B --> B2[更省码率]
    B --> B3[有依赖]

    C[B 帧] --> C1[参考前后帧]
    C --> C2[压缩率更高]
    C --> C3[时序更复杂]
    C --> C4[延迟更高]

如果你现在要先形成一个稳定直觉,就记:

  • I:独立、稳、但贵
  • P:参考过去,省码率,主力结构
  • B:参考前后,更省,但更复杂

这已经足够让你先站稳。


七、GOP 到底是什么,它本质上在组织什么

接下来进入另一个高频词:

GOP。

很多人知道它翻译成 Group of Pictures,但真正关键的是:

它到底在组织什么?

7.1 GOP 的本质

GOP 可以理解成:

一组按照特定预测结构组织起来的连续帧。

也就是说,GOP 不是简单“几帧放一起”,而是:

  • 这组帧里谁当起点
  • 谁参考谁
  • 参考链有多长
  • 多久插一个 I 帧

7.2 一个最简单的 GOP 例子

比如:

1
I P P P P

或者:

1
I B B P B B P

这些都可以看成不同的 GOP 结构。

7.3 GOP 真正影响什么

GOP 会直接影响:

  • 随机访问能力
  • 压缩效率
  • 错误恢复能力
  • 编码延迟
  • 解码复杂度

所以 GOP 的问题,本质上是:

你想用什么样的预测组织方式,在码率、延迟、复杂度和恢复能力之间做取舍。


八、一张 GOP 结构图看懂“预测组织”到底是什么意思

8.1 只有 I/P 的简单 GOP

flowchart LR
    I[I] --> P1[P]
    P1 --> P2[P]
    P2 --> P3[P]
    P3 --> P4[P]

这种结构的特点是:

  • 简单
  • 延迟相对低
  • 压缩率不错
  • 系统实现比带 B 帧简单

8.2 带 B 帧的 GOP

flowchart LR
    I[I] --> P1[P]
    I --> B1[B]
    P1 --> B1
    I --> B2[B]
    P1 --> B2
    P1 --> P2[P]
    P1 --> B3[B]
    P2 --> B3
    P1 --> B4[B]
    P2 --> B4

这张图虽然抽象,但很重要,因为它体现出:

  • B 帧并不是“排在中间就完了”
  • 它真正关键的是参考关系更复杂

所以 GOP 不是一个“长度参数”这么简单,而是一个完整的预测组织方案。


九、为什么 GOP 不是越长越好,也不是越短越好

这个问题特别适合面试。

9.1 GOP 长一点的好处

如果 GOP 更长,通常意味着:

  • I 帧更少
  • 平均码率更低
  • 压缩效率可能更高

因为 I 帧通常最贵,少放几个自然更省。

9.2 GOP 长一点的代价

但代价也很明显:

  • 随机访问更差
  • 错误恢复更慢
  • 一旦参考链断掉,影响范围更大
  • 某些场景下延迟和复杂度会更明显

9.3 GOP 短一点的好处

如果 GOP 更短,通常意味着:

  • I 帧更密
  • 起播、拖动、切片、恢复更方便
  • 错误影响更局部

9.4 GOP 短一点的代价

代价就是:

  • I 帧多
  • 平均码率更高
  • 压缩效率下降

所以你会发现,GOP 长短不是单纯谁好谁坏,而是业务目标不同。


十、一张图看懂 GOP 长短背后的 trade-off

flowchart TD
    A[GOP 更长] --> B1[I 帧更少]
    A --> B2[压缩率更高]
    A --> B3[随机访问更差]
    A --> B4[错误恢复更慢]

    C[GOP 更短] --> D1[I 帧更密]
    C --> D2[更易恢复与定位]
    C --> D3[码率更高]
    C --> D4[压缩率下降]

你可以把这张图直接记成一句话:

GOP 越长越省,但越不灵活;GOP 越短越稳,但越贵。


十一、为什么 B 帧会影响延迟和时序

这是工程里特别重要的一块。

很多人知道 B 帧压缩率高,但不知道它为什么会拉高系统复杂度。

11.1 B 帧的问题不是“解码更慢”这么简单

更根本的问题是:

它需要看到后面的参考帧,才能把当前帧编码好。

这意味着:

  • 编码器不能总是来一帧就立刻决定全部输出
  • 系统要缓存更多帧
  • 输出顺序可能和输入顺序不一致

11.2 一张时序图看懂 B 帧为什么会引入重排序

sequenceDiagram
    participant In as 输入顺序
    participant Enc as 编码器
    participant Out as 显示顺序

    In->>Enc: I
    In->>Enc: B
    In->>Enc: B
    In->>Enc: P

    Note over Enc: 为了编码 B,需要先知道后面的 P

    Enc->>Out: I
    Enc->>Out: P
    Enc->>Out: B
    Enc->>Out: B

这张图最关键的不是精确标准顺序,而是让你理解:

输入顺序、编码顺序、显示顺序可能不再一致。

这就是:

  • PTS / DTS 更复杂
  • buffer 更复杂
  • 低延迟系统更讨厌 B 帧

的根本原因。


十二、低延迟场景为什么经常少用甚至不用 B 帧

这也是一个非常高频的工程问题。

12.1 低延迟场景最怕什么

低延迟场景最怕:

  • 编码前等待
  • 队列积压
  • 解码缓存太深
  • 显示端拿不到最新帧

而 B 帧恰恰会增加这些风险。

12.2 所以常见的选择是什么

很多低延迟场景里,会更偏向:

  • I + P 结构
  • 少量或不用 B 帧
  • 更短的 GOP
  • 更保守的预测结构

这样做虽然会牺牲一些压缩率,但能换来:

  • 更低延迟
  • 更简单时序
  • 更好控制系统行为

这也是为什么:

  • 直播推流
  • RTC
  • 车载实时预览
  • 低延迟监控预览

这类场景对预测结构通常会更保守。


十三、用代码看:FFmpeg 里这些结构通常会体现在哪些参数上

这部分不追求写得像生产代码,但要给你工程感。

13.1 设置 GOP 大小和 B 帧数量

1
2
3
4
5
6
7
8
9
AVCodecContext *ctx = avcodec_alloc_context3(codec);
ctx->width = 1920;
ctx->height = 1080;
ctx->time_base = (AVRational){1, 25};
ctx->framerate = (AVRational){25, 1};
ctx->pix_fmt = AV_PIX_FMT_YUV420P;

ctx->gop_size = 50; // GOP 大小
ctx->max_b_frames = 2; // 最多使用 2 个 B 帧

这段代码很适合建立一个直觉:

  • gop_size 会影响 I 帧间隔
  • max_b_frames 会影响预测结构复杂度

13.2 低延迟场景的常见思路

1
2
ctx->gop_size = 25;
ctx->max_b_frames = 0;

这通常意味着:

  • GOP 更短
  • 没有 B 帧
  • 更适合低延迟场景

当然真实项目里还会结合编码器私有参数,但这已经足够体现主思路。


十四、工程里最常见的几个误区

14.1 误区一:I 帧就是“完整图片”,P / B 帧就是“不完整图片”

这种说法太粗糙了。

更准确的理解应该是:

  • I 帧主要不依赖其他帧
  • P / B 帧主要依赖参考帧结构

重点在“依赖关系”,不是“完整 / 不完整”这种口语化理解。

14.2 误区二:B 帧一定更好

不是。

B 帧通常更省码率,但会引入:

  • 更高延迟
  • 更复杂时序
  • 更复杂缓存

在低延迟场景下,它反而可能不合适。

14.3 误区三:GOP 越长越高级

也不是。

GOP 长短本质上是业务取舍:

  • 长 GOP 更省码率
  • 短 GOP 更灵活、更稳

14.4 误区四:面试里背定义就够了

不够。

面试官更关心你知不知道:

  • 为什么这么设计
  • 会影响什么
  • 适合什么场景

十五、面试里怎么讲,才不像只会背术语

如果面试官问:

你怎么理解 I 帧、P 帧、B 帧和 GOP?

我建议你按下面这个结构讲。

15.1 先讲本质

这几种帧类型本质上是在决定当前帧编码时对其他帧的依赖关系。I 帧尽量独立,P 帧参考过去帧,B 帧可以参考前后帧。

15.2 再讲为什么这么设计

这么设计的核心目的是利用视频连续帧之间的时间冗余,避免每一帧都从零开始编码,从而提高压缩效率。

15.3 再讲工程影响

I 帧更独立但码率开销更大,P 帧是视频编码里的主力结构,B 帧压缩率更高但会增加时序复杂度和编码延迟。GOP 则是在组织这组预测关系,它会影响压缩率、恢复能力、随机访问和低延迟表现。

15.4 最后结合场景

比如低延迟场景通常会减少甚至不用 B 帧,GOP 也往往不会拉得太长;而更偏存储和点播的场景则可以接受更复杂的预测结构来换更高压缩率。

如果你能这么讲,面试官基本就能听出你是真的理解过,而不是只背了“关键帧、预测帧、双向预测帧”。


总结:I / P / B 帧和 GOP,本质上是在组织“视频怎么参考自己”

回到这篇文章最开始的问题:

I 帧、P 帧、B 帧和 GOP 到底该怎么理解?

我觉得最稳的一条主线就是:

  • 视频编码不想每一帧都从零开始存
  • 所以要利用前后帧之间的相似性
  • I / P / B 帧是在定义不同的参考方式
  • GOP 是在组织一组连续帧的参考关系

于是它们就共同决定了这些关键结果:

  • 压缩率
  • 码率开销
  • 随机访问能力
  • 错误恢复能力
  • 时序复杂度
  • 编码延迟

如果把这条线理解透了,后面你再去看:

  • H.264 / H.265 编码流程
  • 码率控制
  • PTS / DTS
  • FFmpeg 编码行为
  • 低延迟链路设计

都会容易很多。

因为到那时你已经不再只是记住几个帧名字,而是真的明白了:

视频编码真正厉害的地方,是它让视频学会了“参考自己”。


一文讲清 I 帧、P 帧、B 帧、GOP 与视频预测结构
https://breaker505.github.io/2026/03/29/i-p-b-frames-gop-and-video-prediction/
作者
爱发呆的鱼
发布于
2026年3月29日
许可协议