AVPlayer Seek не точен даже с допускомДо: 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, но (насколько мне известно) мы должны использовать AVPlayer, потому что нам нужен более качественный «спектральный»: AVAudioTimePitchAlgorithm.

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

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

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

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

person Ian C    schedule 08.02.2019    source источник
comment
Это похоже на работу для AVURLAssetPreferPreciseDurationAndTimingKey developer.apple.com/documentation/avfoundation/   -  person Rhythmic Fistman    schedule 08.02.2019
comment
@RhythmicFistman, который это исправил. Большое спасибо, очень ценю вашу помощь в этом. По какой-то причине я не могу щелкнуть галочкой, чтобы принять этот ответ, поскольку он находится в комментарии, но если вы сделаете репост в качестве ответа, я приму его.   -  person Ian C    schedule 11.02.2019
comment
Большой! Я превратил свое спекулятивное предположение в авторитетный ответ.   -  person Rhythmic Fistman    schedule 11.02.2019


Ответы (3)


Это то, для чего предназначен AVURLAssetPreferPreciseDurationAndTimingKey AVURLAsset.

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

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

person Rhythmic Fistman    schedule 11.02.2019

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

 @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
            })
person Enea Dume    schedule 08.02.2019
comment
Спасибо, Энеа, мы пробовали это, но это не помогло, но спасибо за предложение. - person Ian C; 08.02.2019

Попробуйте это, у меня это отлично работает

@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()
        }
    }
}
person Naveen Paulsingh    schedule 08.02.2019
comment
Спасибо, Навин, мы попробовали это, но в итоге это был AVURLAssetPreferPreciseDurationAndTimingKey. Но ценю ваше предложение. - person Ian C; 11.02.2019