I want to concatenate two audio files into one. I had done following code. Please check below.
- (BOOL)combineFiles{
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack setPreferredVolume:0.8];
NSString *soundOne =[[NSBundle mainBundle]pathForResource:@"test1" ofType:@"m4a"];
NSURL *url = [NSURL fileURLWithPath:soundOne];
AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack1 setPreferredVolume:0.8];
NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:@"test2" ofType:@"m4a"];
NSURL *url1 = [NSURL fileURLWithPath:soundOne1];
AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil];
AVAssetTrack *clipAudioTrack1 = [[avAsset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack1 atTime:kCMTimeZero error:nil];
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetAppleM4A];
if (nil == exportSession) return NO;
exportSession.outputURL = [NSURL fileURLWithPath:[@"test3.m4a" documentDirectory]]; // output path
exportSession.outputFileType = AVFileTypeAppleM4A; // output file type
// perform the export
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (AVAssetExportSessionStatusCompleted == exportSession.status) {
NSLog(@"AVAssetExportSessionStatusCompleted");
} else if (AVAssetExportSessionStatusFailed == exportSession.status) {
NSLog(@"AVAssetExportSessionStatusFailed");
} else {
NSLog(@"Export Session Status: %ld", (long)exportSession.status);
}
}];
return YES;
}
From above code we can combine two audio files into one, where both files play simultaneously. But I want the third file to play the first two files one after the other.
Please help me to solve this problem.
Select your audio files to merge. (Keyboard hotkeys Ctrl + Shift and click on the your favored songs.) Step 3. Right-click on each song > choose Get Info in the drop-down list > choose the Options tab > check Part of a compilation and Gapless album boxes > click on the OK button.
After doing much research I found answer.. It works..
- (void)mergeTwoAudioFiles{
AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test1" ofType:@"m4a"]] options:nil];
AVAsset *avAsset2 = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test2" ofType:@"m4a"]] options:nil];
AVMutableComposition *composition = [[AVMutableComposition alloc] init];
[composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
AVAssetTrack *assetTrack1 = [[avAsset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
AVAssetTrack *assetTrack2 = [[avAsset2 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
CMTime insertionPoint = kCMTimeZero;
[track insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset1.duration) ofTrack:assetTrack1 atTime:insertionPoint error:nil];
insertionPoint = CMTimeAdd(insertionPoint, avAsset1.duration);
[track insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset2.duration) ofTrack:assetTrack2 atTime:insertionPoint error:nil];
AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetAppleM4A];
exportSession.outputURL = [NSURL fileURLWithPath:[@"test3.m4a" documentDirectory]];
exportSession.outputFileType = AVFileTypeAppleM4A;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (AVAssetExportSessionStatusCompleted == exportSession.status) {
NSLog(@"AVAssetExportSessionStatusCompleted");
} else if (AVAssetExportSessionStatusFailed == exportSession.status) {
NSLog(@"AVAssetExportSessionStatusFailed");
} else {
NSLog(@"Export Session Status: %ld", (long)exportSession.status);
}
}];
}
I've worked on a similar project before, and I'm pulling out this code from there. In that project I concatenate between 1 and 160 sounds one after another, and this code works.
AVMutableComposition *composition = [AVMutableComposition composition];
NSMutableArray* audioMixParams = [[NSMutableArray alloc] init]; //Audio mixing parameters
AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; //you can choose your file format here, I chose mp3
[self setUpAndAddAudioAtPath:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:test1 ofType:@"m4a"]] toComposition:composition atStartTime:[composition duration];
[self setUpAndAddAudioAtPath:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:test2 ofType:@"m4a"]] toComposition:composition atStartTime:[composition duration];
AVMutableAudioMixInputParameters *trackMix = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track];
[trackMix setVolume:0.8f atTime:CMTimeMake(0, 1)];
[audioMixParams addObject:trackMix];
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
audioMix.inputParameters = [NSArray arrayWithArray:audioMixParams];
NSLog (@"compatible presets for songAsset: %@",
[AVAssetExportSession exportPresetsCompatibleWithAsset:composition]);
AVAssetExportSession *exporter = [[AVAssetExportSession alloc]
initWithAsset: composition
presetName: AVAssetExportPresetAppleM4A];
exporter.audioMix = audioMix;
exporter.outputFileType = @"com.apple.m4a-audio";
NSURL *exportURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/test.m4a",docDir]];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:[docDir stringByAppendingPathComponent:@"test.m4a"] error:NULL];
exporter.outputURL = exportURL;
[exporter exportAsynchronouslyWithCompletionHandler:^{
int exportStatus = exporter.status;
switch (exportStatus) {
case AVAssetExportSessionStatusFailed:
NSLog(@"AVAssetExportSessionStatusFailed");
break;
case AVAssetExportSessionStatusCompleted: {
NSLog (@"AVAssetExportSessionStatusCompleted");
break;
}
case AVAssetExportSessionStatusUnknown: NSLog (@"AVAssetExportSessionStatusUnknown"); break;
case AVAssetExportSessionStatusExporting: {
dispatch_async(dispatch_get_main_queue(), ^{
});
NSLog (@"AVAssetExportSessionStatusExporting");
break;
}
case AVAssetExportSessionStatusCancelled: NSLog (@"AVAssetExportSessionStatusCancelled"); break;
case AVAssetExportSessionStatusWaiting: NSLog (@"AVAssetExportSessionStatusWaiting"); break;
default: NSLog (@"didn't get export status"); break;
}
}];
I wrote a special function to add track at given position, given below:
- (void) setUpAndAddAudioAtPath:(NSURL*)assetURL toComposition:(AVMutableComposition *)composition atStartTime: (CMTime) startTime{
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
CMTime trackDuration = songAsset.duration;
AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
AVAssetTrack *sourceAudioTrack = [[songAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
NSError *error = nil;
BOOL ok = NO;
//CMTime longestTime = CMTimeMake(848896, 44100); //(19.24 seconds)
CMTimeRange tRange = CMTimeRangeMake(CMTimeMake(0, 1), trackDuration);
//NSLog(@"Note Duration = %f", CMTimeGetSeconds(trackDuration));
//Set Volume
AVMutableAudioMixInputParameters *trackMix = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track];
[trackMix setVolume:0.8f atTime:startTime];
[self.audioMixParams addObject:trackMix];
//Insert audio into track
ok = [track insertTimeRange:tRange ofTrack:sourceAudioTrack atTime:startTime error:&error];
//NSLog(@"%d",ok);
}
This code worked for me, AS-IS. Please let me know if this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With