MediaPlayer.getDuration() 返回错误的持续时间

3

MediaPlayer的getDuration()方法对于某些音频文件给出了不正确的值。我认为所有这些文件的共同特点是它们都使用Audacity或其他音频编辑工具进行过处理。当试图将MediaPlayer进度与进度条相关联时,这是一个问题。

我已经记录了它:

while(mPlayer.isPlaying())
    Log.i("progress/total", 
            mPlayer.getCurrentPosition() + 
            "/" + mPlayer.getDuration());

然后我找到了这个:

I/progress/total(643): 14615/14620
I/progress/total(643): 14647/14620

这只是数千个日志行中的两个,但重点是进度超过getDuration()认为的歌曲总时长后,它仍然继续。因为MediaPlayer实际上可以提供正确的持续时间总和,所以是否有一种方法可以使用它来获取ProgressBar的适当最大值?


这首歌实际上有多长? - ghostbust555
1
文件是什么格式?许多播放器报告可变比特率MP3的错误值。尝试使用恒定比特率重新导出它们,看看是否可以解决问题。 - Geobits
2
是的,它们是MP3文件。这些文件将由用户从设备中选择,因此我正在寻找一种不需要重新导出文件的解决方案。我在想,因为MediaPlayer可以在播放完整首歌曲时获取其完整持续时间(getCurrentPosition()与getDuration()无关),所以我可能能够找到一个hacky的方法来修复进度条。你有什么想法吗? - JMRboosties
3个回答

2

当我在HTC Desire C上运行ICS 4.0.3系统时,使用MediaPlayer.getDuration()方法获取mp3文件的时长时返回了542434毫秒,这与实际播放时间相差太大了。该文件本身约为89秒。我检查了mp3文件内容,并发现其中有一些奇怪的xml代码:

<?xpacket begin="п»ї" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.351735, 2008/07/22-18:04:26        ">

将该文件另存为新文件后,xml被删除,getDuration()返回正确的值。我知道这对于需要播放不能修改的文件的人没有帮助,但对于那些可以修改的人来说,这应该会有所帮助。


我们之前使用 Adobe Soundbooth 导出 MP3 文件;但是现在我们将它们转换成 Ogg 格式通过 Audacity,看起来能够得到正确的播放时长。 - Paul Lammertsma

0

我遇到了类似的情况。在我的情况下,mPlayer.getDuration()mPlayer.getCurrentPosition() 的时间差大约为80秒。

在阅读了一些相关帖子后,我使用第三方软件将 mp3 的采样率从 22,000 kHz 转换为 44,100 kHz。转换后,getDuration()getCurrentPosition() 的结果几乎相同(0.0012秒的恒定误差)。

以下是使用的测试:

dur = mp.getDuration();
Log.d("dur", dur + " <- getDuration");
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    public void onCompletion(MediaPlayer mp) {
        // finish current activity
       Log.d("dur", mp.getCurrentPosition() + " <- getCurrentPostion");

    }
});

0

我之前尝试在演示播放器中播放视频,当我在Android模拟器上测试时,它的行为与您提出的问题类似,但当我在一些真实设备上尝试时,它给了我媒体时长的准确值。

如果您只想通过SeekBar同步播放媒体,则可以执行以下操作:

if (!mediaPlayer.isPlaying())
mediaPlayer.start();

handler.post(new SeekbarRefresh(seekbar));

//Class to update progress of seekbar according to music player 
private class SeekbarRefresh implements Runnable {
    SeekBar seekBar;

    public SeekbarRefresh(SeekBar seekBar, ImageView imageView) {
        this.seekBar = seekBar;
    }

    @Override
    public void run() {

        if (mediaPlayer != null) {
            if (mediaPlayer.getDuration() > 0) {
                int currentDuration = mediaPlayer.getCurrentPosition();
                seekBar.setProgress(currentDuration);
                if (mediaPlayer.isPlaying()){
                    handler.post(this);
                    isAudioPlaying = true;
                     }
                else {
                    handler.removeCallbacks(this);
                    isAudioPlaying = false;
                }
            }
        }
    }
}

    seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                boolean fromUser) {

            mediaPlayer.seekTo(progress);
        }
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接