iOS - получение текущего состояния AVPlayer(Item)
Я ищу окончательный ответ, как получить текущий AVPlayer/AVPlayerItem
состояние на iOS 9 и выше. Проще говоря, пусть они будут состояниями стиля Google ExoPlayer:
простаивает (нет носителя или ошибка)
буферизация (видео на самом деле не воспроизводится / не продвигается и ожидает больше данных)
воспроизведение (видео фактически воспроизводится / продвигается)
завершено (видео закончено, воспроизведение до конца)
Обратите внимание, что на данный момент я не ищу способ отслеживания изменений состояния (посредством уведомлений, наблюдения KVO или других средств), просто состояние в текущий момент времени. Рассмотрим следующий псевдокод:
typedef enum : NSUInteger {
PlayerStateIdle,
PlayerStateBuffering,
PlayerStatePlaying,
PlayerStateCompleted
} PlayerState;
+ (PlayerState)resolvePlayerState:(AVPlayer*)player {
// Magic code here
}
Стены, до сих пор я бился головой:
timeControlStatus
доступно с iOS 10 и вышеplaybackBufferEmpty
всегда верноplaybackBufferFull
всегда ложноloadedTimeRanges
На первый взгляд может показаться многообещающим, но нет ни указания на то, сколько времени должно быть предварительно буферизовано для воспроизведения, ни гарантии того, чтоcurrentTime
быть на краю загруженного временного диапазона - стойло
1 ответ
Согласно документации
Вы можете использовать наблюдение значения ключа, чтобы наблюдать за этими изменениями состояния по мере их возникновения. Одним из наиболее важных свойств предмета игрока является его статус. Статус показывает, готов ли элемент для воспроизведения и доступен ли он для использования.
Для настройки наблюдения:
func prepareToPlay() {
let url = <#Asset URL#>
// Create asset to be played
asset = AVAsset(url: url)
let assetKeys = [
"playable",
"hasProtectedContent"
]
// Create a new AVPlayerItem with the asset and an
// array of asset keys to be automatically loaded
playerItem = AVPlayerItem(asset: asset,
automaticallyLoadedAssetKeys: assetKeys)
// Register as an observer of the player item's status property
playerItem.addObserver(self,
forKeyPath: #keyPath(AVPlayerItem.status),
options: [.old, .new],
context: &playerItemContext)
// Associate the player item with the player
player = AVPlayer(playerItem: playerItem)
}
Обрабатывать:
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
// Only handle observations for the playerItemContext
guard context == &playerItemContext else {
super.observeValue(forKeyPath: keyPath,
of: object,
change: change,
context: context)
return
}
if keyPath == #keyPath(AVPlayerItem.status) {
let status: AVPlayerItemStatus
// Get the status change from the change dictionary
if let statusNumber = change?[.newKey] as? NSNumber {
status = AVPlayerItemStatus(rawValue: statusNumber.intValue)!
} else {
status = .unknown
}
// Switch over the status
switch status {
case .readyToPlay:
// Player item is ready to play.
case .failed:
// Player item failed. See error.
case .unknown:
// Player item is not yet ready.
}
}
}
Не уверен, в чем твоя проблема.
Вы можете просто получить доступ к player.status или player.timeControlStatus и вернуть результат, соответствующий вашему ENUM
Это то, что вы имели ввиду?