2. 音视频编码基础:H.264、AAC与封装格式
做流媒体的人,如果不懂编码原理,就像开车不懂发动机。你可能能把车开走,但出了问题就抓瞎了。这一章,我带你把这部分基础打扎实。
咱们直接切入正题。RTSP流媒体里,最常用的视频编码是H.264,音频编码是AAC。封装格式嘛,MP4、TS、FLV各有各的脾气。下面我一个一个说。
2.1 H.264编码原理:别被“复杂”吓住
H.264,也叫AVC。说实话,它的编码标准文档有上千页。但咱们做运维和集成,不需要背那些公式。你只需要理解它的核心思路:用空间换时间,用计算换带宽。
H.264的核心思想是“预测+残差”。什么意思呢?
- 帧内预测:同一帧画面里,相邻像素块的颜色和纹理往往相似。编码器只记录“预测值和实际值的差异”,而不是记录每个像素的原始值。这能省下大量空间。
- 帧间预测:视频是连续的,相邻帧之间变化很小。编码器只记录“当前帧和参考帧的差异”,也就是运动矢量和残差。我见过不少新手,以为每一帧都是独立压缩的,其实不是。
H.264定义了三种主要的帧类型:
| 帧类型 | 全称 | 特点 | 我在项目中看到的典型大小 |
|---|---|---|---|
| I帧 | 关键帧 | 完整编码,不依赖其他帧。解码的入口点。 | 最大,通常几十KB到几百KB |
| P帧 | 前向预测帧 | 参考前面的I帧或P帧,只记录差异。 | 中等,I帧的1/3到1/5 |
| B帧 | 双向预测帧 | 参考前后帧,压缩率最高,但解码复杂。 | 最小,I帧的1/10甚至更小 |
还有一个概念你必须要懂:NAL单元。H.264码流是由一个个NAL单元组成的。每个NAL单元都有一个头,标识它是什么类型。常见的类型有:
- SPS(序列参数集):包含分辨率、帧率、编码档次等全局信息。
- PPS(图像参数集):包含熵编码模式、分片组等图像级参数。
- IDR(即时解码刷新):一种特殊的I帧,告诉解码器“前面的帧可以扔了,从这里开始重新解码”。
嗯,这里要注意:SPS和PPS必须完整、正确地传给解码器。否则,画面就是花的。我在排查一个花屏问题时,发现是推流端在SPS里写错了分辨率,解码器按错误尺寸去解析,画面全乱了。
2.2 AAC编码原理:比MP3聪明在哪?
AAC,高级音频编码。它比MP3晚出生,但技术更先进。说白了,MP3是90年代的技术,AAC是2000年后的技术。在同等码率下,AAC的音质明显好于MP3。
AAC的核心原理是心理声学模型。人耳对不同频率的声音敏感度不同。AAC会分析音频信号,把那些“人耳听不到或不易察觉”的频率成分直接扔掉,或者用更少的比特去编码。这样,就能在保证主观听感的前提下,大幅降低码率。
常见的AAC规格有几种:
| 规格 | 适用场景 | 特点 |
|---|---|---|
| AAC-LC | 通用场景,大部分流媒体 | 低复杂度,兼容性最好。我90%的项目都用它。 |
| AAC-HE | 低码率场景(<64kbps) | 在LC基础上加了SBR(频带复制),用低频信息去“猜”高频。 |
| AAC-HEv2 | 极低码率场景(<32kbps) | 在HE基础上加了PS(参数立体声),把立体声信息压缩成单声道+参数。 |
AAC的采样率通常用44100Hz或48000Hz。声道数嘛,大部分场景用双声道(立体声)就够了。如果你做的是对讲系统,单声道反而更省带宽。
2.3 封装格式对比:MP4、TS、FLV
编码后的视频和音频,不能直接扔到网络上。需要把它们“打包”成一个容器,也就是封装格式。不同的封装格式,有不同的特性。
我直接给你一张对比表,一目了然:
| 特性 | MP4 | TS | FLV |
|---|---|---|---|
| 起源 | MPEG-4 Part 14 | MPEG-2 Transport Stream | Adobe Flash Video |
| 核心特点 | 文件存储,非流式友好 | 流式传输,抗丢包 | 流式传输,轻量级 |
| 是否支持RTSP | 支持(但需要特殊处理) | 原生支持 | 不支持(RTMP用) |
| 是否支持HLS | 不支持 | 原生支持 | 不支持 |
| 元数据位置 | 文件头(moov box) | 分布在每个包中 | 文件头(onMetaData) |
| 典型应用 | 点播、下载 | 直播、数字电视 | 直播、早期网页播放 |
我来解释一下为什么会有这些差异:
- MP4:它的元数据(moov box)默认放在文件末尾。这意味着,如果你不把moov box移到文件头,播放器必须下载完整个文件才能开始播放。这在点播场景没问题,但在直播场景就是灾难。所以,RTSP推流时,如果要用MP4,必须用“fragmented MP4”或者把moov box前置。
- TS:它的设计初衷就是用于传输。每个TS包(188字节)都包含自己的时间戳和同步信息。即使网络丢包,解码器也能从下一个包开始恢复。这就是为什么数字电视和HLS都用TS。我个人习惯,做RTSP直播时,如果对延迟要求不高但要求稳定,我会选TS。
- FLV:它是Adobe的私有格式,但已经公开了。FLV非常轻量,头部只有几十个字节。它通过“Tag”来组织数据,每个Tag包含一个音频包或视频包。FLV在RTMP协议中广泛使用,但RTSP原生不支持FLV。如果你非要用,需要自己写一个解复用器。
下面这张图,展示了H.264视频和AAC音频是如何被封装进TS流的:
你看,H.264和AAC各自独立编码,然后在PES层被加上时间戳,最后在TS层被复用成一个个188字节的小包。每个TS包都包含一个同步字节(0x47),解码器只要找到这个字节,就能开始解析。
好了,这一章的内容就这些。H.264的帧类型、AAC的规格、三种封装格式的对比,都是你后面做RTSP音画同步时绕不开的基础。把这些搞明白,后面遇到问题你才能快速定位。