简体   繁体   中英

How to tell when AVPlayer has been played for three seconds Swift

I have an application that contains videos that play automatically in an UIImageView in a UITableView when the cell is visible, and all I am trying to do is allow the application to know when the video has been played for three seconds. I wrote this code.

    class PostCell: UITableViewCell {

    var player: AVPlayer?
    var playerLayer: AVPlayerLayer?

    var post: Post? {
    didSet {
        updateView()
    }
}

    func updateView() {

    self.viewcount()

    if let videoUrlString = post?.videoUrl, let videoUrl = URL(string: videoUrlString) {
        player = AVPlayer(url: videoUrl)
        playerLayer = AVPlayerLayer(player: player)
        playerLayer?.frame = postImageView.frame
        playerLayer?.frame.size.width = postImageView.frame.size.width
        playerLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
        self.contentView.layer.addSublayer(playerLayer!)

        player?.play()
    }
      func viewcount() {
    if let currentitem = player?.currentItem {
        if currentitem.currentTime() == CMTimeMake(3, 1) {
            print ("VIDEO PLAYED FOR THREE SECONDS")
        }
      }
   }
}

but it is not printing out my message once the video starts playing. I have searched the web for help but couldn't find anything on this subject. So could anyone please help with my issue and tell me what I am doing wrong ?

Try calling the view count after player had started playing

func updateView() {

    /// Not here Because at this time player current item is not initiated yet
    /// if you use Breakpoints in viewCount code you will see it won't enter
    /// in if condition created
    self.viewcount() /// Comment this line
    if let videoUrlString = post?.videoUrl, let videoUrl = URL(string: videoUrlString) {
        player = AVPlayer(url: videoUrl)
        playerLayer = AVPlayerLayer(player: player)
        playerLayer?.frame = postImageView.frame
        playerLayer?.frame.size.width = postImageView.frame.size.width
        playerLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
        self.contentView.layer.addSublayer(playerLayer!)
        /// Player is initiated with a item to play
        player?.play()
        /// Call current time here
        /// Now it will Enter in if Condition 
        /// Also try using else statement so you know Do control enter in if or in Else
        self.viewcount()
    }


func viewcount()
    {
        if let currentitem = player?.currentItem
        {
            ///Yes Player have a item whose time can be Detected
            if currentitem.currentTime() == CMTimeMake(3, 1)
            {
                print ("VIDEO PLAYED FOR THREE SECONDS")
            }
        }
        else
        {
            /// Check do Control reach here in case 1 When you are calling before player.play()
        }
    }

You are searching for observer of player here is how you can check and track the current position of AVPlayer

Here is function that is adding observer to cell

private func addObserversForVideoPlayer(cell:CustomCell) {

   let observer =  cell.player?.addPeriodicTimeObserver(forInterval: CMTime.init(seconds: 1, preferredTimescale: 1), queue: .main, using: {[weak self,weak cell] (time) in
        guard let cell = cell else {return}

        if cell.player?.currentItem?.status == .readyToPlay {
            // print("Inside Will DISPLAY\(cell.video.currentTime)")

            let timeDuration : Float64 = CMTimeGetSeconds((cell.player?.currentItem?.asset.duration)!)
            cell.lblDuration.text = self?.getDurationFromTime(time: timeDuration)

            let currentTime : Float64 = CMTimeGetSeconds((cell.player?.currentTime())!)
            cell.lblStart.text = self?.getDurationFromTime(time: currentTime)
            cell.slider.maximumValue = Float(timeDuration.rounded())
            cell.slider.value = Float(currentTime.rounded())

        }
    })
    NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: cell.player?.currentItem, queue: .main, using: {[weak cell,weak self]  (notification) in

        if cell?.player != nil {
            cell?.player?.seek(to: kCMTimeZero)
            cell?.player?.play()
        }
    })
}

so that addPeriodicTimeObserver will notify you when the player start playing.

And NSNotification.Name.AVPlayerItemDidPlayToEndTime will notify you when your AVPlayer stops.

Note1: If your cell.player?.currentItem is nil while you are adding AVPlayerItemDidPlayToEndTime it will be cause bug see this One AVPlayer's AVPlayerItemDidPlayToEndTime action executed for all Currently playing videos , If . you don't need it don't add it :)

Note2: You should keep observer so after time you can remove it so that can not take extra load on memory

Hope it is helpful

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM