bilibili / ijkplayer

Android/iOS video player based on FFmpeg n3.4, with MediaCodec, VideoToolbox support.
GNU General Public License v2.0
32.54k stars 8.13k forks source link

Android IjkPlayer seekto后会有时会向后跳跃?不准确怎么解决 #2087

Open jaychou2012 opened 8 years ago

jaychou2012 commented 8 years ago

Android IjkPlayer seekto后会有时会向后跳跃?不准确怎么解决

StayZeal commented 7 years ago

issues/313

zhuzhanpeng commented 7 years ago

问题解决了吗,用的什么方案

ijustkeepmoving commented 6 years ago

视频的SEEKTO是有问题,大部分拖动后,会回跳,甚至从头开始播放。

我提供一个解决方案: 播放视频是,拖动操作结束后,记录拖动位置startPosition,用以下代码重新实例化IJKPLAYER,即可以实现拖到后准确播放。 mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "seek-at-start", startPosition);

MaYinjian commented 5 years ago

@ijustkeepmoving 你好,我试了用mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "seek-at-start", startPosition);,可是还是不行, seekTo(startPosition)
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "seek-at-start", startPosition); 两个一齐调用了也不行,怎么办?

EvanEvil commented 5 years ago

视频的SEEKTO是有问题,大部分拖动后,会回跳,甚至从头开始播放。

我提供一个解决方案: 播放视频是,拖动操作结束后,记录拖动位置startPosition,用以下代码重新实例化IJKPLAYER,即可以实现拖到后准确播放。 mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "seek-at-start", startPosition);

还有其他解决办法吗

trycatchx commented 5 years ago

我已经解决了,包括播放网络视频,而且运行的很好!!我发现一个规律,只要多次seekto 之后,肯定能准确跳转。所以我写了一个重复seekto 的机制:

首先初始化加入配置项:

  //SeekTo设置优化
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0L);
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "fastseek"); //快速seekto
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);

                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "reconnect", 1);
    //重复seekto 的过渡值
    private int curSeekPos = -1;
    private int curSeekCount = 0;
       mPlayerSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (!fromUser) {
                    return;
                }
                long duration = getDuration();
                long newposition = (duration * progress) / 1000L;
                seekTo((int) newposition);
                if (mPlayerTime != null)
                    mPlayerTime.setText(stringForTime((int) newposition));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                curSeekPos = 0;
                curSeekCount = 0;

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                long duration = getDuration();
                long newposition = (duration * seekBar.getProgress()) / 1000L;
                if (mMediaPlayer != null && mMediaPlayer instanceof IjkMediaPlayer) {
                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "seek-at-start", newposition);
                }
                seekTo((int) newposition);
//记录最后需要seekto 的position。
                curSeekPos = (int) newposition;
            }
        });
//重复 seekto
   private void repeatSeekTo() {
        curSeekCount++;
        if (mMediaPlayer != null && mMediaPlayer instanceof IjkMediaPlayer) {
            ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "seek-at-start", curSeekPos);
        }
        seekTo(curSeekPos);
    }
// 监听是不是 seekto 成功了,不成功重seekto,最大次数为 3 次
    private IMediaPlayer.OnSeekCompleteListener mSeekCompleteListener = new IMediaPlayer.OnSeekCompleteListener() {

        @Override
        public void onSeekComplete(IMediaPlayer mp) {
            boolean isSeekComplete = true;
            if (curSeekPos > 0) {
                if (Math.abs(mMediaPlayer.getCurrentPosition() - curSeekPos) <= 1000) {
                    curSeekPos = 0;
                    curSeekCount = 0;
                } else if (curSeekCount <= 3) {
                    repeatSeekTo();
                    isSeekComplete = false;
                }
            }
        }
    };
MoYuFly commented 5 years ago

从seekbar 入手解决,onProgressChanged 这个方法里面最好不要调seekto的方法,因为拖动的时候会一直执行,onStopTrackingTouch在这里面执行一次seekto就可以了,seekto执行一次不会出现跳动的问题。

chenzh2017 commented 4 years ago

seek不准的问题可能会有2个原因导致 1、seekbar导致的,详见#313; 2、未开启精准定位导致的,这个现象目前个人发现的仅影响hls播放,对于m4a或mp3的播放不影响。解决方法就是给播放器设置精准定位,代码如下 player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1); 可参考https://blog.csdn.net/chenzh2016/article/details/109378633问题分析过程

waqasyousafy commented 2 years ago

I am still facing this issue any proper solution