通过ijkPlayer播放m3u8视频时快进不准确的解决方案

144
作者 雪夜月
2016.08.29 19:28 字数 338

我们知道,m3u8是分片的,通过currentPlaybackTime来获取当前的播放时间并不准确。
这篇文章主要为解决以下两个问题:

  1. 在拖动进度条的时候,你会发现当你拖到10:08,它可能会回到10:02这种位置播放,这很科学,但不是我想要的。
  2. 测试发现两小时以上视频在播放过程中滑到视频后半段会回退到一个莫名其妙的位置,而当前播放视频画面确实是当前的时间点的图像。

github官方demo中的refreshMediaControl方法里,它是这么处理的:

- (void)refreshMediaControl {
        //duration
        NSTimeInterval duration = self.delegatePlayer.duration;
        NSInteger intDuration = duration+0.5;
        if (intDuration>0) {
            self.mediaProgressSlider.maximumValue = duration;
            self.currentTimeLabel.text = [NSString stringWithFormat:@"%02d:%02d",(int)(intDuration/60),(int)(intDuration% 60)];

        }else{
            self.currentTimeLabel.text = @"--:--";
            self.mediaProgressSlider.maximumValue = 1.0f;

        }

        //position
        NSTimeInterval  position;
        if (_isMediaSliderBeingDragged) {
            position = self.mediaProgressSlider.value;
        }else{
            position = self.delegatePlayer.currentPlaybackTime;

        }
        NSInteger intPosition = position +0.5;
        if (intDuration  > 0) {
            self.mediaProgressSlider.value = position;
        }else{
            self.mediaProgressSlider.value = 0.0f;
        }
        self.currentTimeLabel.text =[NSString stringWithFormat:@"%02d:%02d",(int)(intPosition/60),(int)(intPosition% 60)];

        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(refreshMediaControl) object:nil];
        if (!self.overlayPanel.hidden) {
            [self performSelector:@selector(refreshMediaControl) withObject:nil afterDelay:0.5];
        }

    }

注意到它获取position的方式是通过self.delegatePlayer.currentPlaybackTime获取的,稍作修改:

if (_isMediaSliderBeingDragged) {
      position = self.mediaProgressSlider.value;
}else{
      if (self.delegatePlayer.playbackState == IJKMPMoviePlaybackStatePlaying && self.delegateIndicatorView.hidden) {
            self.mediaProgressSlider.value += 0.5;
      }
      position = self.mediaProgressSlider.value; //self.delegatePlayer.currentPlaybackTime;
}

另外,由于self.mediaProgressSlider.value通过自身value实时改变而不是self.delegatePlayer.currentPlaybackTime,需要实时调用refreshMediaControl方法,所以需要去除判断。

if (!self.overlayPanel.hidden) {

            [self performSelector:@selector(refreshMediaControl) withObject:nil afterDelay:0.5];

}
这样会导致一种情况,即当你重复点击屏幕会反复调用hideMediaControl和showMediaControl方法,间接导致self.mediaProgressSlider.value变化太快,需要注释掉这两个方法里的refreshMediaControl调用。
不过,这种做法其实算掩耳盗铃了,有时间可以再研究精准定位播放时间。

日记本