Tôi đang cố gắng lấy tệp m4a hoặc mp3 cục bộ và nén/xuống mẫu tệp này (với mục đích tạo tệp nhỏ hơn).AVAssetWriter Cách ghi các tệp m4a/mp3 nén xuống/lấy mẫu
Ban đầu, tôi đang sử dụng AVAssetExportSession để xuất AVAsset sang thư mục tạm thời, nhưng tôi không có quyền kiểm soát nén/lấy mẫu xuống (bạn chỉ có thể sử dụng các giá trị đặt sẵn, chỉ có định dạng tệp .wav hỗ trợ giảm chất lượng).
Sau đó, sau một vài ví dụ ở đây trên SO, tôi đã thử sử dụng AVAssetReader/AVAssetWriter để tạo biểu mẫu này 'xuất'.
tôi tạo độc giả của tôi/nhà văn như vậy:
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];
Và sau đó tôi bắt đầu viết ...
[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;
}
}
}];
Khi tôi thực hiện bằng văn bản, dữ liệu tôi đã được cho là ghi vào exportURL là null và người viết báo cáo thành công. Bất kỳ ý tưởng gì có thể sẽ sai?
Cập nhật Trạng thái của người viết sau khi gọi appendSampleBuffer:
là AVAssetWriterStatusFailed, mặc dù trạng thái người đọc thành công và dường như đọc toàn bộ tệp.
Nó có bao giờ cố gắng viết gì không? Trạng thái của người đọc lần đầu tiên nó cố gắng gắn thêm bộ lọc mẫu là gì? – BlueVoodoo
Ah ha, nó xuất hiện ở mọi bước khi '[writerInput appendSampleBuffer:]' được gọi, trạng thái ghi là 3, bằng cách nhìn vào enum, trông giống như AVAssetWriterStatusFailed. Dường như người đọc đang sao chép tất cả các bộ đệm mẫu từ nội dung của tôi mặc dù - appendSampleBuffer được gọi là * nhiều lần * – Dfowj