私はローカルのm4aまたはmp3ファイルを取得し、このファイルを圧縮/ダウンサンプリングしようとしています(ファイルを小さくするため)。AVAssetWriterダウンサンプリング/圧縮m4a/mp3ファイルを書き込む方法
元々、私はAVAssetをtempディレクトリにエクスポートするためにAVAssetExportSessionを使用していましたが、圧縮/ダウンサンプリングを制御できませんでした(プリセットのみ使用できますが、品質劣化をサポートします)。
次に、ここでいくつかの例をあげて、AVAssetReader/AVAssetWriterを使用してこの「エクスポート」を実行しようとしました。
私のような私のリーダ/ライタを作成:
私は、私はおそらくに書いたデータを書き込む終わりだ[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;
}
}
}];
...
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];
そして、私が書き込みを開始しますexportURLはnullであり、ライターは正常終了を報告します。何が間違っている可能性がありますか?
更新appendSampleBuffer:
を呼び出した後ライターのステータスは、読者のステータスは成功し、ファイル全体を通読しているようだが、AVAssetWriterStatusFailedされます。
これまでに何か書き込もうとしていますか?初めてサンプルバッファを追加しようとしたときの読者のステータスは? – BlueVoodoo
ああ、 '[writerInput appendSampleBuffer:]'が呼び出されるたびに表示され、ライターのステータスは3で、列挙型を見るとAVAssetWriterStatusFailedのようになります。 * appendSampleBufferは* many * timesと呼ばれています。 – Dfowj