VideoView 和 MediaPlayer seekTo 总是从头开始

VideoView and MediaPlayer seekTo always starts from beginning

我在寻找在 VideoView 中播放的视频并继续播放时遇到了一些问题。

这是我的部分代码:

videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
        mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
            @Override
            public void onSeekComplete(MediaPlayer mp) {
                Log.d("V", "onSeekComplete1 " + videoView.getCurrentPosition());
                videoView.start();
                Log.d("V", "onSeekComplete1 " + videoView.getCurrentPosition());
            }
        });
    }
});
videoView.setVideoURI('some local uri');

有时我会使用以下方法暂停视频: videoView.pause();

点击按钮后我正在寻找特定时间的视频,例如。 10 秒(10 000 毫秒)。

@OnClick(R2.id.ivMove)
void clickMove() {
   videoView.seekTo(10000);
}

之后在日志中我看到:

onSeekComplete1 10000
onSeekComplete2 0

所以在调用 videoView.start() 之后,它正在从头开始播放视频!

但是当我在不寻找视频的情况下调用 start() 时(例如,一个按钮调用 pause() 和第二个调用 start() 然后视频正在正确播放 - 从暂停的那一刻开始,而不是从开始。

你能告诉我我做错了什么吗?

尝试 videoView.resume() 而不是 start()

videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
        mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
            @Override
            public void onSeekComplete(MediaPlayer mp) {
                Log.d("V", "onSeekComplete1 " + videoView.getCurrentPosition());
                videoView.resume();
                Log.d("V", "onSeekComplete1 " + videoView.getCurrentPosition());
            }
        });
    }
});
videoView.setVideoURI('some local uri');

问题是由 MediaPlayer 引起的 - 它正在寻找最接近视频的关键帧,结果发现我的测试视频每隔约 30 秒就有一个关键帧。

我改成ExoPlayer https://github.com/google/ExoPlayer - 它可以精确定位。

MediaPlayer seekTo 方法有一个新的重载。它有第二个 int 参数,您可以在其中传递一个 SEEK_CLOSEST 常量。根据Google,"This mode is used with seekTo(long, int) to move media position to a frame (not necessarily a key frame) associated with a data source that is located closest to or at the given time."在测试我自己的应用程序时,它解决了API级别> = 26的问题。我不确定[=14之前是否有任何好的选择=] 26级。

试试这个解决方案。它就像魅力....

   videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            mp.start();
            mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
                @Override
                public void onSeekComplete(MediaPlayer mp) {
                    mp.start();
                }
            });

        }
    });