Ian C
Ian C

Reputation: 23

AVPlayer Seek not accurate even with toleranceBefore: kCMTimeZero

We have an app which plays a long mp3 file (1 hour long). We want to be able to play from set points within the file. But, when we do it, it is inaccurate by up to 10 seconds.

Here's the code:

  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)

Any help very much appreciated! Thanks

[Edit:]

Upvotes: 2

Views: 2582

Answers (3)

Gordon Childs
Gordon Childs

Reputation: 36169

This is what AVURLAsset’s AVURLAssetPreferPreciseDurationAndTimingKey is for.

Apple's documentation.

Beware that this should increase the loading time.

Upvotes: 2

Naveen Paulsingh
Naveen Paulsingh

Reputation: 89

Try this, It's working perfectly for me

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

Upvotes: 0

Enea Dume
Enea Dume

Reputation: 3232

I have done something similar but with a slider to change seconds of playing and worked perfectly.

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

in you case this will be like this:

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

Upvotes: 2

Related Questions