Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle streaming events with AVPlayer

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?

like image 515
Quentin Hayot Avatar asked Jun 16 '11 00:06

Quentin Hayot


3 Answers

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;

like image 189
sciasxp Avatar answered Nov 08 '22 13:11

sciasxp


I have found the solution to this problem.

if (self.avPlayer.currentItem.playbackLikelyToKeepUp == NO) 
{
    // Show activity indicator
}
like image 26
Nir Avatar answered Nov 08 '22 14:11

Nir


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")
    }
}
like image 33
DoubleK Avatar answered Nov 08 '22 13:11

DoubleK