简体   繁体   English

iOS 11 AVPlayer/mp3 currentTime 不准确

[英]iOS 11 AVPlayer/mp3 currentTime not accurate

I am developing a karaoke app which consist of animation and playback song.我正在开发一个包含动画和播放歌曲的卡拉 OK 应用程序。 The most important thing here is very precise synchronization between both.这里最重要的是两者之间非常精确的同步。

I implemented it few months ago and on iOS 9/10 everything was working great.几个月前我实现了它,在 iOS 9/10 上一切运行良好。 We had a problem with Android app (ExoPlayer) because there were too big delay between playback and animation.我们在 Android 应用程序 (ExoPlayer) 上遇到了问题,因为播放和动画之间的延迟太大。 Finally we found out that the problem was caused by wrong song format (mp3) - which was explained here: https://github.com/google/ExoPlayer/issues/3233 .最后我们发现问题是由错误的歌曲格式(mp3)引起的 - 在这里解释: https : //github.com/google/ExoPlayer/issues/3233 We fixed it by packing song into mp4 format (on iOS there is still mp3 used).我们通过将歌曲打包成 mp4 格式来修复它(在 iOS 上仍然使用 mp3)。

I use AVPlayer with HLS我将 AVPlayer 与 HLS 一起使用

self.player = AVPlayer(url: url)

//
var currentTime_: Double {
    if let player = self.player {
        return player.currentTime().seconds
    }

    return 0
}

Everything was ok until iOS 11 release.一切正常,直到 iOS 11 发布。 On iOS 11 there is the same desynchronization (player.currentTime is not accurate) that was on Android.在 iOS 11 上存在与 Android 上相同的去同步化(player.currentTime 不准确)。 What's interesting is that even app that was build on iOS 10 SDK and is available on AppStore doesn't work properly on iOS 11 - but it still works great on iOS 10.有趣的是,即使是在 iOS 10 SDK 上构建并在 AppStore 上可用的应用程序也无法在 iOS 11 上正常运行——但它在 iOS 10 上仍然运行良好。

Nothing on server side was changed.服务器端没有任何变化。 So Apple had to change something in decoding/buffering.所以苹果不得不在解码/缓冲方面做出一些改变。 Right now we are working on changing audio format/decoding but still I am curious - why that has happened?现在我们正在努力改变音频格式/解码,但我仍然很好奇 - 为什么会发生这种情况? Anyone encountered something similar?有人遇到过类似的吗?

Regards问候

You need use this option when create AVURLAsset创建 AVURLAsset 时需要使用此选项

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

If you not use this option, AVPlayer measures mp3 audio duration by file length, so it has small error to get duration.如果不使用此选项,AVPlayer 会根据文件长度来测量 mp3 音频时长,因此获取时长误差很小。

As woosiki pointed it out, you need to use the AVURLAsset.正如woosiki 指出的那样,您需要使用AVURLAsset。 Just keep in mind that loading of large files will take longer due to the pre-calculation of the precise duration.请记住,由于预先计算了精确的持续时间,加载大文件需要更长的时间。 You may want to put a loader indicator.您可能想要放置一个加载器指示器。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM