Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling AVPlayer stalls

I'm trying to catch a moment when AVPlayer is unable to continue playback in case no more media available (too slow network, signal loss, etc). As described in documentation and different examples I'm using KVO to detect this:

item = [[AVPlayerItem alloc] initWithURL:audioURL];
player = [AVPlayer playerWithPlayerItem:item];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onItemNotification:) name:AVPlayerItemPlaybackStalledNotification object:item];
[item addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[item addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];

...

- (void) onItemNotification:(NSNotification*)not
{
    NSLog(@"Item notification: %@", not.name);
}

...

- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
    NSLog(@"Observe keyPath %@", keyPath);
}

I'm starting a playback and turn WiFi off after that. Unfortunately neither 'playbackBufferEmpty' nor 'AVPlayerItemPlaybackStalledNotification' comes. At the moment when playback stops I receive only one AVPlayerItemTimeJumpedNotification and that's all. However there were at least 2 times when I got these notifications. But I can't figure out how to get them every time when playback is stalled. Am I doing something wrong?

like image 798
san Avatar asked Dec 26 '13 12:12

san


People also ask

How do I stop AVPlayer in Objective C?

How do I stop AVPlayer in Objective C? AVPlayer does not have a method named stop . You can pause or set rate to 0.0.

What is Avplayeritem?

An object that models the timing and presentation state of an asset during playback.

How do I use AVPlayer in SwiftUI?

VideoPlayer in SwiftUIimport AVKit import SwiftUI struct ContentView: View { var body: some View { VideoPlayer(player: AVPlayer(url: Bundle. main. url(forResource: "movie", withExtension: "mp4")!)) } }


2 Answers

First try to disconnect internet from your router and you will get playbackBufferEmpty notification. To handle network switching you will need to implemented Reachability

like image 103
Armands.A Avatar answered Sep 27 '22 22:09

Armands.A


There are 2 cases where player can get stuck: it never starts or it runs out of buffered data. I use the following to handle both cases:

When you create a AVPlayer instance:

[_player addObserver:self forKeyPath:@"rate" options:0 context:nil];
[_player.currentItem addObserver:self forKeyPath:@"status" options:0 context:nil];

This is the handler:

-(void)observeValueForKeyPath:(NSString*)keyPath
                     ofObject:(id)object
                       change:(NSDictionary*)change
                      context:(void*)context {

    if ([keyPath isEqualToString:@"status"]) {
        if (_player.status == AVPlayerStatusFailed) {
            //Failed to start.
            //Description from the docs:
            //  Indicates that the player can no longer play AVPlayerItem instances because of an error. The error is described by
            //  the value of the player's error property.
        }
    } else if ([keyPath isEqualToString:@"rate"]) {
        if (_player.rate == 0 && //playback rate is 0
                CMTIME_COMPARE_INLINE(_player.currentItem.currentTime, >, kCMTimeZero) && //video has started
                CMTIME_COMPARE_INLINE(_player.currentItem.currentTime, <, _player.currentItem.duration) && //video hasn't reached the end
                _isPlaying) { //instance variable to track playback state
            //Video stalled. Possible connection loss or connection is too slow.
        }
    }
}

Don't forget to remove observers when you are done:

[_player.currentItem removeObserver:self forKeyPath:@"status"];
[_player removeObserver:self forKeyPath:@"rate"];

See my answer here to see how I handle stalled video: AVPlayer stops playing and doesn't resume again

like image 20
Raimundas Sakalauskas Avatar answered Sep 27 '22 21:09

Raimundas Sakalauskas