16

I have some questions related to AVPlayer which are:

  1. When we pause the AVPlayer through [player pause] does the AVPlayer keep buffering the video from the network or does it just stop? I couldn't get any info related to this in apple's documentation. Also, is it possible to force the AVPlayer to keep buffering while in pause, so that if we have the paused video is in waiting for the first video to be ended then we wouldn't find any gap in between the videos?

  2. On pausing the AVPlayer can we have any event on [player pause].

  3. Can we show still image on AVPlayer for some seconds?

Thanks

Brian Sachetta
  • 3,319
  • 2
  • 34
  • 45
Omer Waqas Khan
  • 2,423
  • 4
  • 33
  • 62
  • Check out AVQueuePlayer for multi-item sequential gapless playback. – MikeyWard Jul 19 '13 at 15:44
  • Used it already, it does not handle the streamed audio/video content, I have done it already using AVPlayer. Thanks – Omer Waqas Khan Aug 02 '13 at 12:32
  • @OmerWaqasKhan Use Charles to observe your app 's network packet, and you can see that player still sends network requests when paused – onmyway133 Jun 26 '15 at 10:53
  • @OmerWaqasKhan a workaround is to send `nil` to `replaceCurrentItemWithPlayerItem` and on `viewWillAppear`, replace with the old one – onmyway133 Jun 26 '15 at 11:09
  • Follow this answer. http://stackoverflow.com/questions/4218090/pre-buffering-for-avqueueplayer/39036307#39036307 Might be helpful for you. – iPatel Aug 19 '16 at 10:39

1 Answers1

39

1) AVPlayer will buffer the video in several cases, none cleary documented. I'd say you can expect buffering when you init the video, and when you replace the current item. You can observe currentItem.loadedTimeRanges to know what's going on. That property will tell you which video time ranges has been loaded.

Also, there is a few other currentItem properties that may help you: playbackLikelyToKeepUp, playbackBufferFull and playbackBufferEmpty.

Achieving a perfect gapless playback is not easy.

/* player is an instance of AVPlayer */
[player addObserver:self 
         forKeyPath:@"currentItem.loadedTimeRanges" 
            options:NSKeyValueObservingOptionNew 
            context:kTimeRangesKVO];    

In observeValueForKeyPath:ofObject:change:context::

if (kTimeRangesKVO == context) {
   NSArray *timeRanges = (NSArray *)[change objectForKey:NSKeyValueChangeNewKey];
   if (timeRanges && [timeRanges count]) {
       CMTimeRange timerange = [[timeRanges objectAtIndex:0] CMTimeRangeValue];
       NSLog(@" . . . %.5f -> %.5f", CMTimeGetSeconds(timerange.start), CMTimeGetSeconds(CMTimeAdd(timerange.start, timerange.duration)));
   }
}

2) Just keep an eye on player.rate.

[player addObserver:self 
         forKeyPath:@"rate" 
            options:NSKeyValueObservingOptionNew 
            context:kRateDidChangeKVO];

Then in your observeValueForKeyPath:ofObject:change:context::

    if (kRateDidChangeKVO == context) {
        NSLog(@"Player playback rate changed: %.5f", player.rate);
        if (player.rate == 0.0) {
            NSLog(@" . . . PAUSED (or just started)");
        }
    }

3) You can build a movie of a given length using a still image but it's easier to use a regular UIImageView on top of the player. Hide/show it when needed.

Sample project: feel free to play with the code I wrote to support my answer.

Community
  • 1
  • 1
djromero
  • 19,551
  • 4
  • 71
  • 68
  • 1
    thanx madmw, and can we force the avplayer to keep buffering while in pause state? – Omer Waqas Khan May 18 '12 at 12:03
  • AFAIK there is no public api to work with AVPlayer buffer. If you want to keep buffering beyond the pause point you can fake the pause: keep playing w/out volume and with the view hidden, then use seekToTime to resume playback. – djromero May 18 '12 at 12:13
  • Thanks for this! A concrete example helped a lot. – user2734823 Aug 13 '14 at 02:23
  • i remove "kTimeRangesKVO" Observer but it not remove and continuously call please help me – Hardik Kardani Jan 19 '15 at 06:38
  • @JaiminPatel you know it's hard, close to impossible, to help you with such little information, right? Add a more detailed comment or consider asking a different question. – djromero Jan 19 '15 at 11:22
  • i try to remove observer like that [appDelegate.player removeObserver:self forKeyPath:@"currentItem.playbackBufferEmpty" context:nil]; but it not remove and application are crash. – Hardik Kardani Jan 19 '15 at 12:15
  • Use appDelegate.player.currentItem instead of appDelegate.player for both addObserver / removeObserver. Of course forKeyPath:@"currentItem.loadedTimeRanges" should be just forKeyPath:@"loadedTimeRanges" – Borzh Feb 06 '15 at 14:16
  • Follow this answer. http://stackoverflow.com/questions/4218090/pre-buffering-for-avqueueplayer/39036307#39036307 Might be helpful for you. – iPatel Aug 19 '16 at 10:39
  • Thanks for you explanation and file on github. This file help a lot to understand more how to work with it! – Daniel Arantes Loverde Nov 16 '16 at 19:29