如何处理AVPlayer .AVPlayerItemPlaybackStalled通知 [英] How to handle AVPlayer .AVPlayerItemPlaybackStalled Notification

查看:144
本文介绍了如何处理AVPlayer .AVPlayerItemPlaybackStalled通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用AVPlayer,有时播放器会随机暂停.我正在观察\.timeControlStatus,但得到的唯一响应是.paused.我还观察到\.isPlaybackLikelyToKeepUp\.isPlaybackBufferEmpty\.isPlaybackBufferFull,但这些都不会触发.但是,使用Notification.Name.AVPlayerItemPlaybackStalled时,我确实得到了一条打印文字,上面写着"stalled".

I'm using AVPlayer and sometimes the player randomly pauses. I'm observing \.timeControlStatus but the only response I get .paused. I'm also observing \.isPlaybackLikelyToKeepUp, \.isPlaybackBufferEmpty, and \.isPlaybackBufferFull but nothing fires for those. However using Notification.Name.AVPlayerItemPlaybackStalled I do get a print statement that says "stalled".

即使\.rate在玩家暂停时触发,也要在.AVPlayerItemPlaybackStalled触发前触发,有时\.timeControlStatus .paused.AVPlayerItemPlaybackStalled之后触发,而玩家只是坐在那里.

Even though \.rate fires when the the player pauses, that fires before .AVPlayerItemPlaybackStalled fires, sometimes \.timeControlStatus .paused fires after .AVPlayerItemPlaybackStalled and the player just sits there.

.AVPlayerItemPlaybackStalled运行并且播放器坐在暂停状态后该怎么办?

What should I do once .AVPlayerItemPlaybackStalled runs and the player is sitting paused?

NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemPlaybackStalled(_:)),
                                               name: NSNotification.Name.AVPlayerItemPlaybackStalled,
                                               object: playerItem)

@objc fileprivate func playerItemPlaybackStalled(_ notification: Notification) {
    print("playerItemPlaybackStalled")
}

这是我的完整代码:

let player = AVPlayer()
player.automaticallyWaitsToMinimizeStalling = false
playerLayer = AVPlayerLayer(player: player)
playerLayer?.videoGravity = AVLayerVideoGravity.resizeAspect
// add KVO observers and NotificationCenter observers
// playerItem keys are already loaded
playerItem.preferredForwardBufferDuration = TimeInterval(1.0)
player.replaceCurrentItem(with: playerItem)


playerStatusObserver = player?.observe(\.currentItem?.status, options: [.new, .old]) { [weak self] (player, change) in
        
    switch (player.status) {
    case .readyToPlay:
        DispatchQueue.main.async {
            // play video
        }
    case .failed, .unknown:
        print("Video Failed to Play")
    @unknown default:
        break
    }
}
    
playerRateObserver = player?.observe(\.rate, options:  [.new, .old], changeHandler: { [weak self](player, change) in

    if player.rate == 1  {
        DispatchQueue.main.async {
            // if player isn't playing play it
        }
    } else {
        DispatchQueue.main.async {
           // is player is playing pause it
        }
    }
})
    
playerTimeControlStatusObserver = player?.observe(\.timeControlStatus, options: [.new, .old]) { [weak self](player, change) in
        
    switch (player.timeControlStatus) {
    case .playing:
            DispatchQueue.main.async { [weak self] in
                // if player isn't playing pay it
            }
    case .paused:
            print("timeControlStatus is paused") // *** SOMETIMES PRINTS after .AVPlayerItemPlaybackStalled runs***

    case .waitingToPlayAtSpecifiedRate:
            print("timeControlStatus- .waitingToPlayAtSpecifiedRate")

    if let reason = player.reasonForWaitingToPlay {
                
            switch reason {
            case .evaluatingBufferingRate:
                    print("timeControlStatus- .evaluatingBufferingRate") // never prints
                    
            case .toMinimizeStalls:
                    print("timeControlStatus- .toMinimizeStalls") // never prints
                    
            case .noItemToPlay:
                    print("timeControlStatus- .noItemToPlay") // never prints
                    
            default:
                    print("Unknown \(reason)")
            }
        }
    @unknown default:
        break
    }
}
    
playbackLikelyToKeepUpObserver = player?.currentItem?.observe(\.isPlaybackLikelyToKeepUp, options: [.old, .new]) {  (playerItem, change) in
    print("isPlaybackLikelyToKeepUp") // never prints
}
    
playbackBufferEmptyObserver = player?.currentItem?.observe(\.isPlaybackBufferEmpty, options: [.old, .new]) { (playerItem, change) in
    print("isPlaybackBufferEmpty") // never prints
}
    
playbackBufferFullObserver = player?.currentItem?.observe(\.isPlaybackBufferFull, options: [.old, .new]) { (playerItem, change) in
    print("isPlaybackBufferFull") // never prints
}
    
NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemDidReachEnd(_:)),
                                               name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                               object: playerItem)

NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemFailedToPlayToEndTime(_:)),
                                           name: .AVPlayerItemFailedToPlayToEndTime,
                                           object: playerItem)
    
    
NotificationCenter.default.addObserver(self, selector: #selector(playerItemNewError(_:)),
                                           name: .AVPlayerItemNewErrorLogEntry,
                                           object: playerItem)

NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemPlaybackStalled(_:)),
                                           name: NSNotification.Name.AVPlayerItemPlaybackStalled,
                                           object: playerItem)

@objc func playerItemDidReachEnd(_ notification: Notification) {
    // show replay button
}

@objc func playerItemFailedToPlayToEndTime(_ notification: Notification) {
    print("playerItemFailedToPlayToEndTime") // never prints

    if let error = notification.userInfo?["AVPlayerItemFailedToPlayToEndTime"] as? Error {
        print(error.localizedDescription) // never prints
    }
}

@objc func playerItemNewError(_ notification: Notification) {
    print("playerItemNewErrorLogEntry") // never prints
}

@objc func playerItemPlaybackStalled(_ notification: Notification) {
    print("playerItemPlaybackStalled") // *** PRINTS ***
}

推荐答案

我在此处找到了答案.基本上在停滞的通知中,我检查缓冲区是否已满.如果没有,我从链接中运行代码.

I found the answer here. Basically inside the stalled notification I check to see if the buffer is full or not. If not I run the code from the link.

这篇关于如何处理AVPlayer .AVPlayerItemPlaybackStalled通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆