Detect if AVPlayerViewController is playing video

2019-06-26 01:04发布

问题:

  1. I have to detect whether the video is in playing or buffering mode.I am loading the video from a URL. I have tried the below code and I am able to track after once the video has started playing, but not when it is in buffering state.
  2. Also, I want to add an overlay view in my player. I have tried to add the overlay in AVPlayer but when in full screen mode the overlay disappears.

Need some suggestions. Thanks in advance. Below is my code:

    let playerAV = AVPlayerViewController()
    var player = AVPlayer()
    player = AVPlayer(URL: url)
    print(url)
    playerAV.player = player
    playerAV.view.frame = CGRectMake(0, 0,  self.videoView.frame.width,  self.videoView.frame.height)
    self.addChildViewController(playerAV)
    self.videoView.addSubview(playerAV.view)
    playerAV.didMoveToParentViewController(self)
    playerAV.player?.play()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ChannelDetailViewController.notificationObserver(_:)), name:AVPlayerItemDidPlayToEndTimeNotification , object: player.currentItem)
        _ = UIDevice.beginGeneratingDeviceOrientationNotifications
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ChannelDetailViewController.deviceOrientationDidChange(_:)) , name:
        UIDeviceOrientationDidChangeNotification, object: nil)
    player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.New, context: nil)
  player.addPeriodicTimeObserverForInterval(CMTime(value: 1, timescale: 3), queue: dispatch_get_main_queue()) { [weak self] time in
    self?.handlePlayerStatus(time)
  }

  func handlePlayerStatus(time: CMTime) {
     if player.status == .ReadyToPlay {
     // buffering is finished, the player is ready to play
     print("playing")
  }
  if player.status == .Unknown{
    print("Buffering")
  }
 }

 override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if keyPath == "rate" {
        if let rate = change?[NSKeyValueChangeNewKey] as? Float {
          if player.currentItem!.status == AVPlayerItemStatus.ReadyToPlay{
            if rate != 0 && player.error == nil {

              print("normal playback")
            }
            else{
              print("playback stopped")
            }

          }else if player.currentItem?.status == AVPlayerItemStatus.Unknown{
            print("test")
          }
        }
    }
    print("you are here")
}

check here for project

回答1:

  1. Check my answer: https://stackoverflow.com/a/38867386/5109911, this shows you how check if the player is loading the buffer, to check if it is ready to play you have to check both player.currentItem.status and player.status

  2. To add an overlay to AVPlayer I suggest using an UIView above your AVPlayer layer.



回答2:

I took a slightly different approach to a similar problem - updating the UI when the AVPlayer starts actual playback (in our case, it was audio playback, but the same principle would apply).

We used a boundary time to execute a block at the start of playback – specifically after 1/3 of a second of playback – to update the UI at the same time as audible playback:

let times = [NSValue(time:CMTimeMake(1,3))]
_ = self.player.addBoundaryTimeObserver(forTimes: times, queue: DispatchQueue.main, using: {
    [weak self] time in
    // Code to update the UI goes here, e.g.
    self?.someUIView.isHidden = false
})

I have a little more detail on the approach (and a sample Xcode project) on our company blog: http://www.artermobilize.com/blog/2017/02/09/detect-when-ios-avplayer-finishes-buffering-using-swift/

As to question #2, I concur with Marco's suggestion of using an UIView overtop of the AVPlayer layer.