1. RTP时间戳基础:协议、作用与时钟频率

各位同学好,我是老周。做流媒体这行十几年了,今天咱们聊聊RTP时间戳。说实话,音画同步这个坑,我踩过不少。很多新手上来就写代码,结果画面和声音对不上,急得直挠头。其实问题的根子,往往就在时间戳上。

这一章,我们先打地基。把RTP协议、时间戳的作用、时钟频率这几个概念彻底搞明白。后面再讲实战,你才不会慌。

1.1 RTP协议到底是什么?

RTP,全称Real-time Transport Protocol,实时传输协议。它跑在UDP上面,专门用来传音视频数据。你想想看,直播、视频通话、IP电话,底层基本都是它。

RTP本身不保证传输质量,它只负责把数据包从A点送到B点,并且带上时间信息。至于丢包了怎么办、乱序了怎么排,那是RTCP和上层应用的事。

我刚开始做流媒体时,总觉得RTP和RTCP是一回事。后来被坑过一次——只发了RTP没配RTCP,结果接收端根本不知道网络状况,画面卡成幻灯片。嗯,这里要注意:RTP是数据通道,RTCP是控制通道,两者配合才能干活。

一个标准的RTP包长这样:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X|  CC   |M|     PT      |       sequence number         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           timestamp                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           synchronization source (SSRC) identifier            |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|            contributing source (CSRC) identifiers             |
|                             ....                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

这里面,timestamp字段就是我们的主角。它占32位,单位不是秒,而是采样时钟的tick数。这个后面会细讲。

1.2 时间戳在RTP中的作用

时间戳是RTP的灵魂。没有它,接收端根本不知道什么时候该播放这个包。

具体来说,时间戳干三件事:

  • 播放时序控制:告诉接收端,这个包应该在哪个时间点被播放出来。
  • 音画同步:音频和视频各自有自己的时间戳,接收端通过比对它们,让声音和画面对齐。
  • 抖动消除:网络有延迟抖动,接收端靠时间戳把乱序的包重新排好,再平滑播放。

我记得有一次做视频会议项目,音频和视频总是差个几百毫秒。查了两天,发现是音频时间戳的时钟频率配错了。音频用8kHz采样,时间戳增量算出来是160,结果代码里写成了320。画面和声音直接错位,像看译制片。从那以后,我对时间戳的计算就格外小心。

核心要点:RTP时间戳不是绝对时间,而是相对时间。它表示的是采样时刻的序号,不是墙上时钟的秒数。

1.3 时钟频率的概念

时钟频率,说白了就是时间戳的“刻度”有多细。单位是Hz,表示每秒有多少个tick。

举个例子:

  • 音频用8kHz采样率,时钟频率就是8000 Hz。每秒钟时间戳增加8000。
  • 视频用90kHz时钟频率,每秒钟时间戳增加90000。

为什么视频要用90kHz?这是历史原因。早期的MPEG标准定了这个值,后来大家就都跟着用了。我个人习惯,视频一律用90kHz,音频根据采样率来定。

时钟频率和时间戳的关系,可以用一个公式表示:

时间戳增量 = 时钟频率 × 帧间隔(秒)

举例:
音频:48kHz采样率,每帧20ms
时间戳增量 = 48000 × 0.02 = 960

视频:90kHz时钟频率,每帧33.33ms(30fps)
时间戳增量 = 90000 × 0.03333 ≈ 3000

你想想看,如果时钟频率设错了,时间戳增量就会算错。接收端拿到错误的时间戳,播放节奏全乱套。我曾经见过一个项目,视频时间戳增量算出来是3003,结果代码里写成了3000。30fps的视频,每帧差3个tick,一分钟下来就差了5400个tick,相当于60ms的偏移。肉眼看不出来,但音频对不上,用户直接投诉。

避坑指南:时钟频率一旦确定,整个会话期间不能改变。如果中途改了,接收端的时间戳计算会全部乱掉。我曾经在切换码率时忘了保持时钟频率一致,结果画面直接卡死。从那以后,我都在SDP里明确声明时钟频率,并在代码里做校验。

1.4 常见媒体类型的时钟频率

不同媒体类型,时钟频率不一样。下面这个表是我平时查得最多的:

媒体类型 常见时钟频率 说明
PCM音频 8000、16000、32000、48000 等于采样率
AAC音频 48000、44100、32000 等于采样率
G.711音频 8000 固定值
H.264视频 90000 标准规定
H.265视频 90000 同H.264
MPEG-4视频 90000 标准规定

音频的时钟频率一般就等于采样率。视频则统一用90kHz。为什么视频不直接用帧率?因为帧率不固定。30fps、60fps、可变帧率,如果用帧率做时钟频率,时间戳计算会非常麻烦。90kHz是30fps的3000倍,精度足够高,能支持到小数点后好几位。

小技巧:如果你不确定视频的时钟频率,直接用90000准没错。这是行业惯例,几乎所有解码器都认。

1.5 知识体系总览

下面这张图,把这一章的核心逻辑串起来了。你看一遍,心里就有谱了。

RTP时间戳基础:知识体系 RTP时间戳 RTP协议 时间戳作用 时钟频率 UDP承载,实时传输 32位timestamp字段 与RTCP配合使用 播放时序控制 音画同步 抖动消除 音频=采样率 视频=90000Hz 增量 = 频率 × 帧间隔 时间戳是相对值,不是绝对时间。时钟频率决定刻度精度。

这张图把RTP时间戳拆成了三块:协议基础、作用、时钟频率。你顺着箭头看,就能理解它们之间的关系。RTP协议提供了传输载体,时间戳在里面扮演调度角色,而时钟频率决定了时间戳的精度。三者缺一不可。