处理 AVPlayer 停顿

Posted

技术标签:

【中文标题】处理 AVPlayer 停顿【英文标题】:Handling AVPlayer stalls 【发布时间】:2013-12-26 12:02:57 【问题描述】:

我正试图捕捉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 次。但是我不知道每次播放停止时如何获取它们。 我做错了吗?

【问题讨论】:

【参考方案1】:

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

【讨论】:

可达性和播放停顿结合了两个不同的东西。【参考方案2】:

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

当你创建一个 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

【讨论】:

“_isPlaying”如何获得?

以上是关于处理 AVPlayer 停顿的主要内容,如果未能解决你的问题,请参考以下文章

如何正确处理 AVPlayer HTTP 错误?

包装 AVPlayer 行为时处理 AVPlayerLayer

关于AVplayer 缓冲问题的处理

AVPlayer 类事件

来电后AVplayer恢复

AVPlayer 播放、暂停和缓冲问题