iOS 11 AVPlayer / mp3 currentTime不准确

时间:2017-11-07 13:02:13

标签: android ios synchronization delay avplayer

我正在开发一个卡拉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必须在解码/缓冲方面改变一些东西。现在我们正在努力改变音频格式/解码,但我仍然很好奇 - 为什么会发生这种情况?有人遇到过类似的东西吗?

此致

2 个答案:

答案 0 :(得分:0)

创建AVURLAsset时需要使用此选项

let asset = AVURLAsset(url: url, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true])

如果您不使用此选项,AVPlayer会按文件长度测量mp3音频持续时间,因此获取持续时间的误差很小。

答案 1 :(得分:0)

正如woosiki指出的那样,您需要使用AVURLAsset。请记住,由于要精确计算持续时间,因此加载大文件将花费更长的时间。您可能需要放置一个加载器指示器。

  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)
      }
    }
  }