Get metadata from audiostream using MPMoviePlayerController

The case:

You have an audio stream from server streaming music to the Internet. You also know that there are metadata sent to the player. The thing is… How to display these metadata to the iPhone or iPad app UI?

First things first:

The simplest implementation is the iOS MPMoviePlayerController framework (although the name implies video stream, it can capture audio-only streams as well). This will allow you to receive the audio stream, play it and (of course) display the metadata.

Another way to play audio streams is to capture standard network packet and use the iOS  AVFoundation Framework.

Using MPMoviePlayerController over AV/network packet has its pros and cons. Less code, less complexity, fast results go to the pros but there are some catches…

MPMoviePlayerController supports only MP3 and AAC audio streams. Real Audio, Windows Media and other formats are not supported and this is done because MP complies and is flexible with the Shoutcast and Icecast broadcast servers (which by the way are the majority of streams on the Internet).

After this introduction, in this post I will focus mainly on getting metadata from a MPMoviePlayerController.

Assuming that you have already set up the MPMoviePlayerController and you already know what kind of metadata is being sent in the stream (if you don’t, use a media player like VLC to check), you must first register an iOS notification to get the metadata in timed intervals (aka when the stream starts or a track begins) and then a method to process them.

Step 1:

Starting with the notification, just insert:

[[NSNotificationCenter defaultCenter] 
    selector:@selector(MetadataUpdate:) // I just name it MetadataUpdate... you name it as you like

right after the MPMoviePlayerController allocation. Then…

Step 2:

Implementing the MetadataUpdate method:

- (void)MetadataUpdate:(NSNotification*)notification
 if ([streamAudioPlayer timedMetadata]!=nil && [[streamAudioPlayer timedMetadata] count] > 0) {
     MPTimedMetadata *firstMeta = [[streamAudioPlayer timedMetadata] objectAtIndex:0];
     metadataInfo = firstMeta.value;

(where streamAudioplayer is your MPMoviePlayerController and metadataInfo a NSString to store the value)

The  [streamAudioPlayer timedMetadata] is a NSArray containing data objects that can retrieved with their properties. These properties include a value (the Artist/Track info string), a timestamp, a key and a keycode. There can be multiple data objects depending on what information the server broadcasts (usually the object at index 0 is the one mainly used).

The above example will get the Artist and Track info of the currently playing song. This comes as a single string in the format (Artist) – (Track Name) exactly as it is broadcasted from the streaming server. If you want to break this into different objects, simply grab what is before of {space}{dash}{space} ( – ) for Artist and what comes after for Track Name.

Note that each stream may handle and send different metadata.

Since the [streamAudioPlayer timedMetadata] is a NSArray containing all metadata broadcasted from the server, if you want to peek into the other data, treat  [streamAudioPlayer timedMetadata] as an array and display all objects:

NSArray *metaArray = [streamAudioPlayer timedMetadata];
NSLog (@"Total objects in metadata array: %i", [metaArray count]); //to get the total count of objects
MPTimedMetadata *firstMeta = [[streamAudioPlayer timedMetadata] objectAtIndex:0];
MPTimedMetadata *secMeta = [[streamAudioPlayer timedMetadata] objectAtIndex:1];
NSLog (@"Meta Property with value: %@ and key: %@ and keyspace: %@ and timestamp: %f", firstMeta.value, firstMeta.key, firstMeta.keyspace, firstMeta.timestamp);
NSLog (@"Meta Property with value: %@ and key: %@ and keyspace: %@ and timestamp: %f", secMeta.value, secMeta.key, secMeta.keyspace, secMeta.timestamp);

Use then the console to show the content of metadata for the key, keyspace, timestamp, value properties.

If you want a more detailed approach and information, always remember to check the official MPTimedMetadata class reference, found at Apple Developer Documentation and from there… code on!