处理AVPlayer停顿

时间:2013-12-26 12:02:58

标签: ios objective-c avplayer key-value-observing

如果没有更多可用媒体(网络速度太慢,信号丢失等)AVPlayer无法继续播放,我正试图抓住时机。正如文档和不同示例中所述,我正在使用KVO来检测这一点:

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);
}

我正在开始播放并在此之后关闭WiFi。很遗憾,“playbackBufferEmpty”和“AVPlayerItemPlaybackStalledNotification”都没有出现。在播放停止的那一刻,我只收到一个AVPlayerItemTimeJumpedNotification,而这就是全部。 但是,当我收到这些通知时,至少有2次。但我无法弄清楚每次播放停止时如何获取它们。 我做错了吗?

2 个答案:

答案 0 :(得分:2)

首先尝试断开互联网与路由器的连接,然后您将获得playbackBufferEmpty通知。 要处理网络切换,您需要实施Reachability

答案 1 :(得分:1)

有两种情况可以让玩家卡住:它永远不会启动或者用完缓冲数据。我使用以下方法来处理这两种情况:

创建AVPlayer实例时:

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

这是处理程序:

-(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.
        }
    }
}

完成后不要忘记删除观察员:

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

请在此处查看我的回答,了解我如何处理停滞不前的视频:AVPlayer stops playing and doesn't resume again