19

I'm building an app which plays an audio stream (from a webradio).

I'm using AVPlayer for it.

  1. I'd like to know how you would handle AVPlayer's "buffering" when the connection is slow or when the user just clicked "play". I want to detect that AVPlayer is "buffering" to display an UIActivityIndicatorView.

  2. Same question while running in the background. What should I do if buffering in this case?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Quentin Hayot
  • 7,786
  • 6
  • 45
  • 62

4 Answers4

27

For the first question

You can refer to my answer on this topic ios avplayer trigger streaming is out of buffer

For the second

Here is how I solved this same problem:

Inside where you handle the event for buffer empty add this code:

    if (object == playerItem && [keyPath isEqualToString:@"playbackBufferEmpty"])
    {
        if (playerItem.playbackBufferEmpty) {
            [[NSNotificationCenter defaultCenter] postNotificationName:@"message" object:@"Buffering..."];
            
            if([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground)
            {
                task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) {
                }];
            }
        }
    }

Now you will have to stop this background task after your buffer is ready to go again:

if (object == playerItem && [keyPath isEqualToString:@"playbackLikelyToKeepUp"])
{
    if (playerItem.playbackLikelyToKeepUp)
    {
        [player play];
        
        if([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground)
        {
            [[UIApplication sharedApplication] endBackgroundTask:task];
            task = 0;
        }
    }
}

ps: task is declared on my .h file as UIBackgroundTaskIdentifier task;

Community
  • 1
  • 1
sciasxp
  • 1,031
  • 10
  • 12
  • Why do you need a bg task here? I don't see the connection. – z8000 Nov 09 '11 at 15:52
  • 5
    This happens because when your application is in background and for some reason your stream is halted iOS will terminate your player and you will not be able to continue once you start receive streaming again. So with this we can cheat on iOS to make it think that your player is still working. – sciasxp Nov 14 '11 at 03:06
  • 1
    Do you need anything inside your task block? Or does that exist just to keep a loop running on the app delegate? – quantumpotato May 25 '12 at 19:16
10

I have found the solution to this problem.

if (self.avPlayer.currentItem.playbackLikelyToKeepUp == NO) 
{
    // Show activity indicator
}
pablasso
  • 2,479
  • 2
  • 26
  • 32
Nir
  • 399
  • 3
  • 22
2

For Swift 3

This works fine for me, maybe it can help, call self?.bufferState() inside addPeriodicTimeObserver

    private func bufferState() {
    if let currentItem = self.avPlayer.currentItem {
        if currentItem.status == AVPlayerItemStatus.readyToPlay {
            if currentItem.isPlaybackLikelyToKeepUp {
                print("Playing ")
            } else if currentItem.isPlaybackBufferEmpty {
                print("Buffer empty - show loader")
            }  else if currentItem.isPlaybackBufferFull {
                print("Buffer full - hide loader")
            } else {
                print("Buffering ")
            }
        } else if currentItem.status == AVPlayerItemStatus.failed {
            print("Failed ")
        } else if currentItem.status == AVPlayerItemStatus.unknown {
            print("Unknown ")
        }
    } else {
        print("avPlayer.currentItem is nil")
    }
}
DoubleK
  • 542
  • 3
  • 16
0

Try this:

AVPlayerItem* mPlayerItem;

if(context == AVPlayerDemoPlaybackViewControllerCurrentItemBufferEmptyContext) 
{
    if (object == self.mPlayerItem && [path isEqualToString:@"playbackBufferEmpty"]) 
    {
        if (self.mPlayerItem.playbackBufferEmpty)
        {
            playBufferEmpty = TRUE;
            [indicator startAnimating];
            [vidStreaminglabel setText:@"Buffering..."];
            [vidStreaminglabel setHidden:NO];
        }
    }
}

else if(context == AVPlayerDemoPlaybackViewControllerCurrentItemPlayBackBufferFullContext)
{
    if (object == mPlayerItem && [path isEqualToString:@"playbackBufferFull"]){
        if (self.mPlayerItem.playbackBufferFull) {
            [mPlayer play];
        }
    }
}

else if (context == AVPlayerDemoPlaybackViewControllerCurrentItemPlayBackLikelyToKeepUpContext)
{
    if (object == mPlayerItem && [path isEqualToString:@"playbackLikelyToKeepUp"])
    {
         if(self.mPlayerItem.playbackLikelyToKeepUp)
         {
             // Autoplay after buffer 
             if(!(mRestoreAfterScrubbingRate != 0.f || [self.mPlayer rate] != 0.f))
             {
                 if (self.presentingViewController) {
                     [mPlayer play];
                 }

                 playBufferEmpty = FALSE;
                 [indicator stopAnimating];
                 [vidStreaminglabel setHidden:YES];
             }
        }
    }
}
NSPratik
  • 4,714
  • 7
  • 51
  • 81