About

This is the developer blog of Simon Wolf, Mac and iPhone developer, owner of Otter Software Ltd..

I am currently available for contract work so please get in touch to see if I can help you.

Twitter Accounts
« QuickTime Chapters | Main | Embedding Fonts in an Application »
Sunday
19Jul2009

Rename QuickTime Tracks

As a result of doing quite a bit of work with QuickTime and QTKit someone asked me if I had some sample code which would allow them to rename an audio track in a QuickTime file . I'd never actually done this but I decided to have a look into it and it turns out that it is pretty easy.

The code below will open a movie file, determine if there are any audio tracks and, if there are, it renames the first one and then exports the movie into a new file. Below the main block of code I've broken things down into segments and explained what is going on in a bit more detail.

Download the example project (a Foundation command-line project).

#import 
#import 

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSError * error = nil;
    NSString * filePath = [@"~/Desktop/test.m4v" stringByExpandingTildeInPath];
    
    NSLog(@"Loading source movie...");
    NSDictionary * initAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                     filePath, QTMovieFileNameAttribute,
                                     [NSNumber numberWithBool:NO], QTMovieOpenAsyncOKAttribute,
                                     nil];
    QTMovie * movie = [[QTMovie alloc] initWithAttributes:initAttributes error:&error];

    if (error) {
        NSLog(@"Unable to load the movie - %@", error);
        return 1;
    }

    NSLog(@"Finding audio tracks...");
    NSArray * trackList = [movie tracksOfMediaType:QTMediaTypeSound];
    if ([trackList count] > 0) {
        NSLog(@"Renaming first audio track...");
        QTTrack * targetTrack = [trackList objectAtIndex:0];
        [targetTrack setAttribute:@"MyNewName" forKey:QTTrackDisplayNameAttribute];
    } else {
        NSLog(@"No audio tracks found.");
        return 1;
    }
    
    NSLog(@"Re-exporting movie...");
    error = nil;
    NSString * saveFilePath = [@"~/Desktop/text_new.m4v" stringByExpandingTildeInPath];
    NSDictionary * saveAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                     [NSNumber numberWithBool:YES], QTMovieFlatten,
                                     nil];
    if (![movie writeToFile:saveFilePath withAttributes:saveAttributes error:&error]) {
        NSLog(@"Problem writing file.");
        if (error)
            NSLog(@"Error: %@", [error userInfo]);
        return 1;
    }

    NSLog(@"The movie file was saved successfully.");
    
    [pool drain];
    return 0;
}

Frameworks

This project needs the QTKit framework so if you get compilation errors the first thing to check is that it is included as an external framework.

Opening A QuickTime File

NSDictionary * initAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                 filePath, QTMovieFileNameAttribute,
                                 [NSNumber numberWithBool:NO], QTMovieOpenAsyncOKAttribute,
                                 nil];
QTMovie * movie = [[QTMovie alloc] initWithAttributes:initAttributes error:&error];

Note that the movie file is being opened synchronously which means that everything else is blocked until the movie has finished loading. This is not the preferred method (asynchronous loading and use of the QTMovieLoadStateDidChangeNotification notification is better) but it is the least amount of code for an example project like this.

As a slight aside, the QuickTime developers within Apple recommend that QuickTime files are opened using an attributes dictionary.

Finding The Required Track(s)

NSArray * trackList = [movie tracksOfMediaType:QTMediaTypeSound];
if ([trackList count] > 0) {
    NSLog(@"Renaming first audio track...");
    QTTrack * targetTrack = [trackList objectAtIndex:0];
    [targetTrack setAttribute:@"MyNewName" forKey:QTTrackDisplayNameAttribute];
} else {
    NSLog(@"No audio tracks found.");
    return 1;
}

This code is lazy but again the aim was to write fewer lines of code since this is an example project. There are a couple of ways to retrieve an array of tracks in a QTMovie file. The first is via the tracks method which returns an array of all tracks and the second is via the tracksOfMediaType: method. However there are quite a few media types you can use and some over-lap so you may be safer enumerating through all of the tracks rather than grabbing a specific sub-set unless your code is only going to apply to a specific QTMovie format.

The possible media types are:QTMediaTypeVideo, QTMediaTypeSound, QTMediaTypeText, QTMediaTypeBase, QTMediaTypeMPEG, QTMediaTypeMusic, QTMediaTypeTimeCode, QTMediaTypeSprite, QTMediaTypeFlash, QTMediaTypeMovie, QTMediaTypeTween, QTMediaType3D, QTMediaTypeSkin, QTMediaTypeQTVR, QTMediaTypeHint, QTMediaTypeStream, QTMediaTypeMuxed, QTMediaTypeQuartzComposer.

Renaming The Track

Actually renaming the track is achieved via the setAttribute:forKey: method using the QTTrackDisplayNameAttribute key.

Saving the Changes

Although the QTMovie object contains an updateMovieFile method, this only work on specific file types so it is safer to use the writeToFile:withAttributes:error: method:

NSString * saveFilePath = [@"~/Desktop/text_new.mov" stringByExpandingTildeInPath];
NSDictionary * saveAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], QTMovieFlatten,
                                 nil];
if (![movie writeToFile:saveFilePath withAttributes:saveAttributes error:&error]) {

Note the use of the QTMovieFlatten attribute. If this is not used QuickTime will try to create what is called a reference movie which means that the newly exported movie will not actually contain any of media that is in the original file but rather it will create a reference to it. This results in a very small file but is useless unless you have the original file to hand too.

Reader Comments (1)

The only downside to doing this is that it is necessary to flatten the movie (as you discuss).

Once you flatten a movie, load it into iTunes and modify any of the metadata. It takes AGES to save, because it needs to write out a flattened image again.

I don't have a solution, but it's worth noting.

January 25, 2010 | Unregistered CommenterScott

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>