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 同步(音频为主)。FFmpeg 的默认行为经过了大量测试,覆盖了 80% 以上的场景。等遇到具体问题时,再针对性调整。
1.5 本章小结
音视频同步的基础,就是理解 PTS 和 DTS 的区别,以及三种同步策略的取舍。音频为主同步是默认选择,视频同步音频适合低延迟场景,音频同步视频则用于离线转码。
嗯,这里要注意:时间戳的精度直接影响同步效果。FFmpeg 内部使用 AVRational 来表示时间基,精度可以达到微秒级。但实际播放时,受硬件和驱动影响,误差可能在 10-50 毫秒之间。这个范围人眼基本察觉不到,算合格。