I am trying to extract audio track from .mp4
video file and convert to .m4a
audio file with this outputSettings
using AVAssetWriter
class
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];
Case 1: .mp4 video file with audio track params (print with CMFormatDescriptionRef
):
mediaType:'soun'
mediaSubType:'aac '
mSampleRate: 44100.000000
mFormatID: 'aac '
mChannelsPerFrame: 2
ACL: {Stereo (L R)}
result: successfully create .m4a
output file with defined output params
Case 2: .mp4 video file with audio track params(print with CMFormatDescriptionRef
):
mediaType:'soun'
mediaSubType:'aac '
mSampleRate: 48000.000000
mFormatID: 'aac '
mChannelsPerFrame: 6
ACL: {5.1 (C L R Ls Rs LFE)}
result: convert fails, when adding sample buffer [AVAssetWriter appendSampleBuffer: ...]
with unknown error
:
Error Domain: NSOSStatusErrorDomain
code: -12780
description: The operation could not be completed
To convert video to audio I use the same algorithm as described there: https://github.com/rs/SDAVAssetExportSession/blob/master/SDAVAssetExportSession.m
Also I tried to setup channelLayout.mChannelLayoutTag
with kAudioChannelLayoutTag_MPEG_5_1_D
, and update AVNumberOfChannelsKey
with 6
value, but it doesn't work for me.
Can anyone help me to understand what I am doing wrong? May be there are no solution to perform this task using only iOS AVFoundation framework? Should I use different outputParams
for audio track with 5.1 aac 6 channels?
I haven't tried this with 5.1 audio, but when extracting audio from video I like to use a passthrough AVAssetExportSession
on an audio-only AVMutableComposition
as this avoids transcoding which would be slow and throw away audio quality. Something like:
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");
}
}];
I don't have any 5.1 files on hand, so if that doesn't work you may need to look more closely at the line
AVAssetTrack* srcTrack = [[srcAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
ps this code from 2012 "just worked", which was nice.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.