Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timeline Progress bar for AVPlayer

AVPlayer is fully customizable, unfortunately there are convenient methods in AVPlayer for showing the time line progress bar.

AVPlayer *player = [AVPlayer playerWithURL:URL];
AVPlayerLayer *playerLayer = [[AVPlayerLayer playerLayerWithPlayer:avPlayer] retain];[self.view.layer addSubLayer:playerLayer];

I have an progress bar that indicates the how video has been played, and how much remained just as like MPMoviePlayer.

So how to get the timeline of video from AVPlayer and how to update the progress bar

Suggest me.

like image 625
Sanjeev Rao Avatar asked Jan 04 '12 10:01

Sanjeev Rao


4 Answers

Please use the below code which is from apple example code "AVPlayerDemo".

    double interval = .1f;  

    CMTime playerDuration = [self playerItemDuration]; // return player duration.
    if (CMTIME_IS_INVALID(playerDuration)) 
    {
        return;
    } 
    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration))
    {
        CGFloat width = CGRectGetWidth([yourSlider bounds]);
        interval = 0.5f * duration / width;
    }

    /* Update the scrubber during normal playback. */
    timeObserver = [[player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC) 
                                                          queue:NULL 
                                                     usingBlock:
                                                      ^(CMTime time) 
                                                      {
                                                          [self syncScrubber];
                                                      }] retain];


- (CMTime)playerItemDuration
{
    AVPlayerItem *thePlayerItem = [player currentItem];
    if (thePlayerItem.status == AVPlayerItemStatusReadyToPlay)
    {        

        return([playerItem duration]);
    }

    return(kCMTimeInvalid);
}

And in syncScrubber method update the UISlider or UIProgressBar value.

- (void)syncScrubber
{
    CMTime playerDuration = [self playerItemDuration];
    if (CMTIME_IS_INVALID(playerDuration)) 
    {
        yourSlider.minimumValue = 0.0;
        return;
    } 

    double duration = CMTimeGetSeconds(playerDuration);
    if (isfinite(duration) && (duration > 0))
    {
        float minValue = [ yourSlider minimumValue];
        float maxValue = [ yourSlider maximumValue];
        double time = CMTimeGetSeconds([player currentTime]);
        [yourSlider setValue:(maxValue - minValue) * time / duration + minValue];
    }
} 
like image 135
iOSPawan Avatar answered Nov 15 '22 01:11

iOSPawan


Thanks to iOSPawan for the code! I simplified the code to the necessary lines. This might be more clear to understand the concept. Basically I have implemented it like this and it works fine.

Before starting the video:

__weak NSObject *weakSelf = self;    
[_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1.0 / 60.0, NSEC_PER_SEC)
                                      queue:NULL
                                 usingBlock:^(CMTime time){
                                                [weakSelf updateProgressBar];
                                             }];

[_player play];

Then you need to have a method to update your progress bar:

- (void)updateProgressBar
{
    double duration = CMTimeGetSeconds(_playerItem.duration);
    double time = CMTimeGetSeconds(_player.currentTime);
    _progressView.progress = (CGFloat) (time / duration);
}
like image 29
Raphael Avatar answered Nov 15 '22 00:11

Raphael


    let progressView = UIProgressView(progressViewStyle: UIProgressViewStyle.Bar)
    self.view.addSubview(progressView)
    progressView.constrainHeight("\(1.0/UIScreen.mainScreen().scale)")
    progressView.alignLeading("", trailing: "", toView: self.view)
    progressView.alignBottomEdgeWithView(self.view, predicate: "")
    player.addPeriodicTimeObserverForInterval(CMTimeMakeWithSeconds(1/30.0, Int32(NSEC_PER_SEC)), queue: nil) { time in
        let duration = CMTimeGetSeconds(playerItem.duration)
        progressView.progress = Float((CMTimeGetSeconds(time) / duration))
    }
like image 33
amleszk Avatar answered Nov 14 '22 23:11

amleszk


I know it's an old question, but someone may find it useful. It's only Swift version:

 //set the timer, which will update your progress bar. You can use whatever time interval you want

 private func setupProgressTimer() {
    timer = Timer.scheduledTimer(withTimeInterval: 0.02, repeats: true, block: { [weak self] (completion) in
        guard let self = self else { return }
        self.updateProgress()
    })
}

//update progression of video, based on it's own data

private func updateProgress() {
    guard let duration = player?.currentItem?.duration.seconds,
        let currentMoment = player?.currentItem?.currentTime().seconds else { return }

    progressBar.progress = Float(currentMoment / duration)
}
like image 43
Artem Boordak Avatar answered Nov 15 '22 00:11

Artem Boordak