Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: Get file's metadata

I have an mp3 file on a server. I want to get this file's information like what's the size of this file, what's the artists name, what's the album name, when was the file created, when was it modified, etc. I want all this information.

Is it possible to get this information without actually downloading the whole file? Using NSURLConnection or otherwise?

EDIT:

The following code doesn't give me the required information, i.e. file created by, artist name, etc

    NSError *rerror = nil;
    NSURLResponse *response = nil;

    NSURL *url = [NSURL URLWithString:@"http://link.to.mp3"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"HEAD"];

    NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&rerror];
    NSString *resultString = [[[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding] autorelease];

    NSLog(@"URL: %@", url);
    NSLog(@"Request: %@", request);
    NSLog(@"Result (NSData): %@", result);
    NSLog(@"Result (NSString): %@", resultString);
    NSLog(@"Response: %@", response);
    NSLog(@"Error: %@", rerror);

    if ([response isMemberOfClass:[NSHTTPURLResponse class]]) {
        NSLog(@"AllHeaderFields: %@", [((NSHTTPURLResponse *)response) allHeaderFields]);
    }

The "AllHeaderFields" is:

AllHeaderFields: {
    "Cache-Control" = "max-age=0";
    Connection = "keep-alive";
    "Content-Encoding" = gzip;
    "Content-Type" = "text/plain; charset=ascii";
    Date = "Fri, 17 Feb 2012 12:44:59 GMT";
    Etag = 19202n;
    Pragma = public;
    Server = dbws;
    "x-robots-tag" = "noindex,nofollow";
}
like image 710
Mustafa Avatar asked Feb 17 '12 12:02

Mustafa


1 Answers

It is quite possible to get the ID3 information embedded in an MP3 file (artist name, track title) without downloading the whole file or using low-level APIs. The functionality is part of the AVFoundation framework.

The class to look at is AVAsset and specifically it's network friendly subclass AVURLAsset. AVAsset has an NSArray property named commonMetadata. This commonMetadata property will contain instances of AVMetadataItem, assuming of course that the reference URL contains metadata. You will usually use the AVMetadataItem's commonKey property to reference the item. I find this method of iterating through an array checking commonKeys irritating so I create an NSDictionary using the commonKey property as the key and the value property as the object. Like so:

-(NSDictionary *)dictionaryOfMetadataFromAsset:(AVAsset *)asset{
    NSMutableDictionary *metaData = [[NSMutableDictionary alloc] init];
    for (AVMetadataItem *item in asset.commonMetadata) {
        if (item.value && item.commonKey){
            [metaData setObject:item.value forKey:item.commonKey];
        }
    }
    return [metaData copy];
}

With the addition of this simple method the AVAsset's metadata becomes quite easy to use. Here is an example of getting an MP3's metadata through a URL:

NSURL *mp3URL = [NSURL URLWithString:@"http://'AddressOfMP3File'"];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:mp3URL options:nil];
NSDictionary *metaDict = [self dictionaryOfMetadataFromAsset:asset];
NSLog(@"Available Metadata :%@",metaDict.allKeys);
NSLog(@"title:%@",[metaDict objectForKey:@"title"]);

I have found that this code seems to load just the first few seconds of your MP3 file. Also note that this code is synchronous; So use with caution. But AVURLAsset does have some async functionality described in the docs.

Once you have the AVAsset you can create a AVPlayerItem with it and feed that to an AVPlayer and play it, or not.

like image 81
NJones Avatar answered Nov 18 '22 18:11

NJones