我看到很多资源建议在现代Android版本上使用AudioTrack.getTimestamp()
来计算音频/视频同步的音频延迟。
例如:
https://stackoverflow.com/a/37625791/332798
https://developer.amazon.com/docs/fire-tv/audio-video-synchronization.html#section1-1
https://groups.google.com/forum/#!topic/android-platform/PoHfyNK54ps
但是,这些都没有解释如何使用时间戳来计算延迟?我正在努力想弄清楚如何处理时间戳的framePosition / nanoTime来提出延迟数字。
答案 0 :(得分:1)
因此,在此API之前,您将使用AudioTrack.getPlaybackHeadPosition()
,这只是一个近似值。因此,为了考虑延迟,您必须使用两种隐藏方法之一的延迟值来抵消该值:AudioManager.getOutputLatency()
或AudioTrack.getLatency()
。
使用新的AudioTrack.getTimestamp()
API,您可以直接在输出中获取给定时间播放头位置的快照。因此,它完全准确并且已经考虑了设备延迟。因此,现在无需调用任何其他API来添加/删除延迟。
需要注意的是,此时间戳只是一个快照,文档建议您不要经常调用此新方法。因此获得“当前”位置的技巧是使用您的上一个快照并线性插入当前值应该是:
playheadPos = timestamp.framePosition +
(System.nanoTime() - timestamp.nanoTime) * samplerate / 1e9;
然后可以将此位置与您在AudioTrack
中写入的帧数进行比较,方法是维护另一个计数器,该计数器每次AudioTrack.write()
完成时递增:
int bytesWritten = track.write(...);
writtenPos += bytesWritten / pcmFrameSize;
如果您正在使用ENCODING_AC3
,AudioTrack
报告的播放头位置仍然是样本。您需要将其转换为字节,或将您写入的字节数转换回样本。无论哪种方式,您都需要知道AC3流的比特率(即384000bps
)
int bytesWritten = track.write(...);
writtenPos += bytesWritten * samplerate / (bitrate / 8);