
相关服务:香港GPU服务器
YUV 色彩空间(特别是 YUV 4:2:0 采样)。
简单来说,它解释了为什么视频文件能在保持清晰的同时,体积还能压得那么小。以下是详细拆解:
1. 核心公式:视频信号 = 亮度 + 色度
图左侧展示了图像是如何分解的:
-
Luma (Y): 亮度分量。它是图像的黑白底色,包含了细节和轮廓。人类的眼睛对亮度非常敏感。
-
Chroma (UV): 色度分量。它给图像“上色”。人类的眼睛对颜色的分辨率其实没有对亮度那么高。
-
结论: 只要保证亮度(Y)清晰,稍微压缩一下颜色(UV),肉眼很难发现区别。
2. YUV 4:2:0 采样原理
图右侧那堆密密麻麻的 Y 和 U/V 字母解释的是采样方式:
-
Y (Luma): 每一个像素点都有一个 Y。如图所示,Y 是铺满的。
-
U/V (Chroma): 并不是每个像素都有自己的颜色信息。在 4:2:0 采样中,每 4 个亮度像素(2x2 的小方格)共用一组 U 和 V。
-
为什么要这样做?
通过这种方式,颜色的数据量直接减少了 75%。因为 Y(亮度)保留了所有细节,你看起来图像依然很清晰,但文件体积却大大缩小了。
3. 图中各部分含义
-
左图(眼睛): 直观对比。左边是成品,中间是黑白的亮度图(决定清晰度),右边是模糊的色度图(决定颜色)。
-
右侧字母阵列: 演示了 Y 和 UV 的分布。你可以看到红色的
U和V只有在特定的Y节点之间才出现。 -
箭头指向的右侧 U 矩阵: 表示提取出来的色度分量,它的密度明显比 Y 稀疏很多。
总结
这节课讲的是 “人眼视觉特性”在视频压缩中的应用。
它告诉你:为了省带宽和空间,视频工程师把颜色给“减配”了,但利用人眼的弱点,让你觉得画质没变。 这种技术被广泛应用于 H.264、H.265 等几乎所有的现代视频格式中。

这张图解释的是视频压缩技术的底层逻辑——数据冗余(Redundancy)。
简单来说,视频之所以能压缩,是因为原始数据里有很多“废话”和“重复的信息”。图中重点介绍了两种最主要的冗余类型:
1. 空间冗余 (Spatial Redundancy)
-
含义: 指的是单张图片内部相邻像素之间的相似性。
-
图中解释: 比如一张图片里有一片蓝天,或者像图中这种白色的背景。如果你把图像分成很多 $16 \times 16$ 的小方块(宏块),你会发现很多相邻的方块长得几乎一模一样。
-
压缩逻辑: 既然大家都一样,我就没必要记录每一个像素点的颜色,我只需要记录“这一片全是白色”或者“参考左边那个块的值”就行了。
-
应用: 这就是 帧内压缩 (Intra-frame coding)。
2. 时间冗余 (Temporal Redundancy)
-
含义: 指的是视频前后两帧之间内容的相似性。
-
图中演示: 注意看那个“在线秒表”。
-
左边是 $01.420$ 秒,右边是 $10.836$ 秒。
-
虽然时间变了,但你会发现秒表周围的背景、按钮、甚至是“在线秒表”这几个字,在前后几十帧甚至几百帧内都是完全没有变化的。
-
-
压缩逻辑: 如果两帧图像之间只有秒表的数字变了,其他地方都没动,那我在存下一帧的时候,只记录变了的那个数字部分,不变的地方直接复用前一帧的数据。
-
应用: 这就是 帧间压缩 (Inter-frame coding),也就是我们常听到的 I帧、P帧、B帧 的核心原理。
总结:他在讲什么?
这张课件是在告诉你:视频压缩不是靠变魔术,而是靠“找相同”。
-
空间冗余 是在一张画里找相同(横向找)。
-
时间冗余 是在一串画里找相同(纵向找)。
通过消除这些重复的信息,视频文件的大小可以从几十 GB 压缩到几百 MB,而你看起来画质却没怎么下降。
你这是在看音视频基础原理的视频吧?这部分内容是理解视频编码格式(如 H.264/AVC)最基础的理论依据。有什么具体的术语没听懂吗?

这张图进入了视频压缩最核心的实战环节:GOP(画面组)结构以及 I、P、B 帧的原理。
它解释了视频是如何利用前面提到的“时间冗余”来省空间的,同时引出了一个非常关键的副作用——延迟。
1. 三种帧类型的分工(找不同)
图中展示了三种不同角色的帧,它们各司其职:
-
I 帧 (Intra-coded frame): 关键帧。
-
它是完整的图像,不依赖任何其他帧。
-
图中位置: 最左边。它是整个序列的“祖宗”,后面的帧都要参考它。
-
-
P 帧 (Predictive-coded frame): 前向预测帧。
-
原理: 它只记录与前一帧(I 或 P)的差别。
-
图中演示: 注意看最右边的 P 帧,它发现三角形没变,只有长方体变了,所以它“只记录长方体”的移动和变化。
-
-
B 帧 (Bipredictive-coded frame): 双向预测帧。
-
原理: 它最“鸡贼”,既看前面的帧,又看后面的帧。
-
图中演示: 中间那个 B 帧,它参考了左边的 I 帧(看三角形)和右边的 P 帧(看圆形和长方体),通过两头对比,算出自己的内容。它的压缩率最高,体积最小。
-
2. 两个关键顺序:解码 vs. 显示
这是图中非常硬核的部分,解释了为什么直播会有延迟:
-
显示顺序 (1 -> 2 -> 3): 这是我们要看到的正常时间线(I 帧 -> B 帧 -> P 帧)。
-
解码顺序 (1 -> 3 -> 2): 这是播放器处理数据的真实顺序。
-
重点: 因为 B 帧(第 2 帧)需要参考后面的 P 帧(第 3 帧)才能计算出来。
-
结果: 播放器必须先拿到第 1 帧,再拿到第 3 帧,最后才能把第 2 帧拼出来。
-
3. B 帧带来的代价:编码延迟
图中右侧红字写着:“B 帧带来编码延迟”。
-
原因: 如果你是在做直播,采集到了第 2 帧(B 帧),你不能马上发出去,你必须等第 3 帧(P 帧)也拍好了,才能把这两帧一起编码发走。
-
结论: * 追求极高压缩率(存电影): 多用 B 帧,文件小。
-
追求极低延迟(视频通话、直播): 通常会禁用 B 帧,只用 I 帧和 P 帧,因为这样画面拍到就能立刻发出去,不用等后面的帧。
-
总结
这张图的核心结论是:为了达到更高的压缩比,我们引入了双向参考的 B 帧,但也因此付出了“等待后续帧”的时间代价。
所以下面的0号秒编码i帧
是的,你抓住了重点。
图中底部的红字 “0ms: 编码I帧 ---- 直接发送出去” 解释了直播或实时视频传输中的起步逻辑:
1. 为什么 0 毫秒必须是 I 帧?
因为 I 帧是“自给自足”的。在视频流刚开始(0ms)或者播放器刚点进去的那一刻,它手里没有任何参考数据。如果不发一个完整的 I 帧,解码器就没法画出第一张画。
2. “直接发送出去”意味着什么?
这对应了低延迟的需求:
-
无依赖: I 帧不需要等待后续的 P 帧或 B 帧。
-
零延迟处理: 只要摄像头采集完这一帧,编码器立刻就能把它打包发给观众。
-
建立基准: 这一帧发出后,后面的 P 帧就可以基于这一帧去计算“变动的地方”了。
3. 结合你之前的图来看
如果你在 0ms 发送的是一个 B 帧,那麻烦就大了:
-
观众的电脑得先收到 0ms 的 B 帧(打不开,得等),再收到 40ms 甚至 80ms 后的 P 帧。
-
这样观众看到第一张脸的时间,就至少落后了 80 毫秒以上。
这里的逻辑链条是:
-
0ms: 采集到第 1 帧画面。
-
编码为 I 帧: 体积虽然大(包含全部像素),但不需要等别人。
-
立刻发送: 观众端秒开,并以此为基础,等待后续 40ms、80ms 发来的 P 帧增量数据。
所以说,I 帧是视频流的“锚点”。 无论是刷短视频的第一秒,还是直播点进去的一瞬间,你接收到的第一个包绝对是一个 I 帧。
你现在看这几张图,是不是已经能把色彩空间(YUV)、**数据冗余(找相同)和帧类型(I/P/B)**这三者串起来了?这正是视频系统从“图像”变成“流”的完整过程。
所以先发p帧再发b帧
对头!在包含 B 帧的视频流中,**传输顺序(和解码顺序一致)**确实是先发 P 帧,再发 B 帧。
我们可以用你图里的逻辑梳理一个“时间线”,你就能秒懂为什么必须“插队”:
1. 现实中的顺序(显示顺序)
假设每帧间隔 40ms:
-
第 1 帧 (0ms): I 帧(我是祖宗,直接发)。
-
第 2 帧 (40ms): B 帧(我要看前后两帧)。
-
第 3 帧 (80ms): P 帧(我只看前面的 I 帧)。
2. 传输和解码的顺序(插队逻辑)
为了让第 2 帧(B 帧)能顺利解出来,服务器必须玩个花招:
-
先发 I 帧 (第 1 帧): 客户端收到,直接画出来。
-
跳过 B 帧,先发 P 帧 (第 3 帧): 客户端收到,先憋着不显示,存进缓存里。
-
再发 B 帧 (第 2 帧): 此时客户端手里既有 I 帧,又有 P 帧,终于可以把夹在中间的 B 帧算出来了。
所以结论是:
解码/传输顺序: I -> P -> B
显示顺序: I -> B -> P
3. 这也就是为什么直播会“卡”或者“延迟”
-
编码端: 摄像机拍到了第 2 帧,但它不能发,它得等第 3 帧拍完。这一下就白白等了 40ms。
-
解码端: 观众手机收到了第 3 帧,也不能显示,得等第 2 帧到了才能一起排队显示。
总结一下你的思路:
你说的非常对。在有 B 帧的情况下,P 帧必须比 B 帧先走,因为 P 帧是 B 帧的“参照物”。
一个小考点:
如果老师问你,如何把直播延迟降到最低?
你现在就可以抢答:“把 B 帧删了,全部改成 I 帧和 P 帧,这样就不存在‘等下一帧’的逻辑,拍到哪发到哪!”(这就是为什么很多低延迟直播协议,比如 WebRTC,默认都不用 B 帧的原因)。

这张图通过时间线(Timeline)的方式,彻底拆解了为什么 B 帧会导致延迟的物理过程。它把每一毫秒发生的事情都列出来了,非常硬核。
我们按照图中的时间点(假设帧间隔是 40ms)来翻译一下:
1. 0ms:起步阶段
-
动作: 摄像头采集到第 1 帧,编码为 I 帧。
-
状态: 因为 I 帧不依赖别人,所以立刻直接发送。
-
结果: 延迟为 0(理想状态下)。
2. 40ms:尴尬的等待期
-
动作: 摄像头采集到第 2 帧,按照算法,这一帧打算编成 B 帧。
-
困境: 图中红字写着 “是否能编码 B 帧?不能完成编码”。
-
原因: 因为 B 帧是双向参考的,它需要知道“未来的第 3 帧”长什么样才能动笔。此时第 3 帧还没拍出来呢!
-
结果: 40ms 的时候没有数据可以发送。网络是空闲的,观众在干等。
3. 80ms:爆发式补发
-
动作: 终于,第 3 帧(P 帧)拍出来了。
-
逻辑: 1. 编码器终于集齐了第 1 帧和第 3 帧,现在可以回头把 40ms 时的那个 B 帧 编出来了。
2. 此时手里有两颗“炮弹”:第 3 帧(P 帧)和第 2 帧(B 帧)。
-
发送顺序: 按照咱们刚才讨论的,先发第三帧 P 帧,再发第二帧 B 帧。
-
代价: 此时第 2 帧已经迟到了整整 40ms 甚至更多,这就是所谓的编码延迟。
4. 图中那个关键的提问
图中有一行小字问:“编码的时间点为啥 P 帧是在 B 帧后面,如果 P 帧在前面不就没有延迟了?”
这其实是一个很好的反向思考:
-
如果视频里全是 I P P P 这样的序列(没有 B 帧),那么 40ms 的时候拍到 P 帧,P 帧只参考前面的 I 帧,它可以立刻发走。
-
结论: 确实,去掉 B 帧,延迟就消失了。但代价是文件会变大,因为 P 帧的压缩率没有 B 帧高。
总结
这张图的核心是在算账:
为了省点流量(用 B 帧),你必须在时间线上“憋”一帧的时间。
这就是为什么在打游戏、视频通话、互动直播时,技术人员会咬牙切齿地把 B 帧关掉——因为实时性比省那点流量重要得多。
你现在对这个“憋数据”的过程理解了吗?这就是音视频开发里著名的 PTS(显示时间戳) 和 DTS(解码时间戳) 不一致的根本原因。
为什么可以没有b帧
可以没有 B 帧,是因为 B 帧(双向预测帧)虽然是“压缩高手”,但它不是“必需品”。
视频编码器完全可以只用 I 帧和 P 帧来工作。以下是为什么可以没有 B 帧的三个核心原因:
1. 为了极低的延迟(实时性优先)
这是不使用 B 帧最常见的理由。
-
有 B 帧: 编码器必须等到“未来”的帧产生后,才能回头编码当前的 B 帧。这会导致至少 1-2 帧的物理等待延迟。
-
没有 B 帧: 采用 IPPP 模式。每一帧 P 帧只参考它前面的帧。摄像头拍到一帧,编码器立刻就能算出一帧,算完立刻发走。
-
应用场景: 视频通话(微信/飞书)、云游戏、远程监控、低延迟直播。在这些场景下,哪怕视频体积大一点,也要保证画面能“秒到”。
2. 降低硬件性能开销
-
内存占用: 编码或解码 B 帧时,设备需要同时在内存里缓存“前一个参考帧”和“后一个参考帧”。如果去掉 B 帧,缓存压力会减小。
-
计算复杂度: B 帧的算法最复杂(它要进行双向运动补偿)。对于一些低功耗的嵌入式设备、老旧的监控摄像头,它们可能跑不动复杂的 B 帧算法,所以直接舍弃。
3. 编辑和剪辑的便利性
-
在专业的视频剪辑领域(如 ProRes 或 DNxHR 格式),经常甚至连 P 帧都不要,只保留 全 I 帧(All-Intra)。
-
如果没有 B 帧(甚至没有 P 帧),剪辑软件在拖动时间轴时,不需要进行复杂的跨帧换算,电脑性能损耗极低,每一帧都是独立的,剪辑极其流畅。
总结:性能与体积的博弈
你可以把视频编码想象成存钱:
-
I 帧 是全额现金(体积大,最稳)。
-
P 帧 是欠条(只记变化量,体积小)。
-
B 帧 是极其复杂的金融衍生品(体积最小,但计算和兑现都要花时间)。
如果你追求省空间(存硬盘看电影),B 帧越多越好;
如果你追求快(打视频电话),B 帧就是累赘,必须去掉。
你现在接触到的这套知识点,其实就是音视频开发中经常听到的 “低延迟优化” 的核心。在你的实验环境(SRS、FFmpeg)中,如果你推流时加上 -bf 0 参数,就是在强制告诉编码器:“我不要 B 帧,我要快!”
这个逻辑在你之前的实验(SRS + Docker)中实践过吗?

这张图讲的是音视频开发中一个非常关键的参数:GOP(Group of Pictures,画面组)长度,以及它如何影响直播的秒开(首屏加载速度)。
图中通过对比解释了:为什么在直播领域,GOP 不能设置得太长。
1. 什么是 GOP?
GOP 是指两个 I 帧 之间的间隔。
-
如图中所示,一个 GOP 是从一个 I 帧开始,后面跟着一堆 P 帧或 B 帧,直到下一个 I 帧出现前结束。
-
GOP Length 计算公式:$秒数 \times 帧率$。图中举例:$5秒 \times 25fps = 125帧$。
2. 直播痛点:为什么 GOP 5 秒太长了?
图中用两条彩色线展示了观众点进直播间时的两种命运:
-
运气好(红线): * 观众点进直播间时,服务器刚好正在发 I 帧。
-
结果: 播放器拿到 I 帧直接解码显示,画面秒开。
-
-
运气差(蓝线 - “完美错过 I 帧”):
-
观众点进直播间时,I 帧刚发完,现在正在发 P 帧。
-
致命问题: 播放器手里没有“祖宗”I 帧,根本解不出这些 P 帧。
-
结果: 观众必须等。如果 GOP 是 5 秒,极端情况下观众要对着黑屏等 接近 5 秒,直到下一个 I 帧出现。
-
3. 直播领域的黄金准则
图中的核心结论是:直播领域的 GOP 绝对不能设置太长。
-
电影/视频文件: GOP 可以很长(比如 10 秒),因为你可以随意拖动进度条,播放器会预读,而且文件体积小。
-
直播间: 为了保证用户“秒开”,通常 GOP 设置为 1-2 秒。
-
这样观众最倒霉也就等 1 秒多就能看到画面。
-
虽然 I 帧多了会导致文件稍微大一点点,但为了首屏秒开的体验,这个代价是必须付出的。
-
总结
这张图解释了**用户体验(秒开)与压缩效率(GOP 长度)**之间的平衡:
-
I 帧是进入直播间的门票。
-
GOP 越长,门票发的频率越低,新来的观众等得就越久。
-
5 秒的 GOP 会让直播间流失大量新观众。
你之前在配置 SRS 服务器或者用 FFmpeg 推流时,有没有注意到 -g 或者 gop_size 这个参数?通常我们会设为帧率的 1 倍或 2 倍。你在自己搭建的直播环境下测试过不同 GOP 长度的加载速度吗?

这张图是对前面几张散点知识的官方总结和定义。它把 GOP 的概念从“直观理解”上升到了“工程参数”层面。
以下是这张课件的核心知识点拆解:
1. 引入了更专业的术语:IDR 帧
-
定义: 每一个序列的第一个图像叫做 IDR 图像(Instantaneous Decoding Refresh,立即刷新图像)。
-
关系: IDR 图像一定是 I 帧,但 I 帧不一定是 IDR 帧。
-
作用: IDR 帧是一个“断层”标记。它告诉解码器:“从我这里开始,清空所有缓存,前面的参考帧都作废,大家从头开始看。”
-
GOP 长度: 两个 IDR 帧之间的距离。
2. GOP 长度的影响(博弈论)
这里总结了一个非常经典的工程矛盾:
-
GOP 越大(I 帧越稀疏): * 优点: 压缩效率越高(因为 I 帧最占空间,P/B 帧多,文件就小)。
-
缺点: 视频流恢复能力差(如果你网络抖动丢了一个包,可能要等好几秒画质才能恢复正常)。
-
-
反之亦然: GOP 越小,视频越大,但抗网络波动能力强,点进去显示得也快。
3. 实战参数建议
课件给出了非常具体的工业配置参考:
-
直播场景: 如果一秒 25 帧,GOP 设置为 25 或 50(即 1 秒或 2 秒发一个 I 帧)。这是为了兼顾“秒开速度”和“流畅度”。
-
非直播流(点播/存文件): * 可以把 B 帧设置为连续 2 帧(比如
IBBPBBP...)。-
目的: 极大地降低码率(文件体积),反正用户是下载着看或者点播看,不差那点编码延迟。
-
💡 深度分析:为什么是“帧率的倍数”?
图中提到 “一般是帧率的倍数”。这样做是为了保证 GOP 的时长是整数秒。
如果你设置 GOP 为 50,帧率 25,那么正好每 2 秒一个 I 帧。这对于服务器计算切片(比如 HLS 协议的 .ts 文件)非常友好,能对齐时间戳。
总结
这张课件是把你之前的零散感觉转化成了可操作的配置代码。比如你之后用 FFmpeg 推流,你就会知道为什么要写 -g 50 -bf 2 这样的参数了。
你看到这里,音视频压缩的“时间、空间、质量”三者之间的三角博弈关系应该已经非常清晰了。这些基础打扎实了,以后调优推流服务器(SRS)时,你就知道每个参数背后的意义了。
为什么设置b帧降低码率
设置 B 帧之所以能显著降低码率(即减小文件体积),核心原因在于它的参考机制比 P 帧更“贪婪”,从而实现了更高的压缩效率。
我们可以从以下几个维度来理解:
1. “双向预测”:更精确的找不同
-
P 帧(单向): 只看前面的画。它记录的是:“我比前一帧多了什么、动了什么”。
-
B 帧(双向): 既看前面,又看后面。它记录的是:“我处在前面这帧和后面这帧的中间,我是怎么演变过去的”。
-
为什么更省钱? 想象你在画一个飞行的皮球。P 帧只能根据上一帧推测球的位置;而 B 帧知道球从哪里来,也知道球要往哪里去。有了前后两个参考点,它描述“变化”所需的字节数就极少。
2. 极高的压缩比
在视频编码的“三兄弟”里,它们的体积通常呈现这样的比例:
-
I 帧: 像是一张高质量的 JPEG 照片(100% 体积)。
-
P 帧: 经过压缩,体积可能只有 I 帧的 20% - 50%。
-
B 帧: 压缩最狠,体积通常只有 I 帧的 5% - 10%。
-
结论: 在同样的画质下,你放的 B 帧越多,整个视频序列(GOP)的总大小就越小。
3. “物尽其用”:利用人眼的生理弱点
-
B 帧在设计上就被定义为“非参考帧”(通常情况下)。这意味着 B 帧即便丢了一点细节,也不会影响到后面帧的清晰度。
-
编码器会故意给 B 帧分配更低的质量(更高的量化参数值),反正它只是一闪而过的过渡。利用这种“牺牲”,换取了极大的码率节省。
形象比喻:
如果把视频编码比作补全一句话:
-
I 帧: “今天天气真的非常不错。”(全文完整记录)
-
P 帧: “同上,多了一个‘哈’字。”(参考前面,记录增量)
-
B 帧: “夹在上面两句中间。”(通过两头推导,几乎不占字数)
实际工程中的应用
在你刚才看的课件里提到:“非直播流,B 帧一般设置 2 帧连续”。
-
如果你设置序列为
IBBPBBP,这比IPPP模式在同等画质下,码率能降低 20% - 40% 左右。 -
这也是为什么你在 B 站看视频或者存电影时,文件里到处都是 B 帧,因为对于离线视频来说,省流量、省空间才是硬道理。
你现在明白为什么课件里说“B 帧降低码率”了吧?它就是用计算量(CPU 累)和时间(延迟高)换取了更细致的差分信息。
既然你正在研究这块,你之后在自己跑 FFmpeg 命令时,可以试着对比一下加了 -bf 2(开启两个 B 帧)和 -bf 0(关闭 B 帧)后的文件大小差异,效果会非常明显。
所以直播里b帧不是越低越好吗
没错,你一语道破了直播工程学的核心权衡。
在**直播(尤其是对延迟极度敏感的互动直播)**里,你的直觉非常精准:B帧确实是越少越好,甚至最好是 0。
为了让你理解得更透彻,我们可以把这个逻辑拆解为两个极端场景:
1. 为什么直播要“痛杀”B帧?(延迟是天敌)
正如你之前分析的那张时间线图,只要有 B 帧存在,编码器就必须“等”。
-
物理延迟: 必须等后一帧拍出来,当前的 B 帧才能编码。
-
逻辑延迟: 必须先发 P 帧,再发 B 帧。
-
后果: 在像连麦、打游戏直播、或者是电商秒杀抢购这种场景下,40ms 或 80ms 的额外延迟可能就是“生与死”的区别。所以,专业的直播推流通常会将 B 帧设为 0。
2. 那为什么 B 帧还没被“开除”?(带宽是成本)
既然 B 帧这么耽误事,为什么还没从视频界消失?因为它有一个杀手锏:省钱。
-
高画质 vs 低码率: 如果你是在做一个晚会直播或者体育比赛直播,延迟 2-3 秒其实没人在乎,但画面一定要清晰。
-
成本博弈: 如果不用 B 帧,达到同样的画质可能需要 8Mbps 的带宽;用了 B 帧,可能只需要 5Mbps。对于平台来说,这省下的 3Mbps 乘以百万观众,就是天文数字般的带宽费。
3. 直播配置的“潜规则”总结
根据你的学习进度,你可以记住这套工业界常用的选择:
| 场景 | B 帧设置 | 核心诉求 |
| 视频会议 / 云游戏 | 必须为 0 | 追求绝对的实时,延迟 > 100ms 就没法玩了。 |
| 互动直播(主播连麦) | 通常为 0 | 保证主播和观众说话能对得上,不卡顿。 |
| 普通秀场直播 / 赛事 | 0 或 1 | 在延迟和画质之间找个平衡点。 |
| 电影点播 / 短视频 | 2 或更多 | 不怕延迟(反正有预加载),只求文件越小越好。 |
💡 给你一个“高手级”的思考
你正在学习的这些知识点,实际上是在做一个三元博弈:
-
码率(文件大小/带宽成本)
-
延迟(实时性)
-
画质(清晰度)
你想降低码率(省钱)? 那就得加 B 帧,但延迟就上来了。
你想降低延迟(快)? 那就得砍掉 B 帧,但码率就上来了(为了保住画质)。
所以,你说“B 帧越低越好”是对的,但前提是你在**“追求速度”**这条赛道上。如果你哪天成了视频网站的老板,想省带宽费,你可能反而会觉得“B 帧越多越好”了。
你现在的思路已经完全进入音视频专家的逻辑了。你打算在你那个 Docker 里的 SRS 环境试着把 B 帧关掉(-bf 0)看看延迟的变化吗?
没看懂为什么b帧越多文件越小
其实道理很简单,你可以把 B 帧想象成一个**“超级省话大王”**。
为了让你秒懂,我们不用专业术语,直接用**“记账”**来打比方。
假设你要向朋友描述一个人从左边走到右边的三张照片:
1. 如果没有 B 帧(只有 I 帧和 P 帧)
-
第 1 张 (I 帧): 你必须画出整个人,背景、衣服、五官,全部画出来。(画了 100 笔)
-
第 2 张 (P 帧): 你参考第 1 张,只写:“人向右挪了 10 厘米”。(写了 10 笔)
-
第 3 张 (P 帧): 你参考第 2 张,又写:“人又向右挪了 10 厘米”。(又写了 10 笔)
-
总成本:120 笔。
2. 如果引入了 B 帧(I - B - P 模式)
-
第 1 张 (I 帧): 还是画全整个人。(100 笔)
-
第 3 张 (P 帧): 参考第 1 张,写:“人挪到了最右边 20 厘米处”。(10 笔)
-
第 2 张 (B 帧): 此时它最聪明,它看着左边的 I 帧和右边的 P 帧,直接写:“我正好就在你们两个的正中间。”
-
关键点: 因为它同时参考了“过去”和“未来”,它描述自己位置的时候,逻辑极度精简,甚至可能只需要 2 笔 就能说清楚。
-
总成本:112 笔。
为什么 B 帧能“省话”?
-
双向参考更准:
单向参考(P 帧)就像“盲人摸象”,只能猜下一步。双向参考(B 帧)就像“填空题”,已知开头和结尾,填中间那个空是非常容易且准确的,所以它记录的“差值数据”极小。
-
预测更“便宜”:
在视频编码里,描述“物体动了多少”比描述“物体长什么样”要省钱得多。B 帧因为有两个参考源,它能找到最像自己的块,剩下的微小差异(残差)就变得非常少,数据量自然暴跌。
-
数据丢了也没关系:
编码器在压缩时,会故意给 B 帧分配更少的带宽(码率)。因为它知道 B 帧不作为别人的参考,即便稍微模糊一点点,只要下一帧 P 帧或 I 帧是清晰的,人眼就会自动“脑补”过去,觉得整体画质还行。
总结
B 帧越多,视频里这种“半卖半送”的参考帧比例就越高。
虽然每帧都还是 1/25 秒,但由于 B 帧只有 I 帧体积的 5% 甚至更小,所以当你把视频里大量的 P 帧换成 B 帧时,整个文件就像挤掉了水分的海绵,体积迅速缩水。
这回能理解为什么它能让文件变小了吗?
什么带宽码率啊,为什么要把p帧换成b帧
这两个词是音视频开发的“度量衡”,理解了它们,你就能看懂为什么我们要费尽心思把 P 帧换成 B 帧了。
1. 什么是码率(Bitrate)?
码率就是:1 秒钟的视频,包含了多少数据量。
它的单位通常是 Mbps(兆位每秒)。
-
低码率: 1 秒的数据量少。文件小,网络要求低,但画质可能像打了一层马赛克。
-
高码率: 1 秒的数据量大。文件大,画质非常清晰,但如果你网速慢,看视频就会一直转圈。
2. 什么是带宽(Bandwidth)?
带宽就是:你的“网速上限”。
你可以把它想象成一根水管。
-
如果视频的码率大于你的带宽(水流比水管粗),视频就会卡顿。
-
对于直播平台老板来说,带宽就是钱。给 100 万观众看 8Mbps 的视频,和看 4Mbps 的视频,老板付给电信运营商的钱差了一倍。
3. 核心问题:为什么要把 P 帧换成 B 帧?
把 P 帧换成 B 帧,其实是在玩一个**“偷梁换柱”**的游戏,目标是:在不降低画质的前提下,强行把码率压下去。
场景 A:全是 P 帧(无 B 帧)
如果你想让观众看清楚,可能每秒需要发 10MB 的数据。
-
缺点: 码率高(10MB/s),对观众网速要求高,平台带宽费极贵。
场景 B:把部分 P 帧换成 B 帧
因为 B 帧体积超级小(只有 P 帧的几分之一),换完之后:
-
同样的一秒钟,数据量可能从 10MB 掉到了 6MB。
-
神奇之处: 观众看起来,画面清晰度几乎没变。
总结:换成 B 帧的本质逻辑
-
为了省钱: 同样的清晰度,用 B 帧能让视频文件变小。如果一个视频从 1G 变成 700MB,老板能省下 30% 的流量费。
-
为了不卡: 观众的“水管”(带宽)是有限的。如果我能用更低的码率(B 帧多一点)传出同样的画质,那些网速不太好的观众也能流畅观看,不会卡顿。
一句话总结:
把 P 帧换成 B 帧,就是为了用更少的“流量”(码率),装下同样清晰的“画面”。
你现在理解为什么在做离线视频(比如存电影、发短视频)时,大家拼了命也要多塞点 B 帧进去了吧?因为在这些场景下,省流量就是最高的优先级。
你是在为你那个直播服务器计算带宽成本吗?
为什么能把 P 帧换成 B 帧
这其实是在问:编码器凭什么觉得 B 帧能代替 P 帧?
答案很简单:因为 B 帧是 P 帧的“加强版”。它们都是为了记录“变化”,但 B 帧记录变化的方式更高级。
我们可以从以下三个层面拆解:
1. 逻辑层面:只要有“参照物”就行
视频压缩的核心逻辑是:“能不画就不画,找个参考凑合一下”。
-
P 帧说: 我参考过去(前一帧),算算我变了多少。
-
B 帧说: 我既参考过去(前一帧),又参考未来(后一帧),算算我在它们中间是什么样的。
既然 B 帧也能通过参考(Prediction)把图像拼出来,那它在逻辑上就能完全替代 P 帧。
2. 物理层面:它比 P 帧更省空间
为什么我们要费劲把 P 帧换成 B 帧?因为 B 帧更“虚”。
-
P 帧: 它是实打实的增量。比如人往右走,它要记录“人挪动了”这个完整的信息。
-
B 帧: 它是“插值”。因为它看到了开头(前一帧)和结尾(后一帧),它记录的信息更像是“补全中间的残影”。
由于 B 帧有两个参考源,它能找到的“相同部分”更多,剩下的“不同部分”(残差)就非常小。在计算机里,残差越小,占用的比特位(Bit)就越少,文件就越小。
3. 工程层面:牺牲“时间”换取“体积”
你能把 P 帧换成 B 帧,是因为你接受了延迟。
-
如果不换(全用 P 帧): 采集到第 2 帧,参考第 1 帧,啪,编码发走了。速度极快。
-
如果换成 B 帧: 采集到第 2 帧,编码器说:“别急,我得等第 3 帧(P 帧)出来,我好前后对比一下。” 于是第 2 帧被扣在了内存里。
总结一下:
你可以把 P 帧换成 B 帧,是因为你觉得**“文件小、省带宽”比“实时性”**更重要。
为什么现在的软件默认都这么干?
因为在非直播场景(比如你拍个视频发朋友圈、看 B 站),多等 100 毫秒的编码时间你根本没感觉,但如果视频体积能从 100MB 缩减到 60MB,你的流量费省了,下载速度也快了。这就是“白给”的福利,所以大家都会把 P 帧尽可能换成 B 帧。
你现在能把这个“等一帧”的延迟逻辑,和你刚才看的那些时间线图对上了吗?

这张图讲的是播放器中一个非常经典的操作:Seek(拖动进度条) 的底层逻辑,以及为什么有些视频拖动时会卡顿或者“马赛克”。
这里核心解释了 “Seek 必须找 I 帧” 的原则。
1. 核心动作:Seek 清空解码器
当你拖动进度条(比如从 10 秒拉回到 5 秒)时,播放器会执行一个动作:清空解码器状态。
-
为什么要清空? 因为之前的解码器里存的是 10 秒前后的参考信息。你突然跳到了 5 秒,之前的参考信息全没用了,必须“毁迹灭迹”重新开始。
2. 图中的尴尬情况:Seek 到了 P 帧
图中展示了一个很惨的情况:
-
目标位置: 你想看 5 秒 处的内容。
-
现实情况: 5 秒那个地方正好是一个 P 帧。
-
结果: 虽然解码器清空了,准备开始干活,但它发现 5 秒这个 P 帧是个“残废”,它必须参考前面的 I 帧才能画出来。可是此时解码器是空的!
3. 两种命运
-
蓝色线(完美错过 I 帧):
如果你非要从 5 秒这个 P 帧开始播,解码器就傻眼了。表现出来就是:画面卡住不动,或者出现一堆花花绿绿的马赛克,直到下一个 I 帧(比如图中的 10 秒处)出现,画面才会恢复正常。
-
红色线(刚好拉到 I 帧):
如果你运气好,或者播放器足够聪明(做了关键帧对齐),它会让你直接跳到最近的一个 I 帧。画面秒开,非常流畅。
4. 深度总结:为什么 5 秒的 GOP 让人痛苦?
结合你之前的图:
-
如果一个视频的 GOP 是 5 秒(即每 5 秒才有一个 I 帧)。
-
你在拖动进度条时,播放器为了保证画面不花,往往会强制帮你跳转到最近的那个 I 帧。
-
这就会导致:你明明想看 7 秒,它非把你弹回 5 秒;或者你想看 9 秒,它把你弹回 5 秒。这种**“拖不动”或者“乱跳”**的感觉,就是因为 I 帧太稀疏了。
💡 总结一下
这张图是在告诉你:I 帧不仅是直播的“开门砖”,也是播放器进度条的“锚点”。 GOP 设置得短(比如 1-2 秒),不仅直播秒开快,用户拖动进度条时的精准度和流畅度也会高很多。
你现在明白为什么有些劣质网页播放器,进度条一拽就卡死,或者画面要闪好几秒了吧?那就是 GOP 太长,且播放器没处理好“非关键帧 Seek”的问题。

这张图带你进入了视频编码的最后一步,也是最数学化的一步:熵编码(Entropy Coding)与 Z 字形扫描(Zig-Zag Scan)。
如果你把之前的 YUV、帧间预测比作“脱水”,那这一步就是“真空包装”。
1. 扫描像素值的目的:为了编码
图中左侧那个 $4 \times 4$ 的矩阵代表的是图像经过变换(如 DCT 变换)和量化后的系数。
-
为什么要有那个箭头的路径(Z 字形扫描)?
-
在图像处理中,能量通常集中在左上角(低频部分,代表图像的大致轮廓)。
-
越往右下角,数值通常越小,甚至会出现大量的连续 0(高频部分,代表细节)。
-
Z 字形扫描能把二维矩阵变成一维序列,并且让大数字排在前面,0 排在后面。这样在存储时,就可以用极短的代码表示“后面全是 0”,从而大幅节省空间。
-
2. 核心逻辑:出现概率越大,用越少的 bit 表示
图中红字写着:“出现概率越大的,使用更少的 bit 表示”。
这是信息论里的 哈夫曼编码(Huffman Coding) 或 算术编码(Arithmetic Coding) 的核心思想:
-
举个例子: 如果视频里“0”出现的频率是 90%,我们就给“0”分配一个超级短的代号(比如
1);如果“212”这种大数字很少出现,我们就给它分配一个长代号(比如1101010)。 -
结果: 整体算下来,总的比特数(bit)就会变得非常少。
3. 编码压缩:数值越小,字节越少
-
结合你之前看的 P 帧 和 B 帧:
-
因为 P/B 帧只记录“残差”(差值),这些差值通常都很小(接近 0)。
-
数值越小,经过这种“概率预测”编码后的字节数就越少。
-
-
这就是为什么 B 帧文件小的终极原因: 它的残差值经过这一步处理后,几乎被压缩到了极致。
总结:视频压缩的全过程
看到这张图,你其实已经把视频编码的完整链路串起来了:
-
色彩空间转换: RGB 转 YUV,把颜色信息抽稀(图 1)。
-
空间冗余: 找一张图里的重复部分(图 2)。
-
时间冗余: 找前后帧的重复部分,生成 I、P、B 帧(图 3、4、5)。
-
变换量化: 把图像变成图中这种数字矩阵。
-
熵编码: 按照图中这种 Zig-Zag 路径 扫描,用“短代号”代替“高频数”,完成最后的压缩(图 8)。
💡 老师想表达的意思:
他在讲 “变长编码”。视频不是像存文本文件那样一个字符占 8 位,而是聪明的编码器会根据数字出现的频率动态分配长度。**“省掉废话”**就是视频压缩的最后一道工序。
你这套课件含金量很高啊,从物理采样一直讲到了信息论底层。这部分关于“扫描路径”和“概率编码”的内容,你在写代码(比如用 FFmpeg 配置 entropy 编码器)时会遇到相关的参数选择(如 CABAC 或 CAVLC)。
现在你对整个视频从摄像头拍到、到压成 MP4 发出去的流程,是不是感觉已经通关了?

我让你分析这个照片里的内容,什么垂直预测
这张图展示的是 H.264 编码中非常核心的“帧内预测 (Intra Prediction)” 技术。
简单来说,它的目的就是:消灭一张图片内部的重复信息(空间冗余)。
以下是详细拆解:
1. 核心原理:相邻像素的相关性
-
现象:在同一张画面里,相邻的像素通常非常接近(比如蓝天的一片区域,像素值几乎一样)。
-
策略:既然相邻像素差不多,我们就不记录每个像素的具体数值,而是用“邻居”的值来预测当前块的值,最后只记录两者的差值。
2. 什么是“垂直预测”和“水平预测”?
图中展示了两种具体的预测模式(以 $4 \times 4$ 的像素小块为例):
-
垂直预测 (Vertical Prediction):
-
操作:把上一行像素的值直接“复制”下来,作为下面每一行像素的预测值。
-
适用场景:画面呈现上下纹理一致时。
-
-
水平预测 (Horizontal Prediction):
-
操作:把左侧一列像素的值水平地“推”过去,作为右侧每一列像素的预测值。
-
图中演示:你看右侧那个标注“这个小块是预测”的图,它就是把最左边的数值(212, 170, 128, 96)直接横向填充到了整行。
-
3. 为什么要算“差值 (Residual)”?
这是压缩最精妙的地方。图中给出了一个公式:
$$\text{原始值 } X - \text{预测值 } X_p = \text{差值 } d$$
-
原始块:里面的数值很大(比如 212, 189 等),直接存储很占空间。
-
预测块:利用左侧块预测出来的“假想图”。
-
残差块 (黄框部分):这是最终要存储的数据。你会发现里面的数值变得非常小(比如 0, 2, 6 等)。
4. 结论:为什么这样能压缩?
在计算机里,存一个大数字(比如 212)需要的比特位很多,而存一个小数字(比如 0 或 2)需要的比特位非常少。
-
H.264 就是通过这种方式,把原本饱满的图像数据变成了大量接近 0 的微小差值。 * 再结合你之前看的那张 Zig-Zag 扫描图,这些小数字和大量的 0 会被极度压缩,从而实现视频体积的暴减。
一句话总结:
垂直/水平预测就是利用已知的像素去“猜”未知的像素。猜得越准,剩下的差值就越小,视频文件也就越小。
你现在能理解为什么这个步骤叫“帧内”预测了吗?因为它只在这一张画里找规律,还没涉及到前后的运动。
原始值是本来的图,预测值是上一张图的值
不完全是,这是一个非常容易混淆的点。
在 H.264 的“帧内预测”(也就是你这张图 1000109408.jpg 讨论的场景)中,预测值并不是来自“上一张图”(上一帧),而是来自**“当前这张图”里已经编码过的邻居像素**。
我们来精准拆解一下:
1. 预测值从哪来?(当前帧的邻居)
-
帧内预测 (Intra Prediction):预测值来自当前画面中,该块左边或者上面的像素。
-
垂直预测:把“头顶上”那行像素向下复制。
-
水平预测:把“左手边”那列像素向右复制。
-
-
目的:利用一张图内部的空间相关性来省空间。
2. 你说的“上一张图”叫什么?(帧间预测)
如果你用“上一张图”的值来预测当前图,那叫 帧间预测 (Inter Prediction)。
-
这对应的是你之前看的 P 帧和 B 帧。
-
它利用的是时间上的重复性(比如背景没动,就直接用上一帧的像素)。
3. 为什么一定要用“邻居”而不用“上一张”?
在编码 I 帧(关键帧) 时,解码器手里还没有任何“上一张图”的数据。
-
为了让 I 帧能独立打开(秒开),它只能“自力更生”,在自己的画面里找规律。
-
所以,你图里的原始值是你想编码的那个 $4 \times 4$ 小块,预测值是它紧挨着的左侧或上方像素的“克隆体”。
总结
-
帧内预测(这张图的内容):预测值 = 同图片的左边/上面像素。
-
帧间预测(P/B 帧的内容):预测值 = 前一张/后一张图片的像素。
这就是为什么图中强调的是“相邻像素的相关性”,而不是“相邻帧的相关性”。这种“空间上的修补”让即便是一个独立的 I 帧,也能被压得很小。
左侧或上方像素的“克隆体”,左侧和上方像素哪来的
这个问题问到了点子上!这涉及到一个非常关键的概念:编码顺序。
你可以把编码一张图片想象成**“粉刷匠刷墙”,它是按照从左到右、从上到下**的顺序进行的。
1. 邻居像素是怎么“无中生有”的?
当你准备编码图中那个黄色的 $4 \times 4$ 小块(当前块)时,它的左侧和上方其实已经被编码完了。
-
上方的像素: 是在处理“上一行”宏块时存下来的。
-
左侧的像素: 是在处理“当前行”的前一个宏块时存下来的。
2. 它们为什么能被当成参考?
因为解码端(播放器)也会按照完全一样的顺序来解码。
-
播放器先解出最左上角的像素。
-
到了你要看的小块时,播放器手里已经拿到了左边和上面的真实像素值。
-
编码器只需要告诉播放器:“喂,用你左边那排像素往右填充,然后再加减我给你的这几个差值。”
-
播放器照做,画面就还原出来了。
3. 一个极端的逻辑挑战:最左上角的像素参考谁?
如果你是这张图的第一个像素(坐标 0,0),左边没邻居,上面也没邻居,怎么办?
-
这时候就不能用“水平”或“垂直”预测了。
-
H.264 有一种模式叫 DC 预测:如果不靠邻居,就取一个默认的平均值(比如 128),或者干脆直接记录原值。
总结
左侧和上方的像素,其实是**“前辈”。 在处理当前这一块的时候,编码器会把紧邻的“前辈”边缘像素暂存在内存里**,专门等着给当前块当“模板”用。
所以,这套逻辑成立的前提是:所有块必须按顺序排队。
这个“粉刷匠顺序”的逻辑,能解释你对“邻居像素来源”的疑问了吗?这也正是为什么 H.264 叫“行扫描”编码的原因。






![[ 网络通信基础 ]——网络的传输介质(双绞线,光纤,标准,线序)](../download/20260617/2aed2e32838d4defaf3d0595004d364c.png)