1. 音视频同步基础:时间戳概念、PTS/DTS详解、音视频不同步的典型现象

做流媒体的人,早晚都会遇到音画不同步的问题。我记得刚入行那会儿,调试一个直播流,画面里的人嘴在动,声音却慢了半秒,用户投诉电话直接打到了CTO那里。从那以后,我就把时间戳这件事刻在了骨子里。

说白了,音视频同步的核心就一句话:让音频和视频按照它们被采集时的真实时间关系,在播放端还原出来。听起来简单,但实际落地时坑特别多。这一章我们先打好基础,把时间戳、PTS、DTS这些概念彻底讲透。

1.1 为什么需要时间戳?

你想想看,视频是一帧一帧的图像,音频是一段一段的采样。它们各自独立编码、独立传输,到了播放端如果不靠时间戳对齐,那画面和声音就是各跑各的。

举个简单的例子:一个视频文件里,第10秒的画面和第10秒的声音,必须有一个共同的「时钟」来标记它们。这个时钟就是时间戳。

核心原则:时间戳是音视频同步的唯一锚点。没有时间戳,就没有同步可言。

我在项目中遇到过一种情况:有人觉得既然音频和视频是交替打包的,那按顺序播放不就行了?嗯,这种想法在本地文件播放时勉强能跑,但一旦涉及网络传输、丢包重传、变速播放,立刻就会乱套。所以,时间戳不是可选项,是必选项。

1.2 PTS 和 DTS:两个容易搞混的概念

很多初学者会把 PTS 和 DTS 当成一回事。其实它们分工完全不同。

概念 全称 含义 用途
PTS Presentation Time Stamp 显示时间戳 告诉播放器「这一帧/这一段应该在什么时间显示」
DTS Decoding Time Stamp 解码时间戳 告诉解码器「这一帧应该在什么时间解码」

为什么需要两个时间戳?因为视频编码里有三种帧类型:I帧、P帧、B帧。

  • I帧(关键帧):完整图像,可以独立解码。
  • P帧(前向预测帧):依赖前面的I帧或P帧。
  • B帧(双向预测帧):依赖前面和后面的帧。

B帧的存在,导致了解码顺序和显示顺序不一致。举个例子:一个视频序列的显示顺序是 I1 - B2 - P3 - B4 - P5。但解码器必须先解码 I1,然后解码 P3,才能解码 B2(因为B2依赖P3)。所以解码顺序是 I1 - P3 - B2 - P5 - B4。

这时候,DTS 告诉解码器「按这个顺序解码」,PTS 告诉播放器「按那个顺序显示」。两者缺一不可。

我的习惯:在封装 MP4 或 TS 时,我会严格检查每一帧的 PTS 是否单调递增。如果发现 PTS 回退,那一定是封装层出了问题,需要立即修复。

1.3 时间戳的单位与基准

时间戳不是直接用「秒」来计的,那样精度不够。流媒体领域常用的时间基准有两种:

  • 毫秒(ms):简单直观,但精度有限,常用于低码率场景。
  • 时间基(time_base):用分数表示,比如 1/90000 秒。这是 MPEG-TS 和 RTP 的标准做法。

为什么是 90000?因为 90000 能被 24、25、30、50、60 这些常见帧率整除,计算起来不会产生小数误差。我刚开始做 RTP 推流时,直接用毫秒当时间戳,结果在 29.97fps 的场景下出现了周期性的音画偏移,查了两天才发现是精度不够。

避坑指南:千万不要在 RTP 中使用毫秒作为时间戳单位。RTP 标准要求时间戳的时钟频率必须与媒体流的采样率一致。对于视频,通常使用 90000 Hz;对于音频,使用采样率(如 44100 或 48000)。混用会导致接收端无法正确计算同步关系。

1.4 音视频不同步的典型现象

在实际项目中,我见过各种各样的不同步问题。归纳起来,主要有以下几种:

现象 可能原因 典型场景
声音比画面快 音频 PTS 偏小,或视频解码延迟 直播推流时编码器负载过高
声音比画面慢 音频缓冲区过大,或视频 PTS 跳跃 播放器缓冲策略不当
开始时同步,越往后越偏 音频和视频的时钟频率不一致 RTP 流中音频和视频使用不同的参考时钟
画面卡顿但声音正常 视频帧丢失或解码失败,播放器丢帧 弱网环境下的 RTP 传输
声音断续但画面流畅 音频包丢失或 Jitter Buffer 溢出 网络抖动严重

我曾经处理过一个线上事故:用户反馈直播画面和声音差了将近 3 秒。排查后发现,是推流端的音频采集线程和视频编码线程使用了不同的系统时钟,一个用了 CLOCK_MONOTONIC,另一个用了 CLOCK_REALTIME,两者在长时间运行后产生了漂移。从那以后,我要求团队所有时间戳必须统一来源。

1.5 音视频同步的核心逻辑图

下面这张图展示了音视频同步的基本流程。你可以看到,音频和视频各自独立解码,但最终通过 PTS 在播放端对齐。

音视频同步核心流程 音视频同步核心流程 音频采集 视频采集 音频编码 视频编码 音频 PTS 视频 PTS/DTS (B帧导致顺序不同) 复用 / 封装 RTP 传输 解复用 关键点 • PTS 决定显示时间 • DTS 决定解码顺序 • B帧导致 PTS ≠ DTS

从这张图你可以看到,音频和视频在采集、编码阶段是独立进行的。每个媒体单元都被打上了自己的时间戳。到了复用阶段,它们按照 PTS 的顺序交织在一起。传输和解复用后,播放器根据 PTS 重新对齐音频和视频,最终呈现给用户。

1.6 小结

这一章我们讲了时间戳的基础概念,PTS 和 DTS 的区别,以及不同步的典型现象。嗯,这些都是后面所有同步方案的地基。我个人觉得,理解 PTS 和 DTS 的关系是最容易踩坑的地方,尤其是 B 帧的处理。如果你现在还有点模糊,没关系,后面几章我们会反复用到这些概念,慢慢就熟了。