Alberto
Alberto

Reputation: 4282

Merge two videos without ffmpeg (Cocoa)

I've looked and looked for an answer, but can't seem to find one. Lots have asked, but none have gotten answers. I have an app that have two video paths. Now I just want to merge them into one file that can be saved in a ".mov" format. Does anyone have any clue as to how this can be done?

Note : I want to to this without installing and obviously using ffmpeg.

Please if you have time, some code would be very helpful.

Upvotes: 1

Views: 1127

Answers (1)

VsSoft
VsSoft

Reputation: 288

First, obviously you need to make sure that the movie type is readable/playable by the quicktime libraries.

But, assuming that's the case, the procedure is basically like this: Get a pointer to some memory to store the data:

QTMovie *myCombinedMovie = [[QTMovie alloc] initToWritableData:[NSMutableData data] error:nil];

Next, grab the first movie that you want to use and insert it into myCombinedMovie You can have the parts you want combined in an array and enumerate over them to combine as many parts as you like. Also, if you wanted, you could alter destination range to add an offset:

QTMovie *firstMovie = [QTMovie movieWithURL:firstURL error:nil];
// NOTE THAT THE 3 LINES BELOW WERE CHANGED FROM MY ORIGINAL POST!
QTTimeRange timeRange = QTMakeTimeRange(QTZeroTime, [firstMovie duration]);
QTTime insertionTime = [myCombinedMovie duration];
[myCombinedMovie insertSegmentOfMovie:firstMovie timeRange:timeRange atTime:insertionTime];

Rinse and repeat for the second movie part.

Then, output the flattened movie (flattening makes it self-contained):

NSDictionary *writeAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], QTMovieFlatten, nil]; //note that you can add a QTMovieExport key with an appropriate value here to export as a specific type
[myCombinedMovie writeToFile:destinationPath withAttributes:writeAttributes];

EDITED: I edited the above as insertion times were calculating wrong. This way seems easier. Below is the code all together as one, including enumerating through an array of movies and lots of error logging.

NSError *err = nil;
QTMovie *myCombinedMovie = [[QTMovie alloc] initToWritableData:[NSMutableData data] error:&err];
if (err)
{
    NSLog(@"Error creating myCombinedMovie: %@", [err localizedDescription]);
    return;
}

NSArray *myMovieURLs = [NSArray arrayWithObjects:[NSURL fileURLWithPath:@"/path/to/the/firstmovie.mov"], [NSURL fileURLWithPath:@"/path/to/the/secondmovie.mov"], nil];

for (NSURL *url in myMovieURLs)
{
    QTMovie *theMovie = [QTMovie movieWithURL:url error:&err];
    if (err){
        NSLog(@"Error loading one of the movies: %@", [err localizedDescription]);
        return;
    }
    QTTimeRange timeRange = QTMakeTimeRange(QTZeroTime, [theMovie duration]);
    QTTime insertionTime = [myCombinedMovie duration]; 
    [myCombinedMovie insertSegmentOfMovie:theMovie timeRange:timeRange atTime:insertionTime];
}

NSDictionary *writeAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], QTMovieFlatten, nil]; 
bool success = [myCombinedMovie writeToFile:@"/path/to/outputmovie.mov" withAttributes:writeAttributes error:&err];
if (!success)
{
    NSLog(@"Error writing movie: %@", [err localizedDescription]);
    return;
}

Upvotes: 4

Related Questions