AVPlayer Поиск не точен даже с допуском. Перед: kCMTimeZero

У нас есть приложение, которое воспроизводит длинный mp3-файл (1 час). Мы хотим иметь возможность играть с заданных точек в файле. Но, когда мы делаем это, неточно до 10 секунд.

Вот код:

  let trackStart = arrTracks![MediaPlayer.shared.currentSongNo].samples

  let frameRate : Int32 = (MediaPlayer.shared.player?.currentItem?.asset.duration.timescale)!

  MediaPlayer.shared.player?.seek(to: CMTimeMakeWithSeconds(Double(trackStart), frameRate), 
    toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
  • Мы должны использовать AVPlayer, потому что нам нужен спектраль лучшего качества: AVAudioTimePitchAlgorithm.
  • У нас не было проблемы с AVAudioPlayer, но (AFAIK) мы должны использовать AVPlayer, потому что нам нужен спектраль лучшего качества: "AVAudioTimePitchAlgorithm.

  • [Правка:] - ошибка постоянна - она ​​всегда воспроизводится из одного и того же (неправильного) места для заданной запрошенной позиции. Это также верно после перезапуска.

Любая помощь очень ценится! Спасибо

[Редактировать:]

  • Мы уже пробовали preferredTimescale: playerTimescale
  • Также попробовал kCMTimeIndefinite вместо kCMTimeZero

3 ответа

Решение

Это то, что AVURLAsset"s AVURLAssetPreferPreciseDurationAndTimingKey для.

Документация Apple.

Помните, что это должно увеличить время загрузки.

Я сделал что-то подобное, но с ползунком, чтобы изменить секунды игры и работал отлично.

 @objc func handleSliderChange(sender: UISlider?){
        if let duration = player?.currentItem?.duration{
            let totalSeconds = CMTimeGetSeconds(duration)
            let value = Float64(videoSlider.value) * totalSeconds
            let seekTime = CMTime(value: CMTimeValue(value), timescale: 1)
            player?.seek(to: seekTime , completionHandler: { (completedSeek) in
                //do smthg later
            })
        }
    }

в вашем случае это будет так:

let trackStart = arrTracks![MediaPlayer.shared.currentSongNo].samples
let value = Float64(trackStart)
let seekTime = CMTime(value: CMTimeValue(value), timescale: 1)
MediaPlayer.shared.player?.seek(to: seekTime , completionHandler: { (completedSeek) in
                //do smthg later
            })

Попробуйте это, это прекрасно работает для меня

@IBAction func playbackSliderValueChanged(_ playbackSlider: UISlider) {
    let seconds : Int64 = Int64(playbackSlider.value)
    let targetTime: CMTime = CMTimeMake(value: seconds, timescale: 1)
    DispatchQueue.main.async {
        self.player!.seek(to: targetTime)
        if self.player!.rate == 0 { // if the player is not yet started playing
            self.player?.play()
        }
    }
}
Другие вопросы по тегам