Ios 如何处理AVPlayer.avplayerTemplateBackstalled通知
我使用的是AVPlayer,有时播放器会随机暂停。我正在观察Ios 如何处理AVPlayer.avplayerTemplateBackstalled通知,ios,swift,avplayer,nsnotificationcenter,Ios,Swift,Avplayer,Nsnotificationcenter,我使用的是AVPlayer,有时播放器会随机暂停。我正在观察\.timeControlStatus,但我得到的唯一响应是.paused。我也在观察\。我的播放方式很像Keepup,\。我的播放缓冲区是空的,和\。我的播放缓冲区是满的,但这些都不会触发。然而,使用Notification.Name.avplayerTemplayBackstalled我确实收到一条打印语句,上面写着“stalled” 即使\.rate在播放器暂停时触发,但在.avplayeritemploybackstalled触
\.timeControlStatus
,但我得到的唯一响应是.paused
。我也在观察\。我的播放方式很像Keepup
,\。我的播放缓冲区是空的
,和\。我的播放缓冲区是满的
,但这些都不会触发。然而,使用Notification.Name.avplayerTemplayBackstalled
我确实收到一条打印语句,上面写着“stalled”
即使\.rate
在播放器暂停时触发,但在.avplayeritemploybackstalled
触发之前触发,有时\.timeControlStatus.pause
在.avplayeritemploybackstalled
之后触发,播放器就坐在那里
当.avplayerTemplayBackstalled
运行且播放器暂停时,我该怎么办
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 ***
}
我找到了那个。基本上,在暂停的通知中,我检查缓冲区是否已满。如果没有,我从链接运行代码。我找到了。基本上,在暂停的通知中,我检查缓冲区是否已满。如果没有,我将从链接运行代码。@matt顺便说一句,谢谢你的建议,我将设置一个活动指示器,并且不会触摸播放器。@matt它一直在发生,问题是之后没有发生任何事情,这意味着没有其他观察者或通知被调用。视频只有15秒,大约5秒后就冻结了,我让它停了5分钟,期待着会发生什么,但是娜达。如果它试图填充缓冲区,它不应该在5分钟内被填充,然后其他方法之一被触发吗?嗯,我想我错了。我不知道为什么视频会在5秒钟后暂停,可能需要更多信息。我也不太明白为什么你要将
自动等待最小化设置为false
,这类设置有违目的。我添加了automaticallywaitstominimimizestalling=false,认为这可能会帮助它播放得更快。你说它违背目的是什么意思?我来评论一下,看看摊位是否还在occurs@matt顺便说一句,谢谢你的建议,我会挂一个活动指示器,不会碰播放器。@matt它一直在发生,问题是之后什么也没有发生,这意味着没有其他观察员或通知被呼叫。视频只有15秒,大约5秒后就冻结了,我让它停了5分钟,期待着会发生什么,但是娜达。如果它试图填充缓冲区,它不应该在5分钟内被填充,然后其他方法之一被触发吗?嗯,我想我错了。我不知道为什么视频会在5秒钟后暂停,可能需要更多信息。我也不太明白为什么你要将自动等待最小化设置为false
,这类设置有违目的。我添加了automaticallywaitstominimimizestalling=false,认为这可能会帮助它播放得更快。你说它违背目的是什么意思?我将对它进行注释,看看是否仍然出现失速