首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在IOS上使用AVComposition混合两个音频文件

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

Stack Overflow用户
提问于 2014-09-16 15:41:50
回答 2查看 4.3K关注 0票数 1

我试图混合两个音频文件(将一个音频文件放在另一个音频文件之上,而不是拼接在一起),但我很难在IOS上学习AVFoundation。我在这里遵循了这个答案:How to merge Audio and video using AVMutableCompositionTrack

这就是我所拥有的

代码语言:javascript
复制
//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.  

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

谢谢你的建议。我发现AVFoundation非常令人生畏。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-09-16 22:18:50

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

代码语言:javascript
复制
 [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");
}];
票数 6
EN

Stack Overflow用户

发布于 2017-06-14 10:32:22

Swift 3 3

代码语言:javascript
复制
    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")
})
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25873061

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档