iosswiftavfoundationavplayeravqueueplayer

Issue with AVQueuePlayer seek(to:) and CMTime


I have an AVQueuePlayer and I'm trying to, on button press, seek back 5 seconds.

My code is as follows:

func seekBack() {
    guard let currentTime = self.player?.currentTime() else { return }

    let currentTimeSeconds = CMTimeGetSeconds(currentTime)
    let newTimeSeconds = max(currentTimeSeconds - 5, 0)

    let newTime = CMTimeMakeWithSeconds(newTimeSeconds, currentTime.timescale)

    self.player?.seek(to: newTime)
}

The first time I press the seek back button, it seeks back the correct amount of time (5 seconds), but with every subsequent press, it seeks back to the new time from the first seek back action. If I then let the video play for longer than 5 seconds and press the button, it will properly seek back 5 seconds, but then get stuck as above.

For example, I play the video, and at the 10 second mark, I press the seek back button, and the player seeks back to 5 seconds. I then let the player play for another 1 second, and press the button again, and it only seeks back to the 5 second mark. If I press the button repeatedly, it will only ever seek back to the 5 second mark. If I then let the video play for another 10 seconds (total time ~15 seconds), and press the seek back button again, the player will seek back to 10 seconds and exhibit the same behavior.

I'm not sure if this has anything to do with it, but there is also a button to toggle the playback rate between 1.0, 1.5, and 2.0. The issue described above is exhibited with all 3 playback rates.

Since it's an AVQueuePlayer, I've also tried the following implementation with the same result (it uses the currentItem instead of just the player):

func seekBack() {
    guard let currentTime = self.player?.currentItem?.currentTime() else { return }

    let currentTimeSeconds = CMTimeGetSeconds(currentTime)
    let newTimeSeconds = max(currentTimeSeconds - 5, 0)

    let newTime = CMTimeMakeWithSeconds(newTimeSeconds, currentTime.timescale)

    self.player?.currentItem?.seek(to: newTime)
}

Solution

  • After messing around, I figured it out. For some reason,

    seek(to:)
    

    doesn't seem to work, but if I use the

    seek(to:toleranceBefore:toleranceAfter:)
    

    function with kCMTimeZero for both the before and after tolerance, it works fine.