(注意:我正在运行iOS 9并正在进行HTTP直播)
我有一个AVPlayer
,想要在玩家缓冲时显示加载指示符。当玩家开始使用慢速连接时,KVO会调用这些属性:
isPlaybackBufferEmpty
isPlaybackLikelyToKeepUp
isPlaybackBufferFull
问题是,当缓冲完成后,这些相同的属性不再被调用(当我说完成时我的意思是视频可以再次播放。)我的目标是在正确的时间隐藏加载指示器但是这些不要再打电话了。
我在网上搜索了这个雷达:http://www.openradar.me/25931165 不确定它是否与100%相关
有什么想法吗?
// MARK: - Key-Value Observing Method
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == #keyPath(AVPlayerItem.status) {
switch playerItem.status {
case .unknown:
break
case .readyToPlay:
player.play()
case .failed:
postPlaybackDidFailWithErrorNotification(error: error)
}
}
else if keyPath == #keyPath(AVPlayer.currentItem.isPlaybackBufferEmpty) {
guard let currentItem = player.currentItem else {
return
}
if currentItem.isPlaybackBufferEmpty {
print("isPlaybackBufferEmpty = YES")
} else {
print("isPlaybackBufferEmpty = NO")
}
}
else if keyPath == #keyPath(AVPlayer.currentItem.isPlaybackLikelyToKeepUp) {
guard let currentItem = player.currentItem else {
return
}
if currentItem.isPlaybackLikelyToKeepUp {
print("isPlaybackLikelyToKeepUp = YES")
//player.play()
} else {
print("isPlaybackLikelyToKeepUp = NO")
}
}
else if keyPath == #keyPath(AVPlayer.currentItem.isPlaybackBufferFull) {
guard let currentItem = player.currentItem else {
return
}
if currentItem.isPlaybackBufferFull {
print("isPlaybackBufferFull = YES")
//player.play()
} else {
print("isPlaybackBufferFull = NO")
}
}
else if keyPath == #keyPath(AVPlayer.currentItem) {
// Cleanup if needed.
if player.currentItem == nil {
video = nil
playerItem = nil
}
}
else if keyPath == #keyPath(AVPlayer.rate) {
updateMetadata()
NotificationCenter.default.post(name: AssetPlaybackManager.NotificationName.playerRateDidChangeNotification, object: nil)
}
else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
答案 0 :(得分:1)
您可以使用timeControlStatus,但仅在iOS 10以上版本可用。
根据Apple的官方文档
一种状态,指示当前是否正在播放, 无限期暂停,或在等待适当时暂停 网络条件
将此观察者添加到播放器中。
player.addObserver(self, forKeyPath: “timeControlStatus”, options: [.old, .new], context: nil)
然后,观察其中的变化
func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
方法。在上述方法中使用以下代码
override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "timeControlStatus", let change = change, let newValue = change[NSKeyValueChangeKey.newKey] as? Int, let oldValue = change[NSKeyValueChangeKey.oldKey] as? Int {
let oldStatus = AVPlayer.TimeControlStatus(rawValue: oldValue)
let newStatus = AVPlayer.TimeControlStatus(rawValue: newValue)
if newStatus != oldStatus {
DispatchQueue.main.async {[weak self] in
if newStatus == .playing || newStatus == .paused {
self?.loaderView.isHidden = true
} else {
self?.loaderView.isHidden = false
}
}
}
}
}
这已在上面的iOS 11上使用swift 4进行了测试,并且可以正常工作。
答案 1 :(得分:0)
使用以下功能来设置进度以及AVPlayer的缓冲状态:
func addObserver() {
let intervel : CMTime = CMTimeMake(value: 10, timescale: 10)
observer = player?.addPeriodicTimeObserver(forInterval: intervel, queue: DispatchQueue.main) { [weak self] time in
guard let `self` = self,
let playerItem = self.player?.currentItem else { return }
let currentTime : Float64 = CMTimeGetSeconds(time)
let totalDuration = CMTimeGetSeconds(playerItem.asset.duration)
//this is the slider value update if you are using UISlider.
let sliderValue = (currentTime/totalDuration)
if currentTime >= totalDuration {
if let observer = self.observer{
//removing time observer
self.player?.removeTimeObserver(observer)
self.observer = nil
}
}
let playbackLikelyToKeepUp = self.player?.currentItem?.isPlaybackLikelyToKeepUp
if playbackLikelyToKeepUp == false{
print(self.player?.rate)
print("IsBuffering")
self.lock()
} else {
//stop the activity indicator
print("Buffering completed")
self.unlock()
}
}
}