AVPlayer : 如何处理网络中断

Posted

技术标签:

【中文标题】AVPlayer : 如何处理网络中断【英文标题】:AVPlayer : How to handle network interruptions 【发布时间】:2013-10-17 22:01:21 【问题描述】:

当使用 AVPlayer 从一个 url 播放音频时,它会 例如断开 wifi 时停止播放。

[player play];

不恢复 AVPlayer

player.rate // Value is 1.0

player.currentItem.isPlaybackLikelyToKeepUp // Value is YES

player.status // Value is AVPlayerStatusReadyToPlay

player.error // Value is nil

但是播放器没有播放任何音频。

如何处理与 AVPlayer 的断开连接,以重新连接 AVPlayer 然后重新开始玩?

【问题讨论】:

不确定何时仅播放音频,但对于视频,请按照其他答案中的建议收听 AVPlayerItemFailedToPlayToEndTimeNotification。此外,对于 HLS 直播视频流,我们似乎需要重新创建 AVPlayerItem 并将其设置为 AVPlayer。只是打电话给play(),做寻找等似乎对我们不起作用。现在正在寻找更好的解决方案,但这是我目前所知道的最好的解决方案。此外,如果 avplayeritem 的 .status 失败,我们还需要重新创建它(我的假设)。 【参考方案1】:

为了处理网络变化,你必须为AVPlayerItemFailedToPlayToEndTimeNotification添加一个观察者。

- (void) playURL:(NSURL *)url

    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemFailedToPlayToEndTime:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
    self.player = [AVPlayer playerWithPlayerItem:playerItem];
    [self.player play];


- (void) playerItemFailedToPlayToEndTime:(NSNotification *)notification

    NSError *error = notification.userInfo[AVPlayerItemFailedToPlayToEndTimeErrorKey];
    // Handle error ...

【讨论】:

【参考方案2】:

您应该为AVPlayerItemPlaybackStalledNotification 添加观察者。

AVPlayerItemFailedToPlayToEndTimeNotification 在这个问题上对我没有任何价值。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackStalled:) name:AVPlayerItemPlaybackStalledNotification object:trackItem];

正如文档所述,如果必要的流媒体未通过网络及时传送,则基于文件的播放将不会继续。

通知的对象是其播放的 AVPlayerItem 实例 无法继续,因为没有必要的流媒体 通过网络及时交付。流媒体播放 一旦交付了足够数量的数据,媒体就会继续。 基于文件的播放不会继续。

这解释了为什么 AVPlayer 可以在网络切换后恢复 HLS 流,但如果我使用 AVPlayer 播放基于文件的 TuneIn 资源则不能这样做。

那么答案就变得简单了。

- (void)playbackStalled:(NSNotification *)notification 
    if ([self isFileBased:streamUri]) 
        // Restart playback
        NSURL *url = [NSURL URLWithString:streamUri];
        AVPlayerItem *trackItem = [AVPlayerItem playerItemWithURL:url];
        AVPlayer *mediaPlayer = [AVPlayer playerWithPlayerItem:trackItem];
        [self registerObservers:trackItem player:mediaPlayer];
        [mediaPlayer play];
    

进一步阅读discussion of automaticallyWaitsToMinimizeStalling。

【讨论】:

【参考方案3】:

0xced 对 Swift 3/4 的回答:

var playerItem: AVPlayerItem?
var player: AVPlayer?

func instantiatePlayer(_ url: URL) 
    self.playerItem = AVPlayerItem(url: url)            
    self.player = AVPlayer(playerItem: self.playerItem)
        NotificationCenter.default.addObserver(self, selector: #selector(playerItemFailedToPlay(_:)), name: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime, object: nil)


func playerItemFailedToPlay(_ notification: Notification) 
    let error = notification.userInfo?[AVPlayerItemFailedToPlayToEndTimeErrorKey] as? Error


【讨论】:

以上是关于AVPlayer : 如何处理网络中断的主要内容,如果未能解决你的问题,请参考以下文章

如何正确处理 AVPlayer HTTP 错误?

来电后AVplayer恢复

AVPlayer 播放错误的视频文件

在像 instagram 这样的 tableview 中使用多个 AVPlayer

如何处理网络中断和连接池

如何获取 AVPlayer 的中断开始/结束事件