How to detect AVPlayer actually started to play in swift

故事扮演 提交于 2019-11-29 09:08:38

Since iOS 10 you can observe timeControlStatus property of AVPlayer. It can be .playing.

Check the code:

private func setupAVPlayer() {
    avPlayer.addObserver(self, forKeyPath: "status", options: [.old, .new], context: nil)
    if #available(iOS 10.0, *) {
        avPlayer.addObserver(self, forKeyPath: "timeControlStatus", options: [.old, .new], context: nil)
    } else {
        avPlayer.addObserver(self, forKeyPath: "rate", options: [.old, .new], context: nil)
    }
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if object as AnyObject? === avPlayer {
        if keyPath == "status" {
            if avPlayer.status == .readyToPlay {
                avPlayer.play()
            }
        } else if keyPath == "timeControlStatus" {
            if #available(iOS 10.0, *) {
                if avPlayer.timeControlStatus == .playing {
                    videoCell?.muteButton.isHidden = false
                } else {
                    videoCell?.muteButton.isHidden = true
                }
            }
        } else if keyPath == "rate" {
            if avPlayer.rate > 0 {
                videoCell?.muteButton.isHidden = false
            } else {
                videoCell?.muteButton.isHidden = true
            }
        }
    }
}
Rajat

You can add an observer on the object of your AVPlayer like this

player.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.new, context: nil)

and you can check the status change with your AVPlayer like this

 func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutableRawPointer) {
    if keyPath == "status" {
        print(player.status)
    }
}

Here is what I did to actually know when video started (not when it's only ready to start).

Swift 4

player = AVPlayer(url: URL(fileURLWithPath: path))
player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil)

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "rate" {
        if player.rate > 0 {
            print("video started")
        }
    }
}

From Apple's docs: You can observe an AVPlayerLayer object’s readyForDisplay property to be notified when the layer has user-visible content. In particular, you might insert the player layer into the layer tree only when there is something for the user to look at and then perform a transition from

Declare AVPlayer Global

var streamPlayer = AVPlayer()

func playStreamAudio( for audioUrl:String)
    {
        guard streamPlayer.timeControlStatus != .playing else {
            streamPlayer.pause()
            return
        }
        let url = audioUrl //"http://192.168.71.11:7891/rec.wav"
        let playerItem = AVPlayerItem(url: URL(string:url)!)
        streamPlayer = AVPlayer(playerItem:playerItem)
        streamPlayer.rate = 1.0;
        streamPlayer.volume = 1.0
        streamPlayer.play()
    }
layerObserver = newLayer.observe(\AVPlayerLayer.isReadyForDisplay, options: .new) { [weak self] _, change in
    if change.newValue == true {
        self?.viewModel?.videoLayerReadyToDisplay()
    }
}

When the app receive this event it means you can hide thumbnail(for example) and start displaying video.

Another, simpler, approach is something like:

if videoPlayer.rate != 0 && videoPlayer.error == nil {
            print("video player is playing.................")
        } else {
            print("video player is NOT playing.")
        } 

Where videoPlayer is of type AVPlayer, obviously.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!