Pre-load an AVPlayer streaming video
Asked Answered
T

1

8

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.

Tjaden answered 16/10, 2014 at 20:29 Comment(1)
Follow this answer. #4218590 Might be helpful for you.Canthus
G
17

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.

Gripe answered 24/10, 2014 at 14:45 Comment(3)
Hmmm, that would involve a minor re-architecture of how our progress screen and playback screen interact. (One pushes the other, but that just might be worth it.) Also, I may be able to keep the AVPlayer as a singleton and just pass it to the new window once playbackLikelyToKeepUp is true.Tjaden
Upvote for your lovely answer. Can you please post sample code here. It would be of great help.Pentameter
Follow this answer. #4218590 Might be helpful for you.Canthus

© 2022 - 2024 — McMap. All rights reserved.