1、音视频同步基础:从原理到策略

音视频同步,圈里人常说的「唇同步」。说白了,就是让画面里人的嘴型和声音对上。你想想看,一部电影如果声音比画面快半秒,那观感有多难受。我刚开始做流媒体时,就栽过这个跟头——直播推流出去,观众反馈「声画不同步」,排查了整整两天。

这一章,我们先打好地基。把 PTS、DTS 这些概念理清楚,再看三种同步策略分别怎么选。

1.1 音视频时间戳:PTS 和 DTS

时间戳是同步的命根子。没有它,解码器根本不知道什么时候该显示哪一帧。

  • PTS(Presentation Time Stamp):显示时间戳。告诉解码器:这一帧应该在哪个时间点展示给用户。
  • DTS(Decoding Time Stamp):解码时间戳。告诉解码器:这一帧应该在哪个时间点开始解码。

为什么需要两个?因为有 B 帧(双向预测帧)。B 帧依赖前后的帧才能解码,所以解码顺序和显示顺序不一样。

关键点:对于音频来说,PTS 和 DTS 通常是相等的。因为音频帧没有 B 帧这种依赖关系,解码即显示。视频就复杂多了。

举个例子。一个典型的 GOP(图像组)结构:

帧类型: I  B  B  P  B  B  P
解码顺序: 0  2  3  1  5  6  4
显示顺序: 0  1  2  3  4  5  6

你看,B 帧的解码顺序排在后面,但显示顺序却在前面。这就是 DTS 和 PTS 不一致的原因。

概念 全称 作用 音频场景 视频场景
PTS Presentation Time Stamp 决定何时显示 等于 DTS 可能 ≠ DTS(有 B 帧时)
DTS Decoding Time Stamp 决定何时解码 等于 PTS 可能早于 PTS

我的习惯:在 FFmpeg 命令行里,我经常加 -vsync 2 或者 -af "aresample=async=1" 来处理时间戳异常。后面章节会细讲这些参数。

1.2 音视频同步的原理

同步的核心,就是维护一个「主时钟」。所有音视频帧都拿自己的 PTS 和这个主时钟比较。如果视频帧的 PTS 比主时钟大,说明视频快了,需要等待;如果小了,说明视频慢了,需要丢帧或加速。

主时钟有三种选择:

  • 系统时钟:用 av_gettime() 获取的绝对时间。简单粗暴,但容易漂移。
  • 音频时钟:以音频播放的进度为基准。音频播放是连续的,所以精度高。
  • 视频时钟:以视频帧的 PTS 为基准。但视频帧是离散的,容易抖动。

我个人最常用音频时钟。为什么?因为人耳对声音的抖动比眼睛对画面的抖动敏感得多。你画面跳一帧可能没感觉,但声音卡一下立刻就能察觉。

避坑指南:我曾经在一个项目中,直接用系统时钟做主时钟。结果跑了半小时后,音频和视频的偏差越来越大。后来发现是系统时钟的精度不够,加上音频驱动有缓冲延迟。换成音频时钟后,问题就解决了。

1.3 三种同步策略

FFmpeg 提供了三种同步模式。选哪个,取决于你的应用场景。

策略一:A/V 同步(音频为主)

这是最常用的模式。以音频时钟为主时钟,视频去对齐音频。

  • 原理:视频帧的 PTS 与音频时钟比较。视频快了就等待,慢了就丢帧。
  • 优点:音频播放连续,用户体验好。
  • 缺点:如果音频源本身有问题(比如采样率不准),视频会跟着遭殃。
  • 适用场景:直播、视频通话、大多数点播场景。
# FFmpeg 默认就是音频为主同步
ffmpeg -i input.mp4 -c copy output.mp4

# 显式指定音频为主同步
ffmpeg -i input.mp4 -c copy -vsync 1 output.mp4

策略二:视频同步音频

和策略一类似,但更激进。视频帧如果落后太多,直接丢弃。

  • 原理:视频帧的 PTS 与音频时钟比较。如果视频帧的 PTS 小于当前音频时钟,直接丢掉这帧。
  • 优点:保证实时性,不会出现画面堆积。
  • 缺点:画面可能会跳帧,看起来不流畅。
  • 适用场景:低延迟直播、实时监控。
# 使用 -vsync 2 开启丢帧模式
ffmpeg -i input.mp4 -c copy -vsync 2 output.mp4

策略三:音频同步视频

以视频时钟为主时钟,音频去对齐视频。这个模式用得少,因为音频变速或变调会很难听。

  • 原理:音频帧的 PTS 与视频时钟比较。音频快了就拉长(降采样),慢了就压缩(升采样)。
  • 优点:视频播放绝对流畅,不丢帧。
  • 缺点:音频可能变调,听起来像「加速」或「慢放」。
  • 适用场景:视频编辑、离线转码(允许音频重采样)。
# 使用 -vsync 0 关闭视频同步,音频去对齐视频
ffmpeg -i input.mp4 -c copy -vsync 0 output.mp4
策略 主时钟 对齐方式 优点 缺点 典型场景
A/V 同步(音频为主) 音频时钟 视频对齐音频 音频连续,体验好 视频可能丢帧或重复 直播、点播
视频同步音频 音频时钟 视频丢帧对齐 实时性强 画面跳帧 低延迟直播
音频同步视频 视频时钟 音频变速对齐 视频流畅 音频变调 离线转码

1.4 同步策略选择框架

下面这张图,是我自己总结的同步策略选择流程。每次做项目前,我都会过一遍。

音视频同步策略选择框架 输入音视频流 是否需要低延迟? 是 否 视频同步音频(丢帧) A/V 同步(音频为主) 音频源是否稳定? 视频源是否稳定? 保持视频同步音频 保持 A/V 同步 提示:音频源不稳定时,考虑音频同步视频 但要做好音频重采样和变调补偿

我的经验:如果你不确定选哪个策略,就用默认的 A/V 同步(音频为主)。FFmpeg 的默认行为经过了大量测试,覆盖了 80% 以上的场景。等遇到具体问题时,再针对性调整。

1.5 本章小结

音视频同步的基础,就是理解 PTS 和 DTS 的区别,以及三种同步策略的取舍。音频为主同步是默认选择,视频同步音频适合低延迟场景,音频同步视频则用于离线转码。

嗯,这里要注意:时间戳的精度直接影响同步效果。FFmpeg 内部使用 AVRational 来表示时间基,精度可以达到微秒级。但实际播放时,受硬件和驱动影响,误差可能在 10-50 毫秒之间。这个范围人眼基本察觉不到,算合格。