Мое приложение использует AVAssetReader для воспроизведения песен в библиотеке iPOD. Теперь я хочу добавить возможность записи звука.Использование AVAssetWriter и AVAssetReader для записи и воспроизведения звука
Я записал аудио с использованием AVAssetWriter. Я проверил полученный аудиофайл (формат MPEG4AAC), успешно воспроизведя его с помощью AVAudioPlayer. Моя цель - воспроизвести аудио с помощью AVAssetReader. Но когда я создаю AVURLAsset для файла, у него нет трека, и, следовательно, AVAssetReader не работает (код ошибки: -11828 Формат файла не распознан).
Что делать, чтобы AVAsset распознал формат файла? Есть ли какой-то специальный формат файла, необходимый для AVAsset?
Вот коды для записи:
void setup_ASBD(void *f, double fs, int sel, int numChannels);
static AVAssetWriter *assetWriter = NULL;
static AVAssetWriterInput *assetWriterInput = NULL;
static CMAudioFormatDescriptionRef formatDesc;
AVAssetWriter *newAssetWriter(NSURL *url) {
NSError *outError;
assetWriter = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeAppleM4A error:&outError];
if(assetWriter == nil) {
NSLog(@"%s: asset=%x, %@\n", __FUNCTION__, (int)assetWriter, outError);
return assetWriter;
}
AudioChannelLayout audioChannelLayout = {
.mChannelLayoutTag = kAudioChannelLayoutTag_Mono,
.mChannelBitmap = 0,
.mNumberChannelDescriptions = 0
};
// Convert the channel layout object to an NSData object.
NSData *channelLayoutAsData = [NSData dataWithBytes:&audioChannelLayout length:offsetof(AudioChannelLayout, mChannelDescriptions)];
// Get the compression settings for 128 kbps AAC.
NSDictionary *compressionAudioSettings = @{
AVFormatIDKey : [NSNumber numberWithUnsignedInt:kAudioFormatMPEG4AAC],
AVEncoderBitRateKey : [NSNumber numberWithInteger:128000],
AVSampleRateKey : [NSNumber numberWithInteger:44100],
AVChannelLayoutKey : channelLayoutAsData,
AVNumberOfChannelsKey : [NSNumber numberWithUnsignedInteger:1]
};
// Create the asset writer input with the compression settings and specify the media type as audio.
assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:compressionAudioSettings];
assetWriterInput.expectsMediaDataInRealTime = YES;
// Add the input to the writer if possible.
if (assetWriterInput != NULL && [assetWriter canAddInput:assetWriterInput]) {
[assetWriter addInput:assetWriterInput];
}
else {
NSLog(@"%s:assetWriteInput problem: %x\n", __FUNCTION__, (int)assetWriterInput);
return NULL;
}
[assetWriter startWriting];
// Start a sample-writing session.
[assetWriter startSessionAtSourceTime:kCMTimeZero];
if(assetWriter.status != AVAssetWriterStatusWriting) {
NSLog(@"%s: Bad writer status=%d\n", __FUNCTION__, (int)assetWriter.status);
return NULL;
}
AudioStreamBasicDescription ASBD;
setup_ASBD(&ASBD, 44100, 2, 1);
CMAudioFormatDescriptionCreate (NULL, &ASBD, sizeof(audioChannelLayout), &audioChannelLayout, 0, NULL, NULL, &formatDesc);
//CMAudioFormatDescriptionCreate (NULL, &ASBD, 0, NULL, 0, NULL, NULL, &formatDesc);
return assetWriter;
}
static int sampleCnt = 0;
void writeNewSamples(void *buffer, int len) {
if(assetWriterInput == NULL) return;
if([assetWriterInput isReadyForMoreMediaData]) {
OSStatus result;
CMBlockBufferRef blockBuffer = NULL;
result = CMBlockBufferCreateWithMemoryBlock (NULL, buffer, len, NULL, NULL, 0, len, 0, &blockBuffer);
if(result == noErr) {
CMItemCount numSamples = len >> 1;
const CMSampleTimingInfo sampleTiming = {CMTimeMake(1, 44100), CMTimeMake(sampleCnt, 44100), kCMTimeInvalid};
CMItemCount numSampleTimingEntries = 1;
const size_t sampleSize = 2;
CMItemCount numSampleSizeEntries = 1;
CMSampleBufferRef sampleBuffer;
result = CMSampleBufferCreate(NULL, blockBuffer, true, NULL, NULL, formatDesc, numSamples, numSampleTimingEntries, &sampleTiming, numSampleSizeEntries, &sampleSize, &sampleBuffer);
if(result == noErr) {
if([assetWriterInput appendSampleBuffer:sampleBuffer] == YES) sampleCnt += numSamples;
else {
NSLog(@"%s: ERROR\n", __FUNCTION__);
}
printf("sampleCnt = %d\n", sampleCnt);
CFRelease(sampleBuffer);
}
}
}
else {
NSLog(@"%s: AVAssetWriterInput not taking input data: status=%ld\n", __FUNCTION__, assetWriter.status);
}
}
void stopAssetWriter(AVAssetWriter *assetWriter) {
[assetWriterInput markAsFinished];
[assetWriter finishWritingWithCompletionHandler:^{
NSLog(@"%s: Done: %ld: %d samples\n", __FUNCTION__, assetWriter.status, sampleCnt);
sampleCnt = 0;
}];
assetWriterInput = NULL;
}