在 IOS 上使用 AVComposition 混合两个音频文件

Lin*_*ing 1 audio avfoundation ios

我正在尝试混合两个音频文件(将一个音频文件放在另一个文件上 - 没有拼接在一起),但我正在努力学习 IOS 上的 AVFoundation。我在这里遵循了这个答案:如何使用 AVMutableCompositionTrack 合并音频和视频

这就是我所拥有的:

//NSURL *audioFilePath = [NSURL fileURLWithPath:@"var/mobile/Applications/822732B6-67B9-485F-BA44-FAACAB34C4FD/Documents/Coisir Cheoil10_09_2014_1429.m4a"];
NSURL *audioUrl = [NSURL fileURLWithPath:@"var/mobile/Applications/822732B6-67B9-485F-BA44-FAACAB34C4FD/Documents/Robot R-3-311_09_2014_2252.m4a"];
// need to fix link to backing Track
NSURL *backingTrackURL = [NSURL fileURLWithPath:@"var/mobile/Applications/822732B6-67B9-485F-BA44-FAACAB34C4FD/Documents/Robot R-3-316_09_2014_1559.m4a"];// need ot fix the link to this
AVURLAsset* backingTrack = [[AVURLAsset alloc] initWithURL:audioUrl options:nil];
AVURLAsset* voiceTrack = [[AVURLAsset alloc] initWithURL:backingTrackURL options:nil];

AVMutableComposition* mixComposition = [AVMutableComposition composition];

AVMutableCompositionTrack *compositionCommentaryTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];


[compositionCommentaryTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, backingTrack.duration)
                                    ofTrack:[[backingTrack tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0]
                                     atTime:kCMTimeZero
                                      error:nil];

AVMutableCompositionTrack *compositionVoiceTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];

[compositionVoiceTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, voiceTrack.duration)
                               ofTrack:[[voiceTrack tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0] atTime:kCMTimeZero error:nil];

AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];

NSString* mixedAudio = @"mixedAudio.m4a";

NSString *exportPath = [NSTemporaryDirectory() stringByAppendingString:mixedAudio];
NSURL *exportURL = [NSURL fileURLWithPath:exportPath];

if ([[NSFileManager defaultManager]fileExistsAtPath:exportPath]) {
    [[NSFileManager defaultManager]removeItemAtPath:exportPath error:nil];
}
_assetExport.outputFileType = @"m4a";
_assetExport.outputURL = exportURL;
_assetExport.shouldOptimizeForNetworkUse = YES;

[_assetExport exportAsynchronouslyWithCompletionHandler:^{
    NSLog(@"Completed Sucessfully");
}];

The code fails when I try to set the timeranges with an error index 0 beyond bounds for empty array.  I take it that backing track does not include tracksWithMediaTye:AvMediaTypeAudio and that is why that fails.  
Run Code Online (Sandbox Code Playgroud)

我怀疑这是因为我加载的是 .m4a 音频文件,而不是像 StackOverflow 上的原始答案那样的视频文件。所以我的问题是如何混合两个单独的音频文件并将它们保存为一个新的组合文件。用途是我有一个背景音轨,用户录制自己的人声,然后可以将他们的人声与背景音轨混合并将混合音频发送给自己。

感谢您的任何建议。我发现 AVFoundation 非常令人生畏。

Lin*_*ing 6

我正在发布我最终开始工作的代码,以防其他人试图做同样的事情并想要一些代码示例(我上面的问题我怀疑是音频文件没有正确加载)

 [self showActivityIndicator]; // This code takes a while so show the user an activity Indicator
AVMutableComposition *composition = [AVMutableComposition composition];
NSArray* tracks = [NSArray arrayWithObjects:@"backingTrack", @"RobotR33", nil];
NSString* audioFileType = @"wav";

for (NSString* trackName in tracks) {
    AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:trackName ofType:audioFileType]]options:nil];

    AVMutableCompositionTrack* audioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                     preferredTrackID:kCMPersistentTrackID_Invalid];

    NSError* error;
    [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0] atTime:kCMTimeZero error:&error];
    if (error)
    {
        NSLog(@"%@", [error localizedDescription]);
    }
}
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetAppleM4A];

NSString* mixedAudio = @"mixedAudio.m4a";

NSString *exportPath = [NSTemporaryDirectory() stringByAppendingString:mixedAudio];
NSURL *exportURL = [NSURL fileURLWithPath:exportPath];

if ([[NSFileManager defaultManager]fileExistsAtPath:exportPath]) {
    [[NSFileManager defaultManager]removeItemAtPath:exportPath error:nil];
}
_assetExport.outputFileType = AVFileTypeAppleM4A;
_assetExport.outputURL = exportURL;
_assetExport.shouldOptimizeForNetworkUse = YES;

[_assetExport exportAsynchronouslyWithCompletionHandler:^{
    [self hideActivityIndicator];
    NSLog(@"Completed Sucessfully");
}];
Run Code Online (Sandbox Code Playgroud)