Reputation: 23
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)
We didn't have the problem with AVAudioPlayer, but (AFAIK) we have to use AVPlayer because we need the better quality "spectral:" AVAudioTimePitchAlgorithm.
[Edit:] - The error is consistent - it always plays from the same (wrong) place for a given requested position. This is also true after restarting.
Any help very much appreciated! Thanks
[Edit:]
preferredTimescale: playerTimescale
kCMTimeIndefinite
instead of kCMTimeZero
Upvotes: 2
Views: 2582
Reputation: 36169
This is what AVURLAsset
’s AVURLAssetPreferPreciseDurationAndTimingKey
is for.
Beware that this should increase the loading time.
Upvotes: 2
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
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