Когда меняется статус AVPlayer и AVPlayerItem? - PullRequest
2 голосов
/ 18 мая 2019

Я работаю над плагином музыкального плеера, используя AVFoundation, и хочу создать единый интерфейс на iOS и Android.

Я хочу зафиксировать ошибки, которые могут выдаваться AVPlayer, когда, например, указанный AVPlayerItem недействителен (содержит URL файла, который не поддерживается, например, png файл),

Я бы ожидал, что AVPlayer.replace() сгенерирует исключение или изменение статуса AVPlayerItem или AVPlayer или, по крайней мере, какое-нибудь соответствующее уведомление на NSNotificationCeter.Я пытался слушать / наблюдать за всеми из них, но ни один из них не сообщил ни о какой ошибке.На самом деле, AVPlayer сообщил о состоянии готовности к игре.

    mediaPlayer = AVPlayer();
    playerItem = AVPlayerItem(url: URL(fileURLWithPath: Bundle.main.path(forResource: "image", ofType: "png")!))

    playerItem?.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.old, .new], context: &playerItemContext)
    mediaPlayer?.addObserver(self, forKeyPath: #keyPath(AVPlayer.status), options: [.old, .new], context: &mediaPlayerContext)

    mediaPlayer?.replaceCurrentItem(with: playerItem); // this changes player status to - "ready-to-play"
    mediaPlayer?.play() // this does not report anything

Я разработчик Android и не могу понять, как работает AVPlayer.Как мне этого добиться?

Примечание: я не могу использовать AVAudioPlayer, потому что в документации сказано, что его не следует использовать при воспроизведении музыки из сети или источников, которые могут иметь задержку.

self.mediaPlayer?.replaceCurrentItem(with: nil)
self.mediaPlayer?.play()

Даже этот код не генерирует ошибку

Ответы [ 2 ]

0 голосов
/ 29 мая 2019
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()
            }
        }
    }
0 голосов
/ 18 мая 2019

Вы можете отслеживать статус игрока с помощью свойства AVplayer.

Когда значение timeControlStatus равно AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate, это свойство описывает, почему проигрыватель в данный момент ожидает. В противном случае это ноль. Вы можете использовать значение reasonForWaitingToPlay для отображения пользовательского интерфейса, условно отображающего состояние ожидания игрока. Это свойство является ключевым значением наблюдаемым. Возможные значения: AVPlayerWaitingWithNoItemToPlayReason, AVPlayerWaitingWhileEvaluatingBufferingRateReason и AVPlayerWaitingToMinimizeStallsReason.

Если значение этого свойства равно нулю, это означает, что в данный момент игрок что-то играет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...