iOS 11 AVPlayer/mp3 当前时间不准确
iOS 11 AVPlayer/mp3 currentTime not accurate
我正在开发一个由动画和播放歌曲组成的卡拉 OK 应用程序。这里最重要的是两者之间非常精确的同步。
我几个月前实施了它,在 iOS 9 月 10 日,一切都运行良好。我们遇到了 Android 应用程序 (ExoPlayer) 的问题,因为播放和动画之间的延迟太大。最后我们发现问题是由错误的歌曲格式(mp3)引起的 - 在这里解释:https://github.com/google/ExoPlayer/issues/3233。我们通过将歌曲打包成 mp4 格式来修复它(在 iOS 上仍然使用 mp3)。
我使用带 HLS 的 AVPlayer
self.player = AVPlayer(url: url)
//
var currentTime_: Double {
if let player = self.player {
return player.currentTime().seconds
}
return 0
}
一切正常,直到 iOS 11 发布。在 iOS 11 上存在与 Android 上相同的去同步化(player.currentTime 不准确)。
有趣的是,即使是基于 iOS 10 SDK 构建并在 AppStore 上可用的应用程序也无法在 iOS 11 上正常运行 - 但它在 iOS 10 上仍然运行良好。
服务器端没有任何变化。所以 Apple 不得不在 decoding/buffering 中做出一些改变。现在我们正在努力改变音频 format/decoding 但我仍然很好奇 - 为什么会这样?有人遇到过类似的事情吗?
此致
创建 AVURLAsset 时需要使用此选项
let asset = AVURLAsset(url: url, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
如果不使用该选项,AVPlayer 会根据文件长度测量 mp3 音频时长,因此获取时长误差较小。
正如 woosiki 指出的那样,您需要使用 AVURLAsset。请记住,由于 pre-calculation 的精确持续时间,加载大文件将花费更长的时间。您可能想放置一个加载器指示器。
func prepareAudioFile(with track: Track) {
guard let url = URL(string: track.streamURL) else {
return
}
let asset = AVURLAsset(url: url,
options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem)
observePlayerProgress()
}
private func observePlayerProgress() {
let interval = CMTimeMake(value: 1, timescale: 5)
player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
if let track = self?.player.currentItem, track.status == .readyToPlay {
// Once the loading is finished this callback will return
// Here you can calculate and set duration and elapsed time (track.duration, time.seconds)
}
}
}
我正在开发一个由动画和播放歌曲组成的卡拉 OK 应用程序。这里最重要的是两者之间非常精确的同步。
我几个月前实施了它,在 iOS 9 月 10 日,一切都运行良好。我们遇到了 Android 应用程序 (ExoPlayer) 的问题,因为播放和动画之间的延迟太大。最后我们发现问题是由错误的歌曲格式(mp3)引起的 - 在这里解释:https://github.com/google/ExoPlayer/issues/3233。我们通过将歌曲打包成 mp4 格式来修复它(在 iOS 上仍然使用 mp3)。
我使用带 HLS 的 AVPlayer
self.player = AVPlayer(url: url)
//
var currentTime_: Double {
if let player = self.player {
return player.currentTime().seconds
}
return 0
}
一切正常,直到 iOS 11 发布。在 iOS 11 上存在与 Android 上相同的去同步化(player.currentTime 不准确)。 有趣的是,即使是基于 iOS 10 SDK 构建并在 AppStore 上可用的应用程序也无法在 iOS 11 上正常运行 - 但它在 iOS 10 上仍然运行良好。
服务器端没有任何变化。所以 Apple 不得不在 decoding/buffering 中做出一些改变。现在我们正在努力改变音频 format/decoding 但我仍然很好奇 - 为什么会这样?有人遇到过类似的事情吗?
此致
创建 AVURLAsset 时需要使用此选项
let asset = AVURLAsset(url: url, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
如果不使用该选项,AVPlayer 会根据文件长度测量 mp3 音频时长,因此获取时长误差较小。
正如 woosiki 指出的那样,您需要使用 AVURLAsset。请记住,由于 pre-calculation 的精确持续时间,加载大文件将花费更长的时间。您可能想放置一个加载器指示器。
func prepareAudioFile(with track: Track) {
guard let url = URL(string: track.streamURL) else {
return
}
let asset = AVURLAsset(url: url,
options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem)
observePlayerProgress()
}
private func observePlayerProgress() {
let interval = CMTimeMake(value: 1, timescale: 5)
player.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
if let track = self?.player.currentItem, track.status == .readyToPlay {
// Once the loading is finished this callback will return
// Here you can calculate and set duration and elapsed time (track.duration, time.seconds)
}
}
}