web-dev-qa-db-fra.com

Comment puis-je vérifier si mon AVPlayer est en tampon?

Je veux détecter si mon AVPlayer est en tampon pour l'emplacement actuel, afin de pouvoir afficher un chargeur ou quelque chose du genre. Mais je n'arrive pas à trouver quoi que ce soit dans la documentation d'AVPlayer.

16
vrwim

Vous pouvez observer les valeurs de votre 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)

puis

override public func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if object is AVPlayerItem {
        switch keyPath {
            case "playbackBufferEmpty":
               // Show loader

            case "playbackLikelyToKeepUp":
                // Hide loader

            case "playbackBufferFull":
                // Hide loader
        }
    }
}
32
Marco Santarossa

La réponse acceptée ne fonctionnait pas pour moi, j'ai utilisé le code ci-dessous pour montrer efficacement le chargeur. 

Swift 3

//properties 
var observer:Any!
var player:AVPlayer!


self.observer = self.player.addPeriodicTimeObserver(forInterval: CMTimeMake(1, 600), queue: DispatchQueue.main) {
    [weak self] time in

    if self?.player.currentItem?.status == AVPlayerItemStatus.readyToPlay {

        if let isPlaybackLikelyToKeepUp = self?.player.currentItem?.isPlaybackLikelyToKeepUp {
            //do what ever you want with isPlaybackLikelyToKeepUp value, for example, show or hide a activity indicator.
        }
    }
}
14
aytek

4 observations rapides:

var playerItem: AVPlayerItem?
var playbackLikelyToKeepUpKeyPathObserver: NSKeyValueObservation?
var playbackBufferEmptyObserver: NSKeyValueObservation?
var playbackBufferFullObserver: NSKeyValueObservation?

private func observeBuffering() {
    let playbackBufferEmptyKeyPath = \AVPlayerItem.playbackBufferEmpty
    playbackBufferEmptyObserver = playerItem?.observe(playbackBufferEmptyKeyPath, options: [.new]) { [weak self] (_, _) in
        // show buffering
    }

    let playbackLikelyToKeepUpKeyPath = \AVPlayerItem.playbackLikelyToKeepUp
    playbackLikelyToKeepUpKeyPathObserver = playerItem?.observe(playbackLikelyToKeepUpKeyPath, options: [.new]) { [weak self] (_, _) in
        // hide buffering
    }

    let playbackBufferFullKeyPath = \AVPlayerItem.playbackBufferFull
    playbackBufferFullObserver = playerItem?.observe(playbackBufferFullKeyPath, options: [.new]) { [weak self] (_, _) in
        // hide buffering
    }
}

Les observateurs doivent être retirés une fois que nous avons fini d’observer.

Pour supprimer ces trois observateurs, il suffit de placer playbackBufferEmptyObserver, playbackLikelyToKeepUpKeyPathObserver et playbackBufferFullObserver à nil.

Pas besoin de les supprimer manuellement (cela est spécifique à la méthode observe<Value>(_ keyPath:, options:, changeHandler:).

4
Roman Barzyczak

#Actualisé dans Swift 4 et a bien fonctionné

Comme je suis allé avec accepté réponse mais ne fonctionnait pas dans Swift 4 pour moi, donc après certaines recherches, j'ai trouvé cela pense de Apple doc . Il existe deux manières de déterminer les états AVPlayer qui sont,

  1. addPeriodicTimeObserverForInterval: file d'attente: usingBlock: et 
  2. addBoundaryTimeObserverForTimes: file d'attente: usingBlock:

et en utilisant des moyens est comme ça

var observer:Any?
var avplayer : AVPlayer?

func preriodicTimeObsever(){

        if let observer = self.observer{
            //removing time obse
            avplayer?.removeTimeObserver(observer)
            observer = nil
        }

        let intervel : CMTime = CMTimeMake(1, 10)
        observer = avplayer?.addPeriodicTimeObserver(forInterval: intervel, queue: DispatchQueue.main) { [weak self] time in

            guard let `self` = self else { return }

            let sliderValue : Float64 = CMTimeGetSeconds(time)
           //this is the slider value update if you are using UISlider.

            let playbackLikelyToKeepUp = self.avPlayer?.currentItem?.isPlaybackLikelyToKeepUp
            if playbackLikelyToKeepUp == false{

               //Here start the activity indicator inorder to show buffering
            }else{
                //stop the activity indicator 
            }
        }
    }

Et n'oubliez pas de tuer l'observateur du temps pour sauver de la fuite de mémoire. méthode pour tuer instance, ajoutez cette méthode en fonction de vos besoins mais je l’ai utilisée dans la méthode viewWillDisappear. 

       if let observer = self.observer{

            self.avPlayer?.removeTimeObserver(observer)
            observer = nil
        }
3
Amrit Tiwari

Mise à jour pour Swift 4.2

    var player : AVPlayer? = nil

    let videoUrl = URL(string: "https://wolverine.raywenderlich.com/content/ios/tutorials/video_streaming/foxVillage.mp4")
    self.player = AVPlayer(url: videoUrl!)
    self.player?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 600), queue: DispatchQueue.main, using: { time in

        if self.player?.currentItem?.status == AVPlayerItem.Status.readyToPlay {

            if let isPlaybackLikelyToKeepUp = self.player?.currentItem?.isPlaybackLikelyToKeepUp {
                //do what ever you want with isPlaybackLikelyToKeepUp value, for example, show or hide a activity indicator.

                //MBProgressHUD.hide(for: self.view, animated: true)
            }
        }
    })
1
xuzepei