4. RTP 时间戳机制:音画同步的基石
时间戳,说白了就是 RTP 包的「时间身份证」。没有它,接收端根本不知道这包数据该什么时候播放。我刚开始接触 RTP 时,觉得时间戳不就是个序号嘛,后来踩了坑才明白——它比序号复杂得多,也重要得多。
4.1 时间戳的核心作用
RTP 时间戳主要干三件事:
- 标记采样时刻:告诉接收端,这包数据是在哪个时间点采集的
- 控制播放节奏:接收端根据时间戳差值,决定两包数据之间的播放间隔
- 实现音画同步:音频流和视频流各自维护时间戳,接收端通过它们对齐播放
关键认知:时间戳不是序号,它反映的是采样时间,而不是包的到达顺序或发送顺序。乱序到达的包,时间戳可能比先到的包还小——这在视频传输中很常见。
我记得有一次排查一个视频花屏问题,发现接收端按到达顺序播放,结果画面一顿一顿的。查了半天,原来是发送端网络抖动导致包乱序,但时间戳本身是对的。接收端没按时间戳排序,直接按到达顺序丢给解码器——嗯,这就是典型的时间戳使用错误。
4.2 时间戳频率与采样率的关系
这里有个容易混淆的概念:时间戳的单位不是毫秒,而是「时钟滴答」。每个 RTP 负载类型(payload type)都有自己的默认时钟频率。
| 媒体类型 | 典型采样率 | RTP 时钟频率 | 说明 |
|---|---|---|---|
| PCMU / PCMA 音频 | 8 kHz | 8,000 Hz | 每个采样对应一个时间戳增量 |
| G.722 音频 | 16 kHz | 8,000 Hz | 注意:时钟频率不等于采样率 |
| H.264 视频 | N/A | 90,000 Hz | 视频固定使用 90 kHz |
| MPEG-4 视频 | N/A | 90,000 Hz | 同样固定 90 kHz |
为什么视频要用 90 kHz?我个人的理解是:90 kHz 能被常见的视频帧率(24、25、30、50、60)整除,能精确表示每个帧的时间位置。你想想看,如果用 1,000 Hz(1ms 精度),30 fps 的帧间隔是 33.333...ms,时间戳增量算出来是 33,333.333...,取整就会引入误差。90 kHz 下,30 fps 的增量正好是 3,000,完美。
实用技巧:计算实际时间时,用 时间戳差值 / 时钟频率 就能得到秒数。比如视频时间戳从 0 跳到 90,000,那就是过了 1 秒。
4.3 时间戳增量计算
增量怎么算?公式很简单:
时间戳增量 = 每帧采样数 × (RTP时钟频率 / 采样率)
我直接给你几个实际例子:
音频示例:PCMU,20ms 一包
- 采样率:8,000 Hz
- 每包时长:20 ms = 0.02 秒
- 每包采样数:8,000 × 0.02 = 160 个采样
- 时钟频率:8,000 Hz(与采样率相同)
- 增量 = 160 × (8,000 / 8,000) = 160
视频示例:H.264,30 fps
- 帧间隔:1/30 ≈ 0.03333 秒
- 时钟频率:90,000 Hz
- 增量 = 90,000 × (1/30) = 3,000
我曾经踩过的坑:音频的时钟频率不一定等于采样率。比如 G.722,采样率是 16 kHz,但 RTP 时钟频率固定为 8,000 Hz。如果你直接用采样率算增量,时间戳会跑得比实际快一倍,接收端播放就会加速。我当时排查了一个「说话像快进」的 bug,最后发现是时钟频率用错了。
4.4 音视频时间戳同步基础
音画同步,核心就是让音频和视频的时间戳在同一个时间轴上对齐。RTP 本身不提供全局时钟,它依赖 RTCP 的 SR(Sender Report)报文来建立时间戳与 NTP 时间的映射关系。
基本思路是这样的:
- 发送端定期发送 RTCP SR,里面包含:
- NTP 时间戳(绝对时间,单位秒)
- RTP 时间戳(对应同一时刻的媒体时间戳)
- 接收端收到 SR 后,建立一条「RTP 时间戳 ↔ NTP 时间」的换算关系
- 音频流和视频流各自换算到 NTP 时间,然后对齐播放
举个例子:
- 音频 RTP 时间戳 160,000 对应 NTP 时间 10:00:00.000
- 视频 RTP 时间戳 270,000 对应 NTP 时间 10:00:00.000
- 那么这两个包就应该同时播放
如果视频的 RTP 时间戳 273,000 对应 NTP 时间 10:00:00.033,那它就应该比上面的音频包晚 33ms 播放。
核心原则:音频和视频的 RTP 时间戳各自独立增长,不能直接比较。必须通过 RTCP SR 映射到同一个 NTP 时间轴后,才能判断谁先谁后。
下面这张图展示了整个时间戳同步的流程:
实战建议:在接收端维护一个音视频同步缓冲区,不要收到一包就立刻播放。等缓冲区里同时有音频和视频数据后,根据 NTP 时间戳决定播放顺序。缓冲区大小一般设为 100-300ms,既能抗抖动,又不会引入明显延迟。
嗯,时间戳这块内容比较多,但核心就三点:时钟频率决定增量精度,RTCP SR 提供映射桥梁,接收端负责对齐播放。搞懂这些,音画同步的基本功就算打牢了。