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甚至更小
我的经验: 在RTSP推流中,我建议把GOP(Group of Pictures,两个I帧之间的间隔)设置在2-4秒。太长了,拉流时首屏延迟会很大;太短了,码率控制不住。我曾经在一个监控项目中,把GOP设成了10秒,结果客户端拉流等了快5秒才出画面,被客户骂惨了。

还有一个概念你必须要懂: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-HEv2,码率压到24kbps。结果在客户的大屏电视上播放,声音像从罐头里发出来的,高频全没了。后来我改成AAC-LC 64kbps,问题解决。记住:不要为了省带宽牺牲听感,尤其是在大屏场景。

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。如果你非要用,需要自己写一个解复用器。
一句话总结: 做RTSP直播,首选TS;做点播,首选MP4(记得把moov box前置);做RTMP直播,只能用FLV。

下面这张图,展示了H.264视频和AAC音频是如何被封装进TS流的:

H.264与AAC封装进TS流示意图 H.264 + AAC → TS 封装流程 H.264 视频流 AAC 音频流 视频PES (添加PTS/DTS) 音频PES (添加PTS) TS复用器 切包(188字节) 添加PAT/PMT TS 输出流 关键点: 1. H.264的NAL单元和AAC的ADTS帧,先被打包成PES包,并带上PTS/DTS时间戳。 2. TS复用器将PES包切分成188字节的小包,并插入PAT(节目关联表)和PMT(节目映射表)。

你看,H.264和AAC各自独立编码,然后在PES层被加上时间戳,最后在TS层被复用成一个个188字节的小包。每个TS包都包含一个同步字节(0x47),解码器只要找到这个字节,就能开始解析。

好了,这一章的内容就这些。H.264的帧类型、AAC的规格、三种封装格式的对比,都是你后面做RTSP音画同步时绕不开的基础。把这些搞明白,后面遇到问题你才能快速定位。