如何使用 AVAssetReader 和 AVAssetWriter 创建 AAC 文件?
Posted
技术标签:
【中文标题】如何使用 AVAssetReader 和 AVAssetWriter 创建 AAC 文件?【英文标题】:How can I use AVAssetReader and AVAssetWriter to create a AAC file? 【发布时间】:2011-12-18 13:44:39 【问题描述】:大家! 我正在处理一个应用程序。它可以录制音频文件并发送给其他人。音频文件保存为(.aac)文件。然后我想继续录制我已经保存为.aac文件的录音。所以我用AVAssetReader 和 AVAssetWriter 成功了。但我失败了!以下是我的代码:
AVMutableComposition *mixComposition = [AVMutableComposition composition];
NSURL *url = [NSURL fileURLWithPath:[DOCUMENTS_FOLDER stringByAppendingPathComponent:buttonTitle]];
NSURL *anotherUrl = [NSURL fileURLWithPath:[DOCUMENTS_FOLDER stringByAppendingPathComponent:[fileList objectAtIndex:0]]];
CMTime nextClipStartTime = kCMTimeZero;
AVURLAsset *preAudioAsset = [[AVURLAsset alloc]initWithURL:url options:nil];
CMTimeRange preTimeRange = CMTimeRangeMake(kCMTimeZero, preAudioAsset.duration);
AVMutableCompositionTrack *preCompositonTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[preCompositonTrack insertTimeRange:preTimeRange ofTrack:[[preAudioAsset tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0] atTime:nextClipStartTime error:nil];
nextClipStartTime = CMTimeAdd(nextClipStartTime, preAudioAsset.duration);
AVURLAsset *cruAudioAsset = [[AVURLAsset alloc]initWithURL:anotherUrl options:nil];
CMTimeRange cruTimeRange = CMTimeRangeMake(kCMTimeZero, cruAudioAsset.duration);
[preCompositonTrack insertTimeRange:cruTimeRange ofTrack:[[cruAudioAsset tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0] atTime:nextClipStartTime error:nil];
//AVAssetReader part
NSError *error;
AVAssetReader *assetReader = [[AVAssetReader assetReaderWithAsset:mixComposition error:&error]retain];
if(error)
NSLog(@"error:%@",error);
AVAssetTrack *audioTrack = [[mixComposition.tracks objectAtIndex:0]retain];
AVAssetReaderOutput *assetReaderOutput =[[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:nil]retain];
if(![assetReader canAddOutput:assetReaderOutput])
NSLog(@"Can't add output!");
return;
[assetReader addOutput:assetReaderOutput];
NSURL *exportUrl = [NSURL fileURLWithPath:[DOCUMENTS_FOLDER stringByAppendingPathComponent:@"combine.aac"]];
//AVAssetWriter part
AVAssetWriter *assetWriter = [[AVAssetWriter assetWriterWithURL:exportUrl fileType:AVFileTypeMPEG4 error:&error]retain];
if(error)
NSLog(@"error:%@",error);
return;
AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[ NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
[ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey,
[ NSNumber numberWithFloat: 44100.0 ], AVSampleRateKey,
[ NSData dataWithBytes: &channelLayout length: sizeof( AudioChannelLayout ) ], AVChannelLayoutKey,
[ NSNumber numberWithInt: 64000 ], AVEncoderBitRateKey,
nil];
AVAssetWriterInput *assetWriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:outputSettings]retain];
if([assetWriter canAddInput:assetWriterInput])
[assetWriter addInput:assetWriterInput];
else
NSLog(@"can't add asset writer input .....");
return;
assetWriterInput.expectsMediaDataInRealTime = NO;
[assetWriter startWriting];
[assetReader startReading];
CMTime startTime = CMTimeMake(0, audioTrack.naturalTimeScale);
[assetWriter startSessionAtSourceTime:startTime];
dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue",NULL);
[assetWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^
while(assetWriterInput.readyForMoreMediaData)
CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer];
if(nextBuffer)
//append buffer
[assetWriterInput appendSampleBuffer:nextBuffer];
else
[assetWriterInput markAsFinished];
[assetWriter finishWriting];
[assetReader cancelReading];
[assetReader release];
[assetReaderOutput release];
[assetWriter release];
[assetWriterInput release];
break;
];
我只想记录另一个文件,然后将后面的附加到前面,但是出现错误:-[AVAssetWriterInput appendSampleBuffer:] input buffer must be in linear PCM format when outputSettings is not nil'
我想问我采取的方法对吗?如果我把它变成PCM格式(.wav)它很好,但是录制文件的大小太大了。如何解决上面提到的错误。我该如何解决 通过代码将 .wav 转换为 .aac 文件?求救!
【问题讨论】:
您找到解决方案了吗? 【参考方案1】:尝试使用以下自定义设置初始化 AVAssetReaderOutput
:
NSDictionary *settings =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:44100.0], AVSampleRateKey,
[NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
nil];
【讨论】:
以上是关于如何使用 AVAssetReader 和 AVAssetWriter 创建 AAC 文件?的主要内容,如果未能解决你的问题,请参考以下文章
如何向 AVAssetReader copyNextSampleBuffer 添加回调?
如何使用 AVAssetReader 在 iOS 上正确读取解码的 PCM 样本——目前解码不正确