Потоковое видео HLS не воспроизводится при первой загрузке - PullRequest
0 голосов
/ 31 марта 2019

Я пытаюсь транслировать потоковую передачу в iOS, поэтому следуйте инструкциям -

  1. Инициализация проигрывателя

    player                 = AVPlayer()
    player.rate            = 1.0
    player.actionAtItemEnd = AVPlayerActionAtItemEnd.none
    
  2. Настройка слоя проигрывателя

    playerLayer                 = AVPlayerLayer(player: player)
    playerLayer.frame           = self.bounds
    playerLayer.backgroundColor = UIColor.clear.cgColor
    playerLayer.videoGravity    = AVLayerVideoGravity.resizeAspectFill
    
    if let sublayers = self.layer.sublayers {
    
        for layer in sublayers {
            layer.removeFromSuperlayer()
        }
    }
    
    self.layer.addSublayer(playerLayer)
    
  3. Настройка проигрывателя Item

    let avAsset = AVURLAsset(url: streamingUrl)
    playerItem = AVPlayerItem(asset: avAsset)
    
  4. Замена текущего элемента в проигрывателе и воспроизведение

    self.player?.replaceCurrentItem(with: self.playerItem)
    self.player?.play()
    

Мое видео воспроизводится отлично, если я загружаю плеер после начала потоковой передачи, но , если я загружаю проигрыватель до того, как я начал потоковую трансляцию из бэкэнда, а затем начинаю потоковую передачу через некоторое время, когда оно не воспроизводит видео.

Я попытался добавить наблюдателя к свойству status playerItem, но оно также не изменилось в вышеупомянутом условии, оно меняется только в том случае, если я загружаю проигрыватель после начала потоковой передачи, и все работает нормально.Итак, мой вопрос: почему я не получаю изменение статуса моего playerItem?Я что-то пропустил?Пожалуйста помоги.Заранее спасибо.

1 Ответ

0 голосов
/ 31 марта 2019

Проверьте, можно ли воспроизвести url, используя AVAsset(url: URL).isPlayable, в вашем случае, прежде чем вы сможете играть

if avAsset.isPlayable {
    playerItem = AVPlayerItem(asset: avAsset)
    ...
}

Для лучшего подхода используйте наблюдателей

class ViewController: UIViewController {

    private var observerContext = 0
    private let player = AVPlayer()
    private var readyForPlayback = false

    private var playerItem: AVPlayerItem? {
        willSet {
            playerItem?.removeObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), context: &observerContext)
        }

        didSet {
            playerItem?.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status), options: [.initial, .new], context: &observerContext)
        }
    }

    private var asset: AVAsset? {
        willSet {
            readyForPlayback = false
            asset?.removeObserver(self, forKeyPath: #keyPath(AVURLAsset.isPlayable), context: &observerContext)
        }

        didSet {
            guard asset == nil else {
                asset!.addObserver(self, forKeyPath: #keyPath(AVURLAsset.isPlayable), options: [.initial, .new], context: &observerContext)
                return
            }

            playerItem = nil
            player.replaceCurrentItem(with: nil)
        }
    }

    // MARK: KVO
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard context == &observerContext else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
            return
        }

        guard let keyPath = keyPath else { return }

        switch keyPath {
        case #keyPath(AVURLAsset.isPlayable):
            guard asset?.isPlayable == true else { return }
            playerItem = AVPlayerItem(asset: asset!)
            player.replaceCurrentItem(with: playerItem)
        case #keyPath(AVPlayerItem.status):
            guard let status = playerItem?.status else { return }

            if status == .readyToPlay {
                guard !readyForPlayback else { return }
                readyForPlayback = true
                player.play()
            } else if status == .failed {
                readyForPlayback = false
                if let error = playerItem?.error {
                    print("Error: \(error)")
                }
            }
        default:
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
}

Использование

self.asset = AVAsset

При остановке воспроизведения

self.asset = nil
...