Ios AVPlayer和AVPlayerItem状态何时更改?
我正在使用AVFoundation开发一个音乐播放器插件,我想在iOS和Android上创建一个统一的界面 我想捕获Ios AVPlayer和AVPlayerItem状态何时更改?,ios,swift,xcode,avfoundation,avplayer,reasonforwaitingtoplay,Ios,Swift,Xcode,Avfoundation,Avplayer,Reasonforwaitingtoplay,我正在使用AVFoundation开发一个音乐播放器插件,我想在iOS和Android上创建一个统一的界面 我想捕获AVPlayer可能引发的错误,例如,当给定的AVPlayerItem无效时(包含不受支持的文件的URL,如png文件) 我希望AVPlayer.replace()在AVPlayerItem或AVPlayer的状态中引发异常或更改,或者至少在NSNotificationCeter上引发一些相关通知。我试着听/观察他们,但没有一个人报告任何错误。事实上,AVPlayer报告了“准备播
AVPlayer
可能引发的错误,例如,当给定的AVPlayerItem
无效时(包含不受支持的文件的URL
,如png
文件)
我希望AVPlayer.replace()
在AVPlayerItem
或AVPlayer
的状态中引发异常或更改,或者至少在NSNotificationCeter
上引发一些相关通知。我试着听/观察他们,但没有一个人报告任何错误。事实上,AVPlayer
报告了“准备播放”状态
我是一名android开发人员,无法理解AVPlayer
的工作原理。我怎样才能做到这一点
注意:我不能使用AVAudioPlayer
,因为文档说明在播放来自网络或可能有延迟的源的音乐时不应使用它
self.mediaPlayer?.replaceCurrentItem(with: nil)
self.mediaPlayer?.play()
即使此代码不会生成错误您也可以借助AVplayer的属性跟踪播放器的状态 当timeControlStatus的值为AVPlayerItemControlStatusWaitingToplayatsSpecifiedRate时,此属性描述播放机当前等待的原因。否则是零。 您可以使用reasonForWaitingToPlay的值有条件地显示指示播放器等待状态的UI。 此属性是可观察的关键值。 可能的值为AVPLAYERWAITING WITH NOITEM TO LAYREASON、AVPLAYERWAITING WHILEING BUFFERINGREASON和AVPLAYERWAITINGTOMINIMIZESTALLS ASON
如果此属性的值为零,则表示当前播放器正在播放某些内容。这与AVPlayer无关。如果媒体播放器本身为零,
self.mediaPlayer?.play()。代码行刚刚中止。那么它怎么可能产生错误呢?Swift不是这样工作的。您可以观察avplayer@matt该问题已被编辑。
private func addObserverPlayerItem()
{
if let playerItem = self.player?.currentItem{
playerItem.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "playbackBufferFull", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "loadedTimeRanges", options: [.new], context: nil)
self.player?.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem.status), options: [.new, .initial], context: nil)
self.player?.addObserver(self, forKeyPath: #keyPath(AVPlayer.status), options: [.new, .initial], context: nil)
}
}
override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if object is AVPlayerItem {
switch keyPath {
case "loadedTimeRanges":
let duration = self.currentItem?.totalBuffer() ?? 0
let totalduration = currentItem?.asset.duration
self.videoControll?.slider.bufferEndValue = totalduration?.seconds ?? 0
self.videoControll?.slider.bufferStartValue = (duration) / (totalduration?.seconds ?? 1)
print((duration) / (totalduration?.seconds ?? 1))
case "playbackBufferEmpty":
// Show loader
self.activityIndicator?.startAnimating()
case "playbackLikelyToKeepUp":
// Hide loader
self.activityIndicator?.stopAnimating()
case "playbackBufferFull":
// Hide loader
self.activityIndicator?.stopAnimating()
case #keyPath(AVPlayer.currentItem.status):
let newStatus: AVPlayerItem.Status
if let newStatusAsNumber = change?[NSKeyValueChangeKey.newKey] as? NSNumber {
newStatus = AVPlayerItem.Status(rawValue: newStatusAsNumber.intValue)!
} else {
newStatus = .unknown
}
if newStatus == .failed {
NSLog("SA Detected Error: \(String(describing: self.player?.currentItem?.error?.localizedDescription)), error: \(String(describing: self.player?.currentItem?.error))")
}
case #keyPath(AVPlayer.status):
print()
case .none:
self.activityIndicator?.stopAnimating()
case .some(_):
self.activityIndicator?.stopAnimating()
}
}
}
private func addObserverPlayerItem()
{
if let playerItem = self.player?.currentItem{
playerItem.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "playbackBufferFull", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "loadedTimeRanges", options: [.new], context: nil)
self.player?.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem.status), options: [.new, .initial], context: nil)
self.player?.addObserver(self, forKeyPath: #keyPath(AVPlayer.status), options: [.new, .initial], context: nil)
}
}
override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if object is AVPlayerItem {
switch keyPath {
case "loadedTimeRanges":
let duration = self.currentItem?.totalBuffer() ?? 0
let totalduration = currentItem?.asset.duration
self.videoControll?.slider.bufferEndValue = totalduration?.seconds ?? 0
self.videoControll?.slider.bufferStartValue = (duration) / (totalduration?.seconds ?? 1)
print((duration) / (totalduration?.seconds ?? 1))
case "playbackBufferEmpty":
// Show loader
self.activityIndicator?.startAnimating()
case "playbackLikelyToKeepUp":
// Hide loader
self.activityIndicator?.stopAnimating()
case "playbackBufferFull":
// Hide loader
self.activityIndicator?.stopAnimating()
case #keyPath(AVPlayer.currentItem.status):
let newStatus: AVPlayerItem.Status
if let newStatusAsNumber = change?[NSKeyValueChangeKey.newKey] as? NSNumber {
newStatus = AVPlayerItem.Status(rawValue: newStatusAsNumber.intValue)!
} else {
newStatus = .unknown
}
if newStatus == .failed {
NSLog("SA Detected Error: \(String(describing: self.player?.currentItem?.error?.localizedDescription)), error: \(String(describing: self.player?.currentItem?.error))")
}
case #keyPath(AVPlayer.status):
print()
case .none:
self.activityIndicator?.stopAnimating()
case .some(_):
self.activityIndicator?.stopAnimating()
}
}
}