Reputation: 21
func seekFullRead(seconds: Float64, completion: (() -> ())? = nil) {
let targetTime:CMTime = CMTimeMakeWithSeconds(seconds, preferredTimescale: 60000)
fullReadPlayer?.currentItem?.seek(to: targetTime, toleranceBefore: .zero, toleranceAfter: .zero, completi[enter image description here][1]onHandler: { (finish) in
if finish {
completion?()
}
})
}
fullReadTimeObserver = fullReadPlayer?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 10), queue: DispatchQueue.main, using: { [weak self](time) in
guard let self = self else { return }
if self.fullReadPlayer?.status == .readyToPlay {
self.delegate?.audioPlayer(self, didUpdateCurrentTime: time.seconds, teach: nil)
}
})
When I seek to 4.57 seconds, the correct current time will be displayed first, then the current time will be 0.2 seconds forward, but playback will start after the current time will be 0.2 seconds forward.
Logs:
current time: 1.30104062
current time: 1.401042787
seek to : 4.579999923706055
current time: 1.498295786
current time: 4.579983333333334
current time: 4.319330793
current time: 4.319642834
current time: 4.401050459
current time: 4.501045084
current time: 4.601038959
Upvotes: 2
Views: 1502
Reputation: 63
I think NSGangster had the point. Observer timer and seek are on different processes. What this means to me is I will have to handle the discrepancies by myself.
I did not find an answer on the internet and had no luck in finding out a way to make this correct, but I did manage to find a workaround: I could use a variable like 'isSeekInProgress' to mark whether to update the progress bar UI. Illustrated below:
var isSeekInProgress: Bool = false // Marker
let targetTime:CMTime = CMTimeMakeWithSeconds(seconds, preferredTimescale: 60000)
isSeekInProgress = true // Mark
fullReadPlayer?.currentItem?.seek(to: targetTime, toleranceBefore: .zero, toleranceAfter: .zero, completi[enter image description here][1]onHandler: { (finish) in
if finish {
isSeekInProgress = false // Unmark
completion?()
}
})
Some people pause the player while seeking then resume playback in the completion block, but this won't work in the case you want the playback to keep going while scrubbing. The above example is fairly painless, and all you have to do is check:
if !playbackManager.isSeekInProgress {
progressSlider.value = playbackManager.progress
}
And during the next periodic observer notification, your progress will be updated.
Upvotes: 3