如何在Android中使用AudioTrack.getTimestamp()计算音频延迟?
我完全懂这种看了一堆资料却没拿到实操细节的困惑!之前做音视频同步的时候,我也对着AudioTrack.getTimestamp()卡了好久,现在把我摸透的实操逻辑分享给你:
用AudioTrack.getTimestamp()计算音频延迟&实现音视频同步
首先得先搞懂这个方法返回的AudioTimestamp对象里的两个核心字段——这是一切计算的基础:
framePosition:已经提交到音频硬件但还没播放的音频帧的起始位置(简单说就是“排队等着出声”的那批音频的开头帧号)nanoTime:对应这个帧位置,硬件预计开始播放的系统纳秒时间(和System.nanoTime()用的是同一个时间基准,不受系统时钟调整影响)
1. 正确获取时间戳
建议在音频播放的周期性回调(比如AudioTrack.OnPlaybackPositionUpdateListener的onPeriodicNotification())里定期获取,或者在你需要做音视频同步的节点主动调用:
AudioTimestamp timestamp = new AudioTimestamp(); boolean isSupported = audioTrack.getTimestamp(timestamp); if (!isSupported) { // 注意:部分旧设备/低版本Android不支持该方法,要准备降级方案(比如用getPlaybackHeadPosition()估算) return; }
2. 计算当前音频播放延迟
延迟的核心计算逻辑很直接——因为nanoTime是硬件预计播放该帧的时间,用它减去当前的系统时间,就是这部分音频还要等多久才会被用户听到:
long currentSystemTime = System.nanoTime(); long playbackDelayNanos = timestamp.nanoTime - currentSystemTime;
- 如果
playbackDelayNanos是正数:说明这帧还要等这么久才会播放,数值就是当前的音频缓冲延迟 - 如果是负数:说明这帧已经在播放中了(可能是调用时机的问题,取绝对值即可)
3. 关联音视频时间戳实现同步
要实现同步,你需要把音频的播放时间和视频的显示时间对齐:
- 先把音频的
framePosition转换成时间戳(和视频用同一个时间基准,比如纳秒):long audioFrameTimeNanos = (timestamp.framePosition * 1_000_000_000L) / audioTrack.getSampleRate(); - 结合刚才算出的延迟,得到这个音频帧实际被用户听到的时间:
long actualAudioPlayTimeNanos = audioFrameTimeNanos + playbackDelayNanos; - 最后调整视频的显示时机:比如你的视频帧的显示时间戳是
videoPtsNanos,如果videoPtsNanos比actualAudioPlayTimeNanos早,就暂停视频等音频追上;如果视频慢了,就丢帧让视频赶上来。
避坑提醒
- 全程用
System.nanoTime()作为时间基准,绝对不要用System.currentTimeMillis()——后者会受系统时间调整(比如手动改时间、NTP同步)影响,直接导致同步错乱 - 不要太频繁调用
getTimestamp(),比如每100ms调用一次就足够,太频繁会额外消耗性能 - 一定要处理
getTimestamp()返回false的情况,给旧设备留好降级方案
内容的提问来源于stack exchange,提问作者tmm1
相关产品推荐
相关产品推荐

