【问题标题】:What is the best way to get an audio file duration in Android?在 Android 中获取音频文件持续时间的最佳方法是什么?
【发布时间】:2011-06-10 05:46:51
【问题描述】:

我正在使用SoundPool 在我的应用程序中播放音频剪辑。一切都很好,但我需要知道剪辑播放何时结束。

目前,我通过使用MediaPlayer 实例获取每个剪辑的持续时间,在我的应用程序中跟踪它。这工作正常,但加载每个文件两次看起来很浪费,只是为了获得持续时间。知道文件的长度(可从AssetFileDescriptor 获得)我自己可以粗略地计算持续时间,但我仍然需要知道采样率和通道数。

我看到了解决该问题的两个潜在解决方案:

  1. 确定剪辑何时播放完毕(SoundClip 似乎无法实现)。
  2. 有一个类可以只加载音频文件的标题,并为我提供采样率/通道数(理想情况下,还可以通过采样计数来获得确切的持续时间)。

有什么建议吗?

谢谢, 最大

我目前正在使用的代码(工作正常,但为此目的相当繁重):

String[] fileNames = ...
MediaPlayer mp = new MediaPlayer();
for (String fileName : fileNames) {
    AssetFileDescriptor d = context.getAssets().openFd(fileName);
    mp.reset();
    mp.setDataSource(d.getFileDescriptor(), d.getStartOffset(), d.getLength());
    mp.prepare();
    int duration = mp.getDuration();
    // ...
}

顺便说一句,这个问题已经asked,但没有得到答案。

【问题讨论】:

  • 你考虑过onCompletitionListener吗? developer.android.com/reference/android/media/…
  • @SatelliteSD 它在我拥有的任何设备上都无法正常工作(永远不会被调用)。即使它确实在某些操作系统版本/某些设备上被调用,它也是不可靠的,因此无用。
  • 您确认setOnCompletitionListner 是在.start() 之后调用的?
  • 完成监听器仅用于 MediaPlayer,不适用于 SoundPool。据我所知,对声音完成进行回调的唯一方法是使用 MediaPlayer,而不是 SoundPool。

标签: android audio media-player duration soundpool


【解决方案1】:

你试过了吗:

String mediaPath = Uri.parse("android.resource://<your-package-name>/raw/filename").getPath();
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(mediaPath);
String duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
mmr.release();

但我不确定这是否比现有代码更轻量。

【讨论】:

  • 别忘了发布MediaMetadataRetriever
  • 我试过这个,但我总是从mmr.setDataSource() 抛出一个 IllegalArgumentException - 有什么方法可以找出该路径的确切外观吗?因为我怀疑我使用的路径可能不正确。我正在使用捆绑中的 .m4a 和/或 .wav 音频文件。
  • @Meher 完美答案+1
  • 有什么方法可以在不下载文件的情况下从 URL 检查持续时间
【解决方案2】:

试试FFmpegMediaMetadataRetriever:

String[] fileNames = ...
FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();

for (String fileName : fileNames) {
    AssetFileDescriptor d = context.getAssets().openFd(fileName);
    mmr.setDataSource(d.getFileDescriptor(), d.getStartOffset(), d.getLength());
    String duration = mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION);
}

mmr.release();

【讨论】:

    【解决方案3】:

    这对我来说是获取资产音频文件持续时间(以总秒为单位)的工作=====>

    MediaMetadataRetriever mmr = new MediaMetadataRetriever();
    AssetFileDescriptor d = context.getAssets().openFd(fileName);
    mmr.setDataSource(d.getFileDescriptor(), d.getStartOffset(), d.getLength());
    String duration = 
    mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
    mmr.release();
    

    更新

    获取资产音频文件持续时间的方法

      public String gettotaltimeassets() {
    
       MediaMetadataRetriever mmr = new MediaMetadataRetriever();
        AssetFileDescriptor d = null;
        try {
            d = getApplicationContext().getAssets().openFd("ASSETS FILE NAME");
        } catch (IOException e) {
            e.printStackTrace();
        }
        mmr.setDataSource(d.getFileDescriptor(), d.getStartOffset(), d.getLength());
        String duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        long dur = Long.parseLong(duration);
        String seconds = String.valueOf((dur % 60000) / 1000);
        Log.d("seconds===========>", seconds);
        mmr.release();
        return  seconds;
    }
    

    获取内部存储音频文件持续时间的方法

    public String gettotaltimestorage(String filePath) {
        // load data file
        Log.d("time=================>","time=================>");
        MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
        metaRetriever.setDataSource(YourACTIVITY.this, Uri.parse(filePath));
        Log.d("time=================>","time=================>");
        String out = "";
        // get mp3 info
    
        // convert duration to minute:seconds
        String duration =
                metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        Log.d("time=================>", duration);
        long dur = Long.parseLong(duration);
        String seconds = String.valueOf((dur % 60000) / 1000);
        Log.d("seconds===========>", seconds);
        // close object
        metaRetriever.release();
        return  seconds;
    
    }
    

    【讨论】:

    • 请解释您的回答。这不仅有助于了解当前问题的原因,而且可以避免将来发生同样的问题。
    • 实际上我编写代码来获取资产中任何音频文件的持续时间,正如@William Seemann 所写,但我使用 MediaMetadata 来检索持续时间...我修改了我的答案,以便您更好地理解...您可以致电此方法用于多个音频文件获取持续时间。
    • 我没有写该评论是因为我无法理解您的代码,但在您的解决方案中附上适当的解释是一种很好的做法。仅代码的答案不受欢迎。
    猜你喜欢
    • 1970-01-01
    • 2015-06-10
    • 2014-02-08
    • 2020-06-02
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    • 2013-10-27
    相关资源
    最近更新 更多