ios - AVAssetWriter 从 AVAsset 转换 aac 5.1 音轨在 appendSampleBuffer 上失败

标签 ios objective-c avfoundation avassetwriter avassetwriterinput

我正在尝试从 .mp4 视频文件中提取音轨,并使用 使用此 outputSettings 转换为 .m4a 音频文件AVAssetWriter

AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;

NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
                                [NSNumber numberWithFloat:44100.0], AVSampleRateKey,
                                [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
                                [NSNumber numberWithInt:128000], AVEncoderBitRateKey, // 128 kbps
                                [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
                                nil];

案例 1: 带有音轨参数的 .mp4 视频文件(使用 CMFormatDescriptionRef 打印):

mediaType:'soun'
mediaSubType:'aac '
mSampleRate: 44100.000000
mFormatID: 'aac '
mChannelsPerFrame: 2
ACL: {Stereo (L R)}

结果:成功创建具有已定义输出参数的.m4a输出文件

案例 2: 带有音轨参数的 .mp4 视频文件(使用 CMFormatDescriptionRef 打印):

mediaType:'soun'
mediaSubType:'aac ' 
mSampleRate: 48000.000000
mFormatID: 'aac '
mChannelsPerFrame: 6
ACL: {5.1 (C L R Ls Rs LFE)}

结果转换失败,当添加示例缓冲区[AVAssetWriter appendSampleBuffer: ...] 时出现未知错误:

Error Domain: NSOSStatusErrorDomain
code: -12780
description: The operation could not be completed

为了将视频转换为音频,我使用了此处描述的相同算法:https://github.com/rs/SDAVAssetExportSession/blob/master/SDAVAssetExportSession.m

我还尝试使用 kAudioChannelLayoutTag_MPEG_5_1_D 设置 channelLayout.mChannelLayoutTag,并使用 6 值更新 AVNumberOfChannelsKey,但是它对我不起作用。

任何人都可以帮助我理解我做错了什么吗?可能没有仅使用 iOS AVFoundation 框架来执行此任务的解决方案吗?我应该为 5.1 aac 6 声道的音轨使用不同的 outputParams 吗?

最佳答案

我还没有尝试过使用 5.1 音频,但是当从视频中提取音频时,我喜欢在纯音频 AVMutableComposition 上使用直通 AVAssetExportSession,因为这样可以避免转码这会很慢并且会降低音频质量。像这样的东西:

AVMutableComposition*       newAudioAsset = [AVMutableComposition composition];
AVMutableCompositionTrack*  dstCompositionTrack;

dstCompositionTrack = [newAudioAsset addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];


AVAsset*        srcAsset = [AVURLAsset URLAssetWithURL:srcURL options:nil];
AVAssetTrack*   srcTrack = [[srcAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];


CMTimeRange timeRange = srcTrack.timeRange;//CMTimeRangeMake(kCMTimeZero, srcAsset.duration);

NSError*    error;

if(NO == [dstCompositionTrack insertTimeRange:timeRange ofTrack:srcTrack atTime:kCMTimeZero error:&error]) {
    NSLog(@"track insert failed: %@\n", error);
    return 1;
}


__block AVAssetExportSession*   exportSesh = [[AVAssetExportSession alloc] initWithAsset:newAudioAsset presetName:AVAssetExportPresetPassthrough];

exportSesh.outputFileType = AVFileTypeAppleM4A;
exportSesh.outputURL = dstURL;

[exportSesh exportAsynchronouslyWithCompletionHandler:^{
    AVAssetExportSessionStatus  status = exportSesh.status;
    NSLog(@"exportAsynchronouslyWithCompletionHandler: %i\n", status);

    if(AVAssetExportSessionStatusFailed == status) {
        NSLog(@"FAILURE: %@\n", exportSesh.error);
    } else if(AVAssetExportSessionStatusCompleted == status) {
        NSLog(@"SUCCESS!\n");
    }
}];

我手头没有任何 5.1 文件,所以如果这不起作用,您可能需要更仔细地查看该行

AVAssetTrack*   srcTrack = [[srcAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

附注这段 2012 年的代码“刚刚好用”,这很好。

关于ios - AVAssetWriter 从 AVAsset 转换 aac 5.1 音轨在 appendSampleBuffer 上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46669257/

相关文章:

ios - AVCaptureVideoDataOutput P3 色彩空间

iphone - 如何在 iPhone 中将 NSString 值与 NSMutableDictionary 键进行比较?

ios - 加速度计数据不正确,延迟了几秒钟

java - 在Android中实现类似iOS的时间选择器

ios - 调试器只显示字典的值和键的 "(no summary)"

ios - 为什么我的 JSON 响应对象没有加载到字典中?

ios - 为什么我不能将 WKWebView 保存到 [NSUserDefaults standardUserDefaults]?

swift - 修改 AVCaptureStillImageOutput 为 AVCapturePhotoOutput

iphone - AVCapture追加SampleBuffer

ios - Finch 可以播放内存中 NSData 中的声音吗?