1

I allow users to capture both images and videos and save them to my server. When a user taps on an icon they should be able to view all of the media stored in that particular location. Currently, I am having difficulty assessing when a video ends to move to the next piece of media or when a video is done processing and ready to be played

I am trying to use notification center to update when it is ready to play but it is still not working. I also included a timer which gives images an automatic 3 seconds to be viewed or if it is a video it gets the videos duration and moves after that video has concluded playing

//METHODS: func showFeed() {

        //ensure there is media to present
        if media.count > 0 {
            //check if media is of type video or image
            //show first piece of media initially
            if media[mediaIndex].media_type! == "CAMERA" || media[mediaIndex].media_type! == "LIBRARY" {
                videoDisplay.isHidden = true

                timeInterval = 3.0
                photoDisplay.kf.setImage(with: URL(string: Constants.Server.PHOTO_URL + media[mediaIndex].media_photo_url!))


            } else if media[mediaIndex].media_type! == "VIDEO" {

                //check if photoview is hidden & if not hide it
                videoDisplay.isHidden = false

                var url = URL(fileURLWithPath: Constants.Server.VIDEO_URL + media[mediaIndex].media_video_url!)

                prepareToPlay(url)

            }

            //date formatter

            //media time stamp
            let timeStampStr = formatter.string(from: media[mediaIndex].media_created_at!)
            media_time_stamp.text = GlobalService.sharedInstance().UTCToLocal(date: timeStampStr)
        }

    //begin timer
    //make sure repeat is set to false so timer is fresh
    /*
    if timerCounter == nil {
        timerCounter = Timer.scheduledTimer(withTimeInterval: TimeInterval(timeInterval), repeats: false, block: {(timer) in
              self.scrollToNextCell()
        })
    }
    */

}

Here is the next call to prepareToPlay()

func prepareToPlay(_ url: URL) { //get time interval from player

    let asset = AVAsset(url: url)

    let assetKeys = [
        "playable",
        "hasProtectedContent"
    ]

    playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: assetKeys)

    playerItem!.addObserver(self,
                           forKeyPath: #keyPath(AVPlayerItem.status),
                           options: [.old, .new],
                           context: &playerItemContext)

    player = AVPlayer(playerItem: playerItem!)

}

//handle changes in state of playback item override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

    // Only handle observations for the playerItemContext
    guard context == &playerItemContext else {
        super.observeValue(forKeyPath: keyPath,
                           of: object,
                           change: change,
                           context: context)
        return
    }

    if keyPath == #keyPath(AVPlayerItem.status) {
        let status: AVPlayerItem.Status
        if let statusNumber = change?[.newKey] as? NSNumber {
            status = AVPlayerItem.Status(rawValue: statusNumber.intValue)!
        } else {
            status = .unknown
        }

        // Switch over status value
        switch status {
        case .readyToPlay:

        //hide loading screen
        mediaLoadingView.isHidden = true
        activityIndicator.stopAnimating()
        //play video
        let assetDuration = player?.currentItem?.asset.duration
        let duration = CMTimeGetSeconds(assetDuration!)
        let timeIntervalDuration = Float(duration)
        timeInterval = timeIntervalDuration
        //add player to player layer
        playerLayer = AVPlayerLayer(player: player!)

        //add player layer to UIView
        //move resize aspect fill to where it will be loaded before frame of layer is calculated
        playerLayer!.videoGravity = .resizeAspectFill

        playerLayer!.frame = self.view.bounds

        videoDisplay.layer.addSublayer(playerLayer!)
         player?.play()

        // Player item is ready to play.
        case .failed:
         let alert = SCLAlertView()
         alert.showError("Failed", subTitle: "video was unable to properly load")
        case .unknown:

            // Player item is not yet ready.
            mediaLoadingView.isHidden = false
            activityIndicator.startAnimating()
            print("player not yet ready")
        }
    }
}

I intend to have the media, if it is a video, to begin playing immediately however it does not

Onicha21
  • 141
  • 2
  • 11
  • I find it odd that `AVPlayerLayer` is a local variable. Hrm, never tried that. I generally keep the `AVPlayer`, `AVPlayerLayer` both global variables. Not sure it has to do anything with this; anywho, inside your last function, what gets called? `.failed`, `.succeed`, or `.unknown`? – impression7vx Sep 04 '19 at 23:44
  • @impression7vx .succeed – Onicha21 Sep 08 '19 at 17:39
  • Does everything else happen? Such as the mediaLoadingView hides, the playerLayer is shown and created? It just doesn’t play? – impression7vx Sep 08 '19 at 17:48
  • @impression7vx correct. the playerlayer appears however the screen is black and media does not get played – Onicha21 Sep 11 '19 at 20:43
  • Can you press play and start the video? This would mean that the playerLayer is there and ready to go - it just doesn’t start automatically, you have to do it yourself – impression7vx Sep 11 '19 at 20:54
  • @impression7vx i'm confused? Once the observer declares that that the player is readyToPlay I call player.play() to begin playing the media – Onicha21 Sep 11 '19 at 21:52
  • I understand - and that is not working for you. But can you manually start the video? – impression7vx Sep 12 '19 at 00:16
  • I haven't attempted this yet – Onicha21 Sep 12 '19 at 01:12
  • Well. If you CAN manually start the movie - then you know the playback that determines if the movie can play might be messed up; if you CANNOT - then there might be another problem. Maybe there is a view being added on top that you cannot see that is black and the movie is actually being played - you just don’t see it because it is hiding. That’s just a single potential theory. – impression7vx Sep 12 '19 at 01:16

0 Answers0