问题描述
我正在尝试使用本地m4a或mp3文件并压缩/下采样此文件(用于制作较小的文件)。
I'm trying to take a local m4a or mp3 file and compress/down-sample this file (for the purposes of making a smaller file).
最初,我使用AVAssetExportSession将AVAsset导出到临时目录,但我没有对压缩/下采样的任何控制(你只能使用预设,其中只有.wav文件格式支持质量下降)。
Originally, I was using the AVAssetExportSession to export an AVAsset to a temp directory, but I didn't have any control over compression/down-sampling (you can only use presets, which of them, only .wav file formats support quality degradation).
然后,按照SO上的几个例子,我尝试使用AVAssetReader / AVAssetWriter来预先形成这个'出口'。
Then, following several examples here on SO, I tried using AVAssetReader/AVAssetWriter to preform this 'export'.
我这样创建我的读者/作者:
I create my reader/writer as such:
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的数据为空,并且作者报告成功完成。可能出现问题的任何想法?
When I'm done writing, the data i've supposedly written to the exportURL is null, and the writer reports a successful completion. Any ideas what might be going wrong?
更新调用后的作者状态appendSampleBuffer:
是AVAssetWriterStatusFailed,虽然读者状态是成功的,并且似乎读取整个文件。
Update The writer status after calling appendSampleBuffer:
is AVAssetWriterStatusFailed, though the readers status is successful, and seems to read through the entire file.
推荐答案
我遇到了解决方案:
使用NSHomeDirectory()在 NSString * exportPath = [NSHomeDirectory()stringByAppendingPathComponent:@out.m4a]
导致编写器无法创建该文件。不完全确定原因,或者我需要做些什么才能使其工作,但将 NSHomeDirectiory()
更改为 NSTemporaryDirectory()
在此期间解决了我的问题。
Using NSHomeDirectory() in NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"]
was causing the writer to not be able to create the file. Not exactly sure why, or what I would need to do to allow this to work, but changing NSHomeDirectiory()
to NSTemporaryDirectory()
has solved my problems in the meantime.
这篇关于AVAssetWriter如何写下采样/压缩的m4a / mp3文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!