15

当使用 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 并重新开始播放?

4

3 回答 3

13

为了处理网络更改,您必须为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 ...
}
于 2014-04-10T14:56:55.400 回答
5

您应该为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];
    }
}

进一步阅读有关automaticWaitsToMinimizeStalling 的讨论

于 2018-09-07T08:49:09.510 回答
1

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

}
于 2017-04-19T12:29:26.290 回答