Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Achieve smooth video scrubbing with AVPlayer

I am trying to achieve smooth video scrubbing with AVPlayer through UISlider I have searched and it seems Apple has a Technical Q&A and explained how to achieve this, but my problem is how should I use this method and change player current time with a UISlider: stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime)

Here is my code :

//Play Intro Movie
let videoURL = Bundle.main.url(forResource: "intro", withExtension: "mp4")
player = AVPlayer(url:videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.frame
view.layer.addSublayer(playerLayer)
//videoPlayer.play()


view.addSubview(slider)
slider.maximumValue = 0
slider.maximumValue = Float(CMTimeGetSeconds((player.currentItem?.asset.duration)!))

Here is Apple sample code :

func stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime)
    {
        player.pause()

        if CMTimeCompare(newChaseTime, chaseTime) != 0
        {
            chaseTime = newChaseTime;

            if !isSeekInProgress
            {
                trySeekToChaseTime()
            }
        }
    }




    func trySeekToChaseTime()
    {
        if playerCurrentItemStatus == .unknown
        {
            // wait until item becomes ready (KVO player.currentItem.status)
        }
        else if playerCurrentItemStatus == .readyToPlay
        {
            actuallySeekToTime()
        }
    }


    func actuallySeekToTime()
    {
        isSeekInProgress = true
        let seekTimeInProgress = chaseTime
        player.seek(to: seekTimeInProgress, toleranceBefore: kCMTimeZero,
                          toleranceAfter: kCMTimeZero, completionHandler:
            { (isFinished:Bool) -> Void in

                if CMTimeCompare(seekTimeInProgress, self.chaseTime) == 0
                {
                    self.isSeekInProgress = false
                }
                else
                {
                    self.trySeekToChaseTime()
                }
        })
    }
like image 226
iOS.Lover Avatar asked Jun 08 '17 11:06

iOS.Lover


2 Answers

Although I'm not using the same method as you do which is stopPlayingAndSeekSmoothlyToTime, I thought I should help you with the seeking action of the player.

func sliderValueChanged() {
    var timeToSeek = player.currentItem?.asset.duration.seconds
    timeToSeek = timeToSeek * Double(slider.value)
    player.seek(to: CMTimeMake(Int64(timeToSeek), 1))
}

Also you should set the slider.maximumValue to 1. Hope this helps.

Note: Please don't forget to handle currentItem optional value. If it is nil you should set the value 0 for timeToSeek variable.

like image 51
Ayazmon Avatar answered Oct 23 '22 07:10

Ayazmon


On slider value change event, just call the

stopPlayingAndSeekSmoothlyToTime(CMTime.init(seconds: (player.currentItem?.asset.duration.seconds)!* slider.value, preferredTimescale: 1000))

The Apples sample code will change the player current time. You can also adjust toleranceBefore and toleranceAfter if you scrub the slider really fast.

like image 4
Surendra Patidar Avatar answered Oct 23 '22 08:10

Surendra Patidar