【问题标题】:Concatenating sound files on the iPhone (m4a) fails在 iPhone (m4a) 上连接声音文件失败
【发布时间】:2013-02-14 14:18:24
【问题描述】:

我正在尝试通过连接几个较小的声音文件来制作一个长声音文件 - 都是 m4a 格式,结果也应该是 m4a 格式。

这是代码(audFiles 数组包含要加入的声音文件的名称)。 注意我只打印文件大小是为了安心...

CMTime nextClipStartTime = kCMTimeZero;
AVMutableComposition *combinedSounds = [AVMutableComposition composition];
NSString *tempDir = NSTemporaryDirectory();
NSArray *audFiles;

for (int i = 0; i < [audFiles count]; i++)
{
    NSString *addSound = [tempDir stringByAppendingString:audFiles[i]];
    if ([[NSFileManager defaultManager] fileExistsAtPath:addSound] == YES)
    {
        NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:addSound error:nil];
        if (fileAttributes != nil)
        {
            NSString *fileSize = [fileAttributes objectForKey:NSFileSize];
            NSLog(@"file %@ %@", addSound, fileSize);
            NSURL *assetURL = [[NSURL alloc] initFileURLWithPath:addSound];

            AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:assetURL options:nil];
            if (asset != nil)
            {
                CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
                NSLog(@"asset %d length %lld", i, asset.duration.value);
                if (asset.duration.value > 0)
                {
                    AVAssetTrack *audTrack = [asset tracksWithMediaType:AVMediaTypeAudio][0];
                    AVMutableCompositionTrack *audioTrack = [combinedSounds addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
                    if ([audioTrack insertTimeRange:timeRange ofTrack:audTrack atTime:nextClipStartTime error:nil] == NO)
                    {
                        NSLog(@"insertTimeRange %d FAILED", i);
                    }
                    nextClipStartTime = CMTimeAdd(nextClipStartTime, asset.duration);
                    nextClipStartTime = CMTimeAdd(nextClipStartTime, CMTimeMake(0.1, 1));
                    NSLog(@"nextClipStartTime %lld", nextClipStartTime.value);
                }
            }
        }
    }
}

NSString *finalSound = [tempDir stringByAppendingString:@"result.m4a"];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:combinedSounds presetName:AVAssetExportPresetPassthrough];

 NSString *exported = [tempDir stringByAppendingString:finalSound];
[[NSFileManager defaultManager] removeItemAtPath:exported error:nil];
NSURL *exportedURL = [[NSURL alloc] initFileURLWithPath:exported];
exportSession.outputURL = exportedURL;
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.outputFileType = AVFileTypeAppleM4A;

[exportSession exportAsynchronouslyWithCompletionHandler:^{
    switch (exportSession.status)
    {
        case AVAssetExportSessionStatusFailed:
        {
            NSLog(@"exportSession FAIL");
            break;
        }
        case AVAssetExportSessionStatusCompleted:
        {
            NSLog(@"exportSession SUCCESS");
        }
    }
}];

报告“exportSession SUCCESS”,导出的文件存在,可以播放,但只包含第一个组成文件。

任何想法我做错了什么?

谢谢。

【问题讨论】:

    标签: iphone avassetexportsession


    【解决方案1】:

    Step 1 : 在您的项目中添加AVFoundation.FrameworkCoreMedia.Framework

    Step 2 : #import &lt;AVFoundation/AVFoundation.h&gt; 在您的 .h 文件中

    Step 3 :Write following method in your .m file

    Step 4 :Call this function from ViewDidAppear to create Merged Audio file.

    // Get Asset Detail
    - (AVAsset *)getAvAssetForFile:(NSString *)fileName andType:(NSString *)fileType
    {
        NSString *URLPath = [[NSBundle mainBundle] pathForResource:fileName ofType:fileType];
        NSURL *assetURL = [NSURL fileURLWithPath:URLPath];
        AVAsset *asset = [AVAsset assetWithURL:assetURL];
        return asset;
    }
    
    - (void)mergeAudioFiles
    {
        // `An Array with List of Audio Clips to be Merged, they could be of different type also`
        NSMutableArray *listOfAudio = [[NSMutableArray alloc] initWithCapacity:0];
    
        // `Create AVAsset Object from your audio files and add to array`
    
        [listOfAudio addObject:[self getAvAssetForFile:@"audioFile1" andType:@"caf"]];
        [listOfAudio addObject:[self getAvAssetForFile:@"audioFile2" andType:@"caf"]];
        [listOfAudio addObject:[self getAvAssetForFile:@"audioFile3" andType:@"aiff"]];
    
        AVMutableComposition *composition = [AVMutableComposition composition];
        CMTime current = kCMTimeZero;
        NSError *compositionError = nil;
        for(AVAsset *asset in listOfAudio) {
            BOOL result = [composition insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration])
                                               ofAsset:asset
                                                atTime:current
                                                 error:&compositionError];
            if(!result) {
                if(compositionError) {
                    // manage the composition error case                
                    NSLog(@"Error in Merging : %@",[compositionError debugDescription]);
                }
            } else {
                current = CMTimeAdd(current, [asset duration]);
            }
        }
    
        AVAssetExportSession *exporter = [[AVAssetExportSession alloc]
                                          initWithAsset: composition
                                          presetName: AVAssetExportPresetAppleM4A];
    
        exporter.outputFileType = @"com.apple.m4a-audio";
    
        // Set Output FileName
        NSString *fileName = @"myAudioTrack";
        NSString *exportFile = [DOC_DIR_PATH stringByAppendingFormat: @"/%@.m4a", fileName];
    
        // set up export
        NSURL *exportURL = [NSURL fileURLWithPath:exportFile];
        exporter.outputURL = exportURL;
    
        // do the export
        [exporter exportAsynchronouslyWithCompletionHandler:^{
            int exportStatus = exporter.status;
            switch (exportStatus) {
                case AVAssetExportSessionStatusFailed: NSLog (@"AVAssetExportSessionStatusFailed: %@", exporter.debugDescription); break;
                case AVAssetExportSessionStatusCompleted: NSLog (@"AVAssetExportSessionStatusCompleted"); break;
                case AVAssetExportSessionStatusUnknown: NSLog (@"AVAssetExportSessionStatusUnknown"); break;
                case AVAssetExportSessionStatusExporting: NSLog (@"AVAssetExportSessionStatusExporting"); break;
                case AVAssetExportSessionStatusCancelled: NSLog (@"AVAssetExportSessionStatusCancelled"); break;
                case AVAssetExportSessionStatusWaiting: NSLog (@"AVAssetExportSessionStatusWaiting"); break;
                default:  NSLog (@"didn't get export status"); break;
            }
        }];    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-03
      • 1970-01-01
      • 2016-04-15
      • 1970-01-01
      • 2011-02-04
      • 2014-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多