Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add audio file contents in movie using AVFoundation on iOS4?

I am using AVFoundation to create a movie file (mp4) using images and sound files.

I have successfully created movie file using AVAssetWriterInputPixelBufferAdaptor which appends CVPixelBufferRef (exracted from UIImage objects) in movie file.

Now, I want to add audio contents from a file in that movie. Fetching data from device microphone is not what I am thinking here. And, I could not find anything similar to AVAssetWriterInputPixelBufferAdaptor which can help writing audio data into that movie file.

Am I missing something here?

like image 310
Imran Raheem Avatar asked Feb 23 '11 10:02

Imran Raheem


2 Answers

At least for me the solution was to use AVMutableComposition class.

1) create AVMutableComposition class object
2) create 2 AVURLAsset class objects, the first based on your video file, and the second based on a file that you want to extract audio track from
3) create 2 AVMutableCompositionTrack class objects, like before one with audio track, the second one with video track(based on appropriate assets objects from 2))
4) create AVAssetExportSession class based on composition object from 1)
5) export your session

Best regards

like image 62
peter Avatar answered Nov 01 '22 20:11

peter


Thank @peter. Here is solution in code.

-(BOOL)compositeVideo{
    //Record cur video
    NSURL *curAudio = [[NSBundle mainBundle]URLForResource:@"a" withExtension:@".pcm"];
    NSURL *curVideo = [[NSBundle mainBundle]URLForResource:@"v" withExtension:@".mp4"];
    AVAsset *video = [AVAsset assetWithURL:curVideo];
    AVAsset *audio = [AVAsset assetWithURL:curAudio];
    AVAssetTrack *vTrack = [[video tracksWithMediaType:AVMediaTypeVideo] firstObject];
    NSArray *arr = [audio tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack *aTrack = [arr firstObject];

    AVMutableComposition *composition = [AVMutableComposition composition];
    AVMutableCompositionTrack *visualTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:1];
    AVMutableCompositionTrack *audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    NSError *error;
    [visualTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, video.duration) ofTrack:vTrack atTime:kCMTimeZero error:&error];
    if (error) {
        NSLog(@"video composition failed! error:%@", error);
        return NO;
    }
    [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audio.duration) ofTrack:aTrack atTime:kCMTimeZero error:&error];
    if (error) {
        NSLog(@"audio composition failed! error:%@", error);
        return NO;
    }

    AVAssetExportSession *exporter = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    exporter.outputURL = [NSURL fileURLWithPath:[path stringByAppendingPathComponent:@"compositedVideo.mp4"]];
    [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
    exporter.outputFileType = AVFileTypeQuickTimeMovie;
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        if (exporter.error) {
            NSLog(@"exporter synthesization failed! error:%@", error);
            [self.delegate compositeDidFinishAtURL:nil duration:-1];
        }else{
            [self.delegate compositeDidFinishAtURL:exporter.outputURL duration:CMTimeGetSeconds(video.duration)];
        }
    }];
    return YES;
}
like image 45
ooOlly Avatar answered Nov 01 '22 20:11

ooOlly