1. 音视频基础概念:PTS、DTS、时间基、帧率、采样率

做音视频同步,说白了就是跟时间打交道。你连时间怎么算的都不清楚,那同步根本无从谈起。这一章我把最核心的几个概念掰开揉碎讲清楚,都是我自己这些年踩坑总结出来的。

1.1 帧率与采样率——两个世界的节奏

视频和音频,本质上是两个完全不同的数据流。视频是一张张图片快速切换,音频是一段段波形连续振动。它们各自有自己的“心跳”。

视频帧率(FPS)

帧率就是每秒显示多少张图像。单位是 fps(frames per second)。

  • 24 fps:电影标准,有胶片感
  • 25 fps:PAL 制式(中国、欧洲)
  • 29.97 fps:NTSC 制式(美国、日本)——注意这个奇葩数字,后面会讲
  • 30/50/60 fps:常见于直播、游戏、高清视频
我的经验: 帧率不是越高越好。我曾经接手一个项目,非要用 120fps 做直播,结果编码器扛不住,解码端也卡顿,最后音画不同步得一塌糊涂。选帧率要综合考虑带宽、编码能力和播放设备。

音频采样率(Sample Rate)

采样率是每秒对模拟音频信号采样的次数。单位是 Hz(赫兹)。

  • 8,000 Hz:电话语音质量
  • 44,100 Hz:CD 音质,最常用
  • 48,000 Hz:电影、广播、专业音频标准
  • 96,000 / 192,000 Hz:高解析音频,一般用不到

这里有个坑:视频帧率是整数或小数,音频采样率是几千几万。两个完全不同的节奏,怎么对齐?答案就在时间基里。

1.2 时间基(Time Base)——一切时间的标尺

时间基,你可以理解成“时间的最小刻度”。

举个例子:视频帧率是 25fps,那每帧的间隔是 1/25 = 0.04 秒。但计算机里用小数做运算容易丢精度,所以我们需要一个整数刻度。

时间基通常用分数表示,比如:

  • 1/90000:MPEG-TS 标准时间基,90kHz 时钟
  • 1/1000:毫秒级时间基
  • 1/25:直接对应 25fps 帧率

所有的时间戳(PTS/DTS)都是基于这个时间基的整数倍。比如时间基是 1/90000,那 1 秒就是 90000 个刻度,0.04 秒就是 3600 个刻度。

核心公式:
实际时间(秒) = 时间戳值 × 时间基
比如:PTS = 3600,时间基 = 1/90000 → 3600 × (1/90000) = 0.04 秒

1.3 PTS 与 DTS——解码和显示是两回事

这两个概念,我当年刚入行时也搞混过。简单说:

  • PTS(Presentation Time Stamp):什么时候显示这帧画面
  • DTS(Decoding Time Stamp):什么时候解码这帧数据

为什么会有两个时间戳?因为视频编码用了 B 帧(双向预测帧)。B 帧需要参考后面的帧才能解码,所以解码顺序和显示顺序不一样。

举个例子:一个 GOP(图像组)的帧顺序是 I B B P,显示顺序是 1 2 3 4,但解码顺序可能是 1 4 2 3。因为 B 帧要等后面的 P 帧解码后才能解码。

帧类型 显示顺序 解码顺序 说明
I 帧 1 1 关键帧,独立解码
B 帧 2 3 需要前后帧参考
B 帧 3 4 需要前后帧参考
P 帧 4 2 需要前向参考
我曾经踩过的坑: 有一次做播放器,直接把 DTS 当 PTS 用,结果画面顺序全乱了。人物说话嘴型对不上,动作像倒放。排查了两天才发现是时间戳用错了。记住:显示用 PTS,解码用 DTS。

1.4 音画同步的核心逻辑

音频和视频各自有独立的 PTS 流。播放器要做的事情很简单:

  1. 解码音频帧和视频帧
  2. 比较当前音频 PTS 和视频 PTS
  3. 如果视频快了,就等一等;如果视频慢了,就丢帧或加速

但实际没那么简单。音频的 PTS 是连续的,因为音频帧长度固定(比如每帧 1024 个采样点)。视频的 PTS 可能因为 B 帧、跳帧、丢帧而变得不连续。

所以大多数播放器以音频时钟为基准(Audio Clock Master),视频去对齐音频。为什么?因为人耳对音频抖动的敏感度远高于人眼对视频抖动的敏感度。

我个人的习惯: 在开发播放器时,我会先确保音频 PTS 的连续性。如果音频 PTS 出现跳变,那音画同步基本没救。视频那边偶尔丢一帧人眼看不出来,但音频卡一下所有人都能感觉到。

1.5 知识体系总览

下面这张图把本章的核心概念串起来了。你可以看到帧率、采样率、时间基、PTS/DTS 之间的关系。

音视频同步基础概念关系图 视频域 帧率 (fps) 时间基 PTS DTS 音频域 采样率 (Hz) 时间基 PTS DTS 音画同步引擎 以音频时钟为基准,对齐视频 PTS 关键说明: • 视频和音频各自有独立的时间基和 PTS/DTS • 时间基是统一的时间刻度,用于将 PTS/DTS 转换为实际时间 • 同步引擎以音频时钟为基准,通过比较 PTS 差值来调整播放节奏

1.6 避坑指南

最后分享几个我实际项目中遇到的坑,希望能帮你少走弯路。

  • 时间基不统一:我曾经遇到一个封装器,视频流用 1/90000 的时间基,音频流用 1/48000 的时间基。播放器没做转换,直接比较 PTS,结果音画永远对不上。解决办法:统一换算成微秒或毫秒再比较。
  • B 帧导致 PTS 乱序:有些编码器输出的 PTS 不是严格递增的,因为 B 帧的 PTS 可能小于前面的 P 帧。播放器必须按 PTS 排序后再显示,不能直接按接收顺序播放。
  • 帧率不是整数:29.97fps 这种奇葩帧率,每帧间隔是 33.3666... 毫秒。如果用整数除法,误差会累积。我习惯用有理数(比如 30000/1001)来精确表示。
  • 音频采样率突变:有些视频中间会切换音频采样率(比如从 44100 切到 48000)。如果播放器没处理好,PTS 计算会全乱。建议在切换点重新计算时间基。
一句话总结:
音画同步的本质,就是用统一的时间基,把视频的帧率和音频的采样率映射到同一个时间轴上,然后通过 PTS 比较来调整播放节奏。概念不难,但细节决定成败。