Seek to a certain position in AVPlayer right after the asset was loaded

Besi picture Besi · Aug 26, 2012 · Viewed 24.7k times · Source

This works: I have an AVPlayer which plays a video right after it was loaded. And this works fine.

This doesn't:

Instead of starting the video at the beginning, I want to play it at a given position. So I wait until the asset is ready for Play using KVO:

BOOL isReadyToSeek = (self.playerItem.status == AVPlayerStatusReadyToPlay)

And then seek to the given time

[playerItem seekToTime:timeInTheMiddleOfTheVideo completionHandler:myHandler];

But the player will always start at the beginning of the video on the initial seek.

Update I tried a dispatch_after with a few seconds but that does not work either. It works after playback but never initially.

When I observe self.player.currentItem.duration I keep getting 0 as the value and timescale.

Answer

user244343 picture user244343 · Aug 27, 2012

Couple of things which may help you:

  1. When checking if the player is ready to play, I check both the player itself and also the player's current item.

    if(self.player.status == AVPlayerStatusReadyToPlay &&
       self.player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
        [self.player play];
    }
    
  2. It's possible that if you seek to e.g. 15 seconds, it may start from the beginning of the video instead if that is the location of the nearest keyframe. To force the player to seek to the exact location (note: this will take several seconds to do), do this:

    Float64 seconds = 500.0f;
    CMTime targetTime = CMTimeMakeWithSeconds(seconds, NSEC_PER_SEC);
    [self.player seekToTime:targetTime
     toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
    

    Or you can seek to the keyframe explicitly before/after the specified point by specifying one of the arguments as infinity:

    [self.player seekToTime:targetTime
     toleranceBefore:kCMTimePositiveInfinity toleranceAfter:kCMTimeZero];