Pre-load an AVPlayer streaming video

Paul Cezanne picture Paul Cezanne · Oct 16, 2014 · Viewed 11.1k times · Source

I'm trying to play a streaming video with a AVPlayer without any network delay. Fortunately, our app has a progress screen before the screen that plays the video. I'm hoping to use some of the time on this progress screen to pre-load the video so it plays without delay on the next screen.

The most promising approach that I've come up with is to use an AVQueuePlayer to play 2 videos, the first would be a video that I play off screen (so you don't see it) and is silent, so you don't hear it. From what I've read on SO AVQueuePlayer buffers the nth+1 video when the nth video is near completion.

Here's my code to do this:

    NSString *blackVideoPath = [[NSBundle mainBundle] pathForResource:@"black10-counting" ofType:@"MOV"];
    AVPlayerItem *blackVideoItem = [AVPlayerItem playerItemWithURL:[NSURL fileURLWithPath:blackVideoPath]];

    AVPlayerItem *realVideoItem = [AVPlayerItem playerItemWithURL:_videoWithEffectsURL];

    NSArray *theItems = [NSArray arrayWithObjects:blackVideoItem, realVideoItem, nil];
    AVQueuePlayer *theQueuePlayer = [AVQueuePlayer queuePlayerWithItems:theItems];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:[theItems firstObject]];


    AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer:theQueuePlayer];

    playerLayer.frame = self.view.bounds;
    [self.view.layer addSublayer:playerLayer];

    [theQueuePlayer play];

This does play my first video (for debugging I have a video with a counting soundtrack) but when reach the end and advance to the next screen (in playerItemDidReachEnd) my real video doesn't play immediately.

Just to make sure my URLs were correct I reversed blackVideoItem and realVideoItem in the list and I do hear the soundtrack to my "real" video.

I've searched SO a lot and it doesn't seem like there is a way to play a streaming video without a delay. I'd love to be wrong.

Answer

jlw picture jlw · Oct 24, 2014

You may be able to do this without AVQueuePlayer.

  • As early as possible, create the AVPlayer with the remote asset.
  • Observe the AVPlayerItem (playback buffers, etc.) to make sure it has buffered enough data to play smoothly at the beginning. (See: Preloading video to play without delay)
  • Show your progress screen.
  • When the player item is ready, remove the progress screen

Depending on the network connection, you may not experience smooth playback the whole way through, but monitoring the player item should let you show some UI if your player is buffering.