avplayer seek 在音频文件中播放错误的位置

avplayer seek plays wrong position in audio file

我想使用 AVPlayer 在 iphone 上播放音频文件。音频文件是设备本地存储中的 mp3 文件。我需要将它(播放的文件)与外部时间源同步。该时间源在播放过程中可能会发生变化,因此有时需要进行同步。我使用以下代码更改播放的音频文件中的时间:

player.play()

//sth here......


//the code which is executed periodically whene it is time to synchronize
let currentShowTime = ...... //time in miliseconds
print("current show time \(currentShowTime)")
let timescale = player.currentItem!.asset.duration.timescale
let currentTime = CMTime(value:Int64(Float64(currentShowTime!) * Float64(timescale) / 1000.0), timescale:timescale)

//alternative way I count the seek time but the effect is the same
//let currentTime = CMTimeMakeWithSeconds(Float64(currentShowTime!)/1000.0, 1000)

print("currenttime \(currentTime)")
player!.seek(to: currentTime,toleranceBefore:kCMTimeZero, toleranceAfter:kCMTimeZero ){done in
  print("done: \(done)")                                                        
  print("player currenttime \(self.player!.currentItem!.currentTime().seconds)")
}

问题是音频文件播放错了地方。所有参数:当前显示时间、当前时间和播放器当前时间都相同(打印相同的值)。但我听说声音发生了变化。当播放文件的开头时,偏移很小(可能是 500 毫秒),但当播放到结尾(文件的 20 分钟)时,偏移就大得多(大约 8 秒)。我还注意到,当我提供较小的 mp3 文件(比特率较低)时,偏移量较小,但当文件质量较高时,偏移量最多为 20 秒。 我做错了什么还是 AVPlayer 中的错误?

我假设您使用的文件是 VBR(可变比特率)mp3 文件。 AVFoundation 在搜索 VBR 文件时遇到问题 - 它使用

averageBitRate = totalBytes / duration
offset = seekTime * averageBitRate

但对于 VBR 文件,averageBitRate 在整个文件中不是恒定的,因此 offset 可能计算错误。

您需要 re-encode 具有恒定比特率的 mp3。