1. 音画同步基础:理解PTS/DTS时间戳、RTP时间戳机制、音视频时钟模型
做RTSP推流的人,十有八九都被音画不同步折磨过。我当年第一次做直播项目,画面和声音差了快两秒,用户直接开骂。后来才发现,根子就在时间戳上。
说白了,音画同步就是让音频和视频在播放时保持时间上的对齐。听起来简单,但实际落地时,你得搞明白三个核心概念:PTS/DTS时间戳、RTP时间戳机制、音视频时钟模型。今天咱们一个一个拆开讲。
1.1 PTS与DTS:解码和显示的时间差
先问个问题:为什么视频帧需要两个时间戳?
因为视频编码里有三种帧类型——I帧、P帧、B帧。I帧是完整图像,P帧依赖前面的帧,B帧依赖前后帧。解码器拿到B帧时,必须先解码它依赖的前后帧,但显示时B帧又得插在中间。这就导致了解码顺序和显示顺序不一致。
- DTS(Decoding Time Stamp):告诉解码器什么时候开始解码这一帧。
- PTS(Presentation Time Stamp):告诉播放器什么时候显示这一帧。
举个例子,一个典型的GOP(图像组)顺序可能是这样:
编码顺序(DTS顺序): I1 P4 B2 B3 P7 B5 B6
显示顺序(PTS顺序): I1 B2 B3 P4 B5 B6 P7
你看,B2和B3在编码时排在P4后面,但显示时却要插在I1和P4之间。如果没有PTS,播放器按DTS顺序直接丢画面,那B帧就全乱套了。
关键点:音频没有B帧的概念,所以音频的PTS和DTS永远相等。只有视频才需要区分这两个时间戳。
我在项目中遇到过一个问题:某个编码器输出的B帧PTS比DTS还小,播放器直接崩溃。后来查手册才发现,那个编码器把PTS和DTS搞反了。嗯,这种坑踩一次就够了。
1.2 RTP时间戳机制:网络传输中的时间载体
RTSP推流时,音视频数据是打包成RTP包发送的。每个RTP包头里都有一个32位的时间戳字段,但它和PTS/DTS不是一回事。
RTP时间戳的作用是:告诉接收端两个RTP包之间的时间间隔。它不直接表示绝对时间,而是用采样率来换算。
| 媒体类型 | 典型采样率 | 时间戳增量含义 |
|---|---|---|
| 音频(PCM) | 8000 Hz / 44100 Hz / 48000 Hz | 每个采样点对应一个时间戳单位 |
| 视频(H.264) | 90000 Hz(固定) | 每帧对应的时间戳增量 = 帧间隔 × 90000 |
为什么视频要用90000 Hz?这是历史原因——MPEG标准定的,90000能被常见的帧率(24、25、30、50、60)整除,算起来方便。
举个例子,25fps的视频,每帧间隔是40ms。RTP时间戳增量就是:
0.04秒 × 90000 Hz = 3600
所以第一帧时间戳是0,第二帧就是3600,第三帧7200,以此类推。
个人习惯:我写推流代码时,会单独维护一个RTP时间戳计数器,而不是直接从PTS转换。因为PTS的单位可能是微秒或纳秒,直接转90000容易丢精度。自己算增量,稳得多。
1.3 音视频时钟模型:谁才是时间的老大?
音画同步的核心,其实是时钟同步。推流端和拉流端各自有本地时钟,如果两个时钟跑得不一样快,时间戳再准也没用。
常见的时钟模型有三种:
- 单一时钟模型:音频和视频共用同一个时钟源。最简单,但一旦时钟漂移,音视频一起偏。
- 独立时钟模型:音频和视频各自用自己的时钟。灵活性高,但需要定期同步,否则会慢慢错开。
- 主从时钟模型:选一个作为主时钟(通常是音频),视频跟着音频走。这是实际项目中最常用的方案。
为什么音频适合做主时钟?因为人耳对声音的抖动比眼睛对画面的抖动敏感得多。音频卡顿一下,用户立刻能察觉;视频稍微跳一帧,反而没那么明显。
避坑指南:我曾经在一个项目中用了视频做主时钟,结果音频播放器为了追视频的节奏,频繁变速,声音变得像机器人。后来改成音频做主时钟,问题立刻解决。记住:音频优先,视频跟随。
下面这张图展示了RTSP推流中音画同步的整体流程:
1.4 三个概念的关系:别搞混了
很多人刚接触时,容易把PTS和RTP时间戳当成一回事。其实它们分工明确:
- PTS/DTS:属于编码层,描述帧的解码和显示时序。
- RTP时间戳:属于传输层,描述RTP包之间的时间间隔。
- 时钟模型:属于系统层,保证推流端和拉流端的时钟基准一致。
打个比方:PTS是电影的剧本,告诉你每个镜头什么时候出现;RTP时间戳是快递单号,告诉你包裹之间的发货间隔;时钟模型是手表,保证导演和观众看的是同一个时间。
核心原则:推流端必须保证RTP时间戳与PTS的映射关系正确,拉流端才能根据RTP时间戳还原出正确的播放时序。任何一端的时钟漂移,都会导致音画不同步。
好了,这一章的内容就到这里。理解PTS/DTS、RTP时间戳和时钟模型,是解决音画同步问题的第一步。后面我们会一步步深入,把这些知识用到实际推流场景中。