首页 > 解决方案 > MediaPlayer 的 seekTo 方法不适用于 mkv 文件

问题描述

我在将 Seekbar 连接到具有 vorbis 编码的 mkv 文件的 MediaPlayer 时遇到了一个非常奇怪的问题。这是根据https://developer.android.com/guide/topics/media/media-formats支持的格式

当 MediaPlayer 通过 SeekBar.OnSeekBarChangeListener 的 onStopTrackingTouch 方法更新时,MediaPlayer 应该寻找到 Seekbar 的位置。此代码适用于 mp3 和 aac 文件。

    @Override
    public void onStopTrackingTouch(SeekBar seekBar){
        serviceMain.seekTo(seekBar.getProgress());
    }

    public void seekTo(int progress) {
        MediaPlayerWUri mediaPlayerWUri = getCurrentMediaPlayerWUri(); // This is a MediaPlayer wrapper
        if (mediaPlayerWUri != null) { // The correct one is returned // verified by debugger
            mediaPlayerWUri.seekTo(progress);
        }
    }

    public void seekTo(int millis){
        if (isPrepared) {
            mediaPlayer.seekTo(millis); // millis has the correct values // verified via debugger
        }
    }

我用媒体持续时间更新了 Seekbar 的最大值;验证它是用调试器调用的。

    private void updateSeekBar() {
        SeekBar seekBar = findViewById(R.id.seekBar);
        if (seekBar != null && serviceMain != null) {
            final int maxMillis = serviceMain.getCurrentSong().getDuration(getApplicationContext());
            seekBar.setMax(maxMillis); // 2305946ms for a file that has the issue
            seekBar.setProgress(getCurrentTime());
            seekBar.setOnSeekBarChangeListener(onSeekBarChangeListener);
            setUpSeekBarUpdater(); // Seek bar updater is a Runnable run every second // code below
        }
    }

    Runnable runnableSeekBarUpdater = new Runnable() {
        @Override
        public void run() {
            if (mediaPlayerWURI.isPlaying()) {
                int currentMilliseconds = mediaPlayerWURI.getCurrentPosition();
                seekBar.setProgress(currentMilliseconds);
            }
        }
    };

Mkv 文件不适用于此代码;我有奇怪的行为。如果我使用长媒体文件寻找 MediaPlayer 的当前位置,则音频停止并且永远不会开始。如果我在 MediaPlayer 的当前位置之前搜索,则 Seekbar 会返回不到一秒钟并跳回当前位置,MediaPlayer 会执行相同的操作。更奇怪的是,当音频停止播放时,MediaPlayer 会继续运行(不更新 Seekbar),当播放结束时 MediaPlayer 会调用 onCompletion。此外,MediaPlayer 在完成后正确响应 seekTo(0),但当 MediaPlayer 到达 5:50 或附近某个地方时,音频停止。

对于较短的 mkv 文件,搜索操作大约需要一两分钟,因为在尝试搜索时没有播放音频。这是无法接受的。我在长文件中得到相同的行为,如果在计时器到达结束之前搜索操作没有完成,则调用 onCompletion。我假设这意味着长 mkv 文件搜索需要很长时间才能完成,以至于计时器在搜索完成之前运行到最后。

查找时,长 mkv 文件会提供类似以下日志的内容:

2020-12-01 16:50:35.840 945-12690/? D/NuPlayerDriver: seekTo(0xaf72e8c0) (120991 ms, 3) at state 5
2020-12-01 16:50:35.840 31974-31974/com.example.waveplayer V/ServiceMain: seekTo end
2020-12-01 16:50:35.841 31974-31974/com.example.waveplayer V/ActivityMain: seekTo end
2020-12-01 16:50:35.843 938-938/? E/MatroskaExtractor: Did not locate the video track for seeking

这些日志属于这种编码

  Metadata:
    ENCODER         : Lavf58.49.100
  Duration: 00:38:25.95, start: 0.006000, bitrate: 139 kb/s
    Stream #0:0(eng): Audio: vorbis, 192000 Hz, stereo, fltp (default)
    Metadata:
      ENCODER         : Lavc58.98.100 libvorbis
      DURATION        : 00:38:25.946000000

数字是正确的并且低于最大值,所以我不知道为什么它不起作用。

这是一个错误吗?mp3 和 aac 文件不这样做。

查找时,短 mkv 文件会给出不同的日志输出:

2020-12-01 19:14:19.064 945-26530/? I/NuPlayerDecoder: [OMX.google.vorbis.decoder] resubmitting CSD
2020-12-01 19:14:19.065 945-26530/? I/NuPlayerDecoder: [OMX.google.vorbis.decoder] resubmitting CSD
2020-12-01 19:14:19.066 945-26530/? I/NuPlayerDecoder: [OMX.google.vorbis.decoder] suppressing rendering until 401945000 us

短 mkv 有这种编码

  Metadata:
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    COMPATIBLE_BRANDS: iso6avc1mp41
    ENCODER         : Lavf58.49.100
  Duration: 00:18:47.53, start: 0.006000, bitrate: 143 kb/s
    Stream #0:0(eng): Audio: vorbis, 192000 Hz, stereo, fltp (default)
    Metadata:
      ENCODER         : Lavc58.98.100 libvorbis
      DURATION        : 00:18:47.534000000

有没有办法来解决这个问题?

标签: androidandroid-mediaplayerandroid-seekbar

解决方案


推荐阅读