Ich versuche, eine lokale M4A oder MP3-Datei und komprimieren/down-Sample diese Datei (für die Zwecke der Erstellung einer kleineren Datei).AVAssetWriter Wie schreibe ich downsampled/komprimierte M4A/MP3-Dateien
Ursprünglich benutzte ich die AVAssetExportSession, um ein AVAsset in ein temporäres Verzeichnis zu exportieren, aber ich hatte keine Kontrolle über Komprimierung/Downsampling (Sie können nur Presets verwenden, die nur .wav Dateiformate Unterstützung der Qualitätsminderung).
Dann, nach einigen Beispielen hier auf SO, habe ich versucht, mit AVAssetReader/AVAssetWriter diesen "Export" zu präformieren.
Ich eröffne mein Leser/Schreiber als solche:
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];
Und dann fange ich an zu schreiben ...
[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;
}
}
}];
Wenn ich mit dem Schreiben fertig bin, habe die Daten i angeblich geschrieben Die exportURL ist null und der Writer meldet einen erfolgreichen Abschluss. Irgendwelche Ideen, was könnte schief gehen?
aktualisieren Der Schriftsteller Status nach appendSampleBuffer:
Aufruf wird AVAssetWriterStatusFailed, obwohl der Leser Status erfolgreich ist, und scheint durch die gesamte Datei zu lesen.
Hat es jemals versucht, etwas zu schreiben? Wie lautet der Leserstatus beim ersten Versuch, den Sample-Puffer anzufügen? – BlueVoodoo
Ah ha, es erscheint bei jedem Schritt, wenn '[WriterInput appendSampleBuffer:]' aufgerufen wird, der Writer-Status ist 3, was durch Betrachten der Enumeration aussieht wie AVAssetWriterStatusFailed. Es sieht so aus, als ob der Reader alle Beispielpuffer aus meinem Asset kopiert - appendSampleBuffer heißt * many * mal – Dfowj