是否可以在不下载的情况下获取远程音频文件的持续时间?

时间:2013-03-21 15:47:36

标签: android android-mediaplayer

我有一个远程音频文件的Url。我需要使用跟踪详细信息为适配器列表构建数据。这是代码的这一部分

    Log.d("audioURL", audio.getUrl());
    MediaPlayer tmpMedia;
    tmpMedia = MediaPlayer.create(getContext(), Uri.parse(audio.getUrl()));
    holder.txtDuration.setDuration(tmpMedia.getDuration()/1000);
    tmpMedia.release();

但是效果太慢了。 LogCat写了这样的东西:

15:05:51.783: D/audioURL(776): http://cs4859.vk.me/u14195999/audios/0cbd695ddf50.mp3
15:05:51.783: D/MediaPlayer(776): Couldn't open file on client side, trying server side
15:05:53.813: D/audioURL(776): http://cs4859.vk.me/u14195999/audios/0cbd695ddf50.mp3
15:05:53.823: D/MediaPlayer(776): Couldn't open file on client side, trying server side
15:05:55.373: D/audioURL(776): http://cs4859.vk.me/u14195999/audios/0cbd695ddf50.mp3
15:05:55.383: D/MediaPlayer(776): Couldn't open file on client side, trying server side
15:05:58.143: D/audioURL(776): http://cs1626.vk.me/u149968/audios/04298447cd3c.mp3
15:05:58.153: D/MediaPlayer(776): Couldn't open file on client side, trying server side

......等等。因此,我的约30首曲目的播放列表初始化约7分钟。

我想,MediaPlayer类方法getDuration()会依次下载这些曲目(或其中的某些部分)以获取其持续时间。

有没有办法快速获得这些持续时间,而无需下载曲目?

Halim Qarroum,这似乎是一种正确的方式,但我在MediaMetadataRetriever课时遇到了一些麻烦。

以上是我的代码:

    if (android.os.Build.VERSION.SDK_INT < 10){
        holder.txtDuration.setDuration(audio.getTrackDuration());
    } else {
        MediaMetadataRetriever mRetriever = new MediaMetadataRetriever();
        Log.d("URI", Uri.parse(audio.getUrl()).toString());
        mRetriever.setDataSource(getContext(), Uri.parse(audio.getUrl()));
        String s = mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        holder.txtDuration.setDuration(Long.parseLong(s));
        mRetriever.release();
    }

由于mRetriever.setDataSource(getContext(), Uri.parse(audio.getUrl()));,应用程序终止于IllegalArgumentExceptionaudio.getURl()字符串为http://cs4859.vk.me/u14195999/audios/134dfe90d1ec.mp3

为什么会发生异常?

3 个答案:

答案 0 :(得分:4)

我会假设mp3,因为“音频文件”是一个短语。

方法1:获取ID3标签

变式1:第三方库

您需要查看mp3文件中的ID3标签。 除非你跟踪你想要的其他元数据。

要专门获取文件的跟踪长度,您需要查看ID3元数据标记,特别是标记的“TRCK”框架。

要仅下载ID3标记部分,必须先下载文件的ID3标题部分。

website包含有关ID3标记格式的非常具体的信息。您需要查看ID3标签的版本号,然后,基于此,您需要找到有关ID3标签的时间长度的信息。然后,您必须下载WHOLE标记,因为框架没有任何特定顺序。

然后您应该能够使用第三方库来查找TRCK帧及其数据。

变式2:HTTP Hack

对于ID3v2标签,请抓取文件的开头。 (ID3v2帧可能在其他地方,但实际上它们总是在那里。)你无法预先确定标签的长度。对于纯文本标签,您可能会在前512-1024字节中找到所需的信息。不幸的是,越来越多的MP3嵌入了“专辑艺术”图片,这可能会更长;尝试选择一个优雅地忽略截断的ID3信息的ID3库。

ID3v1标签位于文件末尾。再一次,你无法分辨他们将会有多长时间。当然,您事先并不知道该文件是否具有ID3v1标签,ID3v2标签,两者都有或两者都没有。一般来说,这些天ID3v2是更好的选择。

要通过HTTP读取文件的一部分,您需要Range标头。这在任何地方都不受支持。

方法2:估算

使用HTTP HEAD请求可以获得的文件大小。持续时间意味着以秒为单位的播放时间,如果不提取整个文件,则无法获得。您可以猜测,通过获取前几个MP3帧,查看它们的比特率,并假设文件的其余部分具有相同的比特率,但考虑到可变比特率编码的普及,这可能性将接近准确的是相当低的。

  理论上,ID3标签可以包含可能允许的信息   在ASPI和ETCO标签中猜测长度更好。但在实践中   这些很少出现。

积分

  

关于SO和互联网的各种作者的信誉,当然是我头脑中一楼的人。

答案 1 :(得分:4)

Dheeb发布了详细的答案。但是,ID3 tags并不总是存在于mp3文件中。您可以使用Android框架附带的MediaMetadataRetriever类,而不是查找会强制您将此方法限制为mp3文件的这些标记。

这个类可以为您提供来自某些类型的音频/视频文件的几个元数据,其中一个信息就是持续时间。此方法具有标准优势,因为它附带Android SDK,并且不限于一种音频格式。

来自Android开发者相关页面:

  

MediaMetadataRetriever类为其提供统一的界面   从输入媒体文件中检索帧和元数据。

使用此类的代码的简单示例:

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(your_data_source);
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long timeInmillisec = Long.parseLong( time );
long duration = timeInmillisec / 1000;
long hours = duration / 3600;
long minutes = (duration - hours * 3600) / 60;
long seconds = duration - (hours * 3600 + minutes * 60);

答案 2 :(得分:0)

存在与MediaMetadataRetriever相关的错误。 您可以尝试,

 metaRetreiver.setDataSource("<remoteUrl>", new HashMap<String, String>());