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

我正在尝试混合两个audio文件(将一个audio文件放在另一个上面 – 不是拼接在一起),但是我正在努力学习IOS上的AVFoundation。 我在这里遵循这个答案: 如何使用AVMutableCompositionTrack合并audio和video

这就是我所拥有的:

//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. 

我怀疑这是因为我正在加载.m4aaudio文件,而不是像StackOverflow原来的答案video文件的目的。 所以我的问题是如何混合两个独立的audio文件,并将它们保存为一个新的组合文件。 用途是我有一个支持轨道,用户logging自己的声音,然后可以混合他们的声音与支持轨道,并发送混合audio自己。

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

我张贴的代码,我最终上class,以防其他人正在尝试做同样的事情,并希望一些代码示例(我上面的问题,我怀疑audio文件没有被正确加载)

  [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"); }]; 

对于Swift 3

  showActivityIndicator() var composition = AVMutableComposition() var tracks: [Any] = ["backingTrack", "RobotR33"] var audioFileType: String = "wav" for trackName: String in tracks { var audioAsset = AVURLAsset(url: URL(fileURLWithPath: Bundle.main.path(forResource: trackName, ofType: audioFileType)), options: nil) var audioTrack: AVMutableCompositionTrack? = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid) var error: Error? try? audioTrack?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, audioAsset.duration), of: audioAsset.tracks(withMediaType: AVMediaTypeAudio)[0], atTime: kCMTimeZero) if error != nil { print("\(error?.localizedDescription)") } } var _assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) // Converted with Swiftify v1.0.6355 - https://objectivec2swift.com/ var mixedAudio: String = "mixedAudio.m4a" var exportPath: String = NSTemporaryDirectory() + (mixedAudio) var exportURL = URL(fileURLWithPath: exportPath) if FileManager.default.fileExists(atPath: exportPath) { try? FileManager.default.removeItem(atPath: exportPath) } assetExport.outputFileType = AVFileTypeAppleM4A assetExport.outputURL = exportURL assetExport.shouldOptimizeForNetworkUse = true assetExport.exportAsynchronously(withCompletionHandler: {() -> Void in self.hideActivityIndicator() print("Completed Sucessfully") })