时间轴AVPlayer进度条

AVPlayer是完全可定制的,不幸的是在AVPlayer有方便的方法来显示时间线进度条。

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

我有一个进度条,指示播放video的方式,还有多less像MPMoviePlayer一样。

那么如何从AVPlayer获取video的时间轴以及如何更新进度条

build议我

请使用苹果示例代码“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); } 

并在syncScrubber方法中更新UISlider或UIProgressBar的值。

 - (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]; } } 

感谢iOSPawan的代码! 我简化了代码到必要的行。 理解这个概念可能会更清楚。 基本上我已经实现了这样,它工作正常。

在开始video之前:

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

那么你需要有一个方法来更新你的进度条:

 - (void)updateProgressBar { double duration = CMTimeGetSeconds(_playerItem.duration); double time = CMTimeGetSeconds(_player.currentTime); _progressView.progress = (CGFloat) (time / duration); } 
  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)) } 

为时间线我做这个

 -(void)changeSliderValue { double duration = CMTimeGetSeconds(self.player.currentItem.duration); [lengthSlider setMaximumValue:(float)duration]; lengthSlider.value = CMTimeGetSeconds([self.player currentTime]); int seconds = lengthSlider.value,minutes = seconds/60,hours = minutes/60; int secondsRemain = lengthSlider.maximumValue - seconds,minutesRemain = secondsRemain/60,hoursRemain = minutesRemain/60; seconds = seconds-minutes*60; minutes = minutes-hours*60; secondsRemain = secondsRemain - minutesRemain*60; minutesRemain = minutesRemain - hoursRemain*60; NSString *hourStr,*minuteStr,*secondStr,*hourStrRemain,*minuteStrRemain,*secondStrRemain; hourStr = hours > 9 ? [NSString stringWithFormat:@"%d",hours] : [NSString stringWithFormat:@"0%d",hours]; minuteStr = minutes > 9 ? [NSString stringWithFormat:@"%d",minutes] : [NSString stringWithFormat:@"0%d",minutes]; secondStr = seconds > 9 ? [NSString stringWithFormat:@"%d",seconds] : [NSString stringWithFormat:@"0%d",seconds]; hourStrRemain = hoursRemain > 9 ? [NSString stringWithFormat:@"%d",hoursRemain] : [NSString stringWithFormat:@"0%d",hoursRemain]; minuteStrRemain = minutesRemain > 9 ? [NSString stringWithFormat:@"%d",minutesRemain] : [NSString stringWithFormat:@"0%d",minutesRemain]; secondStrRemain = secondsRemain > 9 ? [NSString stringWithFormat:@"%d",secondsRemain] : [NSString stringWithFormat:@"0%d",secondsRemain]; timePlayed.text = [NSString stringWithFormat:@"%@:%@:%@",hourStr,minuteStr,secondStr]; timeRemain.text = [NSString stringWithFormat:@"-%@:%@:%@",hourStrRemain,minuteStrRemain,secondStrRemain]; 

并导入CoreMedia框架

lengthSlider是UISlider

在我的情况下,下面的代码工作Swift 3:

 var timeObserver: Any? override func viewDidLoad() { ........ let interval = CMTime(seconds: 0.05, preferredTimescale: CMTimeScale(NSEC_PER_SEC)) timeObserver = avPlayer.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { elapsedTime in self.updateSlider(elapsedTime: elapsedTime) }) } func updateSlider(elapsedTime: CMTime) { let playerDuration = playerItemDuration() if CMTIME_IS_INVALID(playerDuration) { seekSlider.minimumValue = 0.0 return } let duration = Float(CMTimeGetSeconds(playerDuration)) if duration.isFinite && duration > 0 { seekSlider.minimumValue = 0.0 seekSlider.maximumValue = duration let time = Float(CMTimeGetSeconds(elapsedTime)) seekSlider.setValue(time, animated: true) } } private func playerItemDuration() -> CMTime { let thePlayerItem = avPlayer.currentItem if thePlayerItem?.status == .readyToPlay { return thePlayerItem!.duration } return kCMTimeInvalid } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) avPlayer.removeTimeObserver(timeObserver!) }