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 音视频时钟模型:谁才是时间的老大?

音画同步的核心,其实是时钟同步。推流端和拉流端各自有本地时钟,如果两个时钟跑得不一样快,时间戳再准也没用。

常见的时钟模型有三种:

  1. 单一时钟模型:音频和视频共用同一个时钟源。最简单,但一旦时钟漂移,音视频一起偏。
  2. 独立时钟模型:音频和视频各自用自己的时钟。灵活性高,但需要定期同步,否则会慢慢错开。
  3. 主从时钟模型:选一个作为主时钟(通常是音频),视频跟着音频走。这是实际项目中最常用的方案。

为什么音频适合做主时钟?因为人耳对声音的抖动比眼睛对画面的抖动敏感得多。音频卡顿一下,用户立刻能察觉;视频稍微跳一帧,反而没那么明显。

避坑指南:我曾经在一个项目中用了视频做主时钟,结果音频播放器为了追视频的节奏,频繁变速,声音变得像机器人。后来改成音频做主时钟,问题立刻解决。记住:音频优先,视频跟随。

下面这张图展示了RTSP推流中音画同步的整体流程:

RTSP推流音画同步流程 视频编码器 生成PTS/DTS 音频编码器 生成PTS(=DTS) RTP打包 生成RTP时间戳 RTP打包 生成RTP时间戳 RTSP推流 发送RTP包 RTSP推流 发送RTP包 时钟模型(音频主时钟) 音频时钟驱动,视频时钟跟随对齐 说明: PTS/DTS由编码器生成,RTP时间戳在打包时计算,时钟模型决定音视频的同步基准。

1.4 三个概念的关系:别搞混了

很多人刚接触时,容易把PTS和RTP时间戳当成一回事。其实它们分工明确:

  • PTS/DTS:属于编码层,描述帧的解码和显示时序。
  • RTP时间戳:属于传输层,描述RTP包之间的时间间隔。
  • 时钟模型:属于系统层,保证推流端和拉流端的时钟基准一致。

打个比方:PTS是电影的剧本,告诉你每个镜头什么时候出现;RTP时间戳是快递单号,告诉你包裹之间的发货间隔;时钟模型是手表,保证导演和观众看的是同一个时间。

核心原则:推流端必须保证RTP时间戳与PTS的映射关系正确,拉流端才能根据RTP时间戳还原出正确的播放时序。任何一端的时钟漂移,都会导致音画不同步。

好了,这一章的内容就到这里。理解PTS/DTS、RTP时间戳和时钟模型,是解决音画同步问题的第一步。后面我们会一步步深入,把这些知识用到实际推流场景中。