Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to retrieve album art from remote mp3 file in Android?

Tags:

android

upnp

I'm currently writing a UPnP remote control app which is used to connect a remote MediaServer to a remote MediaRenderer. Since the actual MP3 files aren't sent to the Android device, I'd like to be able to get the album art of the currently playing file without having to download the entire MP3 file to my phone.

I've read that MediaMetadataRetriever is useful for this kind of thing, but I haven't been able to get it to work. Each way I try it, I keep getting an IllegalArgumentException by the call to MediaMetadataRetriever#setDataSource, which indicates that my file handle or URI is invalid.

MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();

The following works since it's a direct file path on the device itself:

metaRetriever.setDataSource("/sdcard/Music/Daft_Punk/Homework/01 - Daftendirekt.mp3");

However, any of the following fail with the same error:

metaRetriever.setDataSource(appCtx, Uri.parse("http://192.168.1.144:49153/content/media/object_id/94785/res_id/1/rct/aa"));
metaRetriever.setDataSource(appCtx, Uri.parse("http://192.168.1.144:49153/content/media/object_id/94785/res_id/0/ext/file.mp3"));
metaRetriever.setDataSource("http://192.168.1.144:49153/content/media/object_id/94785/res_id/0/ext/file.mp3");

The first one is the albumArtURI pulled from the UPnP metadata (no *.mp3 extension, but the file will download if pasted into a web browser).

The second and third attempts are using the "res" value from the UPnP metadata, which points to the actual file on the server.

I'm hoping I'm just parsing the URI incorrectly, but I'm out of ideas.

Any suggestions? Also, is there a better way to do this entirely when pulling from a UPnP server? FWIW, I'm using the Cling UPnP library.

== SOLUTION ==

I started looking into william-seemann's answer and it led me to this: MediaMetadataRetriever.setDataSource(String path) no longer accepts URLs

Comment #2 on this post mentions using a different version of setDataSource() that still accepts remote URLs.

Here's what I ended up doing and it's working great:

private Bitmap downloadBitmap(final String url) {
     final MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
     metaRetriever.setDataSource(url, new HashMap<String, String>());
     try {
        final byte[] art = metaRetriever.getEmbeddedPicture();
        return BitmapFactory.decodeByteArray(art, 0, art.length);
     } catch (Exception e) {
        Logger.e(LOGTAG, "Couldn't create album art: " + e.getMessage());
        return BitmapFactory.decodeResource(getResources(), R.drawable.album_art_missing);
     }
  }
like image 554
agelter Avatar asked Jul 31 '13 16:07

agelter


1 Answers

FFmpegMediaMetadataRetriever will extract metadata from a remote file (Disclosure: I created it). I has the same interface as MediaMetadataRetriever but it uses FFmpeg as it's backend. Here is an example:

FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
mmr.setDataSource(mUri);
String album = mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_ALBUM);
String artist = mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_ARTIST);
byte [] artwork = mmr.getEmbeddedPicture();
mmr.release();
like image 158
William Seemann Avatar answered Sep 19 '22 07:09

William Seemann