AVAssetWriter如何写下采样/压缩m4a / mp3文件

我试图采取本地m4a或MP3文件和压缩/下采样此文件(为了制作一个较小的文件的目的)。

最初,我使用AVAssetExportSession将AVAsset导出到临时目录,但我没有任何控制压缩/下采样的方法(只能使用预设,其中只有.wav文件格式支持质量下降) 。

然后,在这里几个例子,我尝试使用AVAssetReader / AVAssetWriter预制这个'出口'。

我创build我的读者/作家是这样的:

NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"]; NSURL *exportURL = [NSURL fileURLWithPath:outPath]; // reader NSError *readerError = nil; AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:asset error:&readerError]; AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; AVAssetReaderTrackOutput *readerOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:nil]; [reader addOutput:readerOutput]; // writer NSError *writerError = nil; AVAssetWriter *writer = [[AVAssetWriter alloc] initWithURL:exportURL fileType:AVFileTypeAppleM4A error:&writerError]; AudioChannelLayout channelLayout; memset(&channelLayout, 0, sizeof(AudioChannelLayout)); channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; // use different values to affect the downsampling/compression NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey, [NSNumber numberWithFloat:44100.0], AVSampleRateKey, [NSNumber numberWithInt:2], AVNumberOfChannelsKey, [NSNumber numberWithInt:128000], AVEncoderBitRateKey, [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey, nil]; AVAssetWriterInput *writerInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio outputSettings:outputSettings]; [writerInput setExpectsMediaDataInRealTime:NO]; [writer addInput:writerInput]; 

然后我开始写…

 [writer startWriting]; [writer startSessionAtSourceTime:kCMTimeZero]; [reader startReading]; dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL); [writerInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^{ NSLog(@"Asset Writer ready : %d", writerInput.readyForMoreMediaData); while (writerInput.readyForMoreMediaData) { CMSampleBufferRef nextBuffer; if ([reader status] == AVAssetReaderStatusReading && (nextBuffer = [readerOutput copyNextSampleBuffer])) { if (nextBuffer) { NSLog(@"Adding buffer"); [writerInput appendSampleBuffer:nextBuffer]; } } else { [writerInput markAsFinished]; switch ([reader status]) { case AVAssetReaderStatusReading: break; case AVAssetReaderStatusFailed: [writer cancelWriting]; break; case AVAssetReaderStatusCompleted: NSLog(@"Writer completed"); [writer endSessionAtSourceTime:asset.duration]; [writer finishWriting]; NSData *data = [NSData dataWithContentsOfFile:exportPath]; NSLog(@"Data: %@", data); break; } break; } } }]; 

当我完成写作时,我认为写入到exportURL的数据为空,作者报告成功完成。 任何想法可能会出错?

更新调用appendSampleBuffer:之后的写入者状态是AVAssetWriterStatusFailed,虽然读者状态是成功的,似乎读取整个文件。

我遇到了解决scheme:

NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"]使用NSHomeDirectory() NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"]导致写入器无法创build文件。 不完全确定为什么,或者我需要做什么来让这个工作,但改变NSHomeDirectiory() NSTemporaryDirectory()已经解决了我的问题在此期间。