Reputation: 7976
I have been attempting to combine a video with background audio. I was able to create a video with 1 video and 1 audio file, (which I thankfully found on SO), but I am having difficulty extending it to use 2 or more audio files. The background audio can come from multiple files and I want to add them sequentially to the video.
Ex. audio-1.caf is 2 seconds long, audio-2.caf is 2 seconds long, video-1.mov is 4 seconds long.
I would like audio-1 to be at time interval 0-2 seconds and audio-2 to be at time interval 2-4 seconds. Unfortunately the code I have been creates a 2 second movie with the first audio-1 and the rest of the movie and audio are not included.
I simplified the problem down so I could ask for help here. The code below attempts to create a blank video with 2 audio sources. (My previous implementation was dynamic and looped through all audio sources)
-(void)writeAudio
{
AVMutableComposition* mixComposition = [AVMutableComposition composition];
NSDictionary * assetOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
NSString * outputFilePath = NSHomeDirectory();
outputFilePath = [outputFilePath stringByAppendingPathComponent:@"Library"];
outputFilePath = [outputFilePath stringByAppendingPathComponent:@"temp.mov"];
NSURL * outputFileUrl = [NSURL fileURLWithPath:outputFilePath];
[[NSFileManager defaultManager] removeItemAtURL:outputFileUrl error:nil];
CMTime nextClipStartTime = kCMTimeZero;
NSURL * audioURL /* = kSomeValidURL */;
NSURL * audio2URL /* = kSomeOtherValidURL */;
AVURLAsset* audioAsset = [[AVURLAsset alloc] initWithURL:audioURL options:assetOptions];
CMTimeRange audio_timeRange = CMTimeRangeMake(nextClipStartTime, audioAsset.duration);
AVMutableCompositionTrack *b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[b_compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:nextClipStartTime error:nil];
nextClipStartTime = CMTimeAdd(nextClipStartTime, audio_timeRange.duration);
AVURLAsset* audio2Asset = [[AVURLAsset alloc] initWithURL:audio2URL options:assetOptions];
CMTimeRange audio2_timeRange = CMTimeRangeMake(nextClipStartTime, audio2Asset.duration);
AVMutableCompositionTrack *b_compositionAudio2Track = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[b_compositionAudio2Track insertTimeRange:audio2_timeRange ofTrack:[[audio2Asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:nextClipStartTime error:nil];
nextClipStartTime = CMTimeAdd(nextClipStartTime, audio2_timeRange.duration);
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
_assetExport.outputFileType = @"com.apple.quicktime-movie";
_assetExport.outputURL = outputFileUrl;
[_assetExport exportAsynchronouslyWithCompletionHandler:
^(void ) {
NSLog(@"audio was completed???");
}
];
}
The problem remains the same, the new video consists of the first audioURL's contents and is the duration of the first audioURL's contents.
Upvotes: 1
Views: 1322
Reputation: 7976
My issue stemmed from not understanding the AVFoundation fully (I still don't).
My time intervals, still need to start at 0 and last the durations of the audio assets, then be inserted at the time I want them to start at.
I changed the code that initializes the audio_timeRanges.
From
CMTimeRange audio_timeRange = CMTimeRangeMake(nextClipStartTime, audioAsset.duration);
To
CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration);
and From
CMTimeRange audio2_timeRange = CMTimeRangeMake(nextClipStartTime, audio2Asset.duration);
To
CMTimeRange audio2_timeRange = CMTimeRangeMake(kCMTimeZero, audio2Asset.duration);
Upvotes: 1