android - 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
有没有办法来解决这个问题?
解决方案
推荐阅读
- assembly - x64 中的这段代码有什么问题?它在 VS2019 中不返回 0
- rust - 将 ty 转换为 macro_rules 中的 ident
- python - 不显示提取的数据
- spring - 如何在 Spring-boot 应用程序中获取 context-path 和 info.info?
- python - 是否可以通过迭代附加到数据框?
- scala - 在 Scala 中导入 Doodle 库
- javascript - 带有 json 转义的 Mustache 渲染
- amazon-web-services - 如何为基于事件的数据构建 DynamoDB 表?
- reactjs - 我正在使用 ajax 从 api 获取数据,但我还想要一个搜索框来添加 pincode 以获取表中的特定数据?
- linux - 通过 Linux shell 将 ANSI 编码转换为另一种编码