AVAudioRecorder не создает файлы.m4a, которые можно открывать и воспроизводить
Я пытаюсь изменить приложение iOS, которое может отправлять аудиофайлы (надежно / зашифрованные) на другие устройства iOS. Он использует AVAudioRecorder для записи аудиофайлов и использует AVAudioPlayer для воспроизведения любых полученных аудиофайлов.
Сейчас я пытаюсь изменить приложение для создания и отправки файлов, совместимых с Android. Я изменил существующий код AVAudioRecorder так:
[settings setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
[settings setValue:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey];
[settings setValue:[NSNumber numberWithInt:16] forKey:AVEncoderBitRateKey];
[settings setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
[settings setValue:[NSNumber numberWithFloat:48000.0] forKey:AVSampleRateKey];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dirPath = [paths objectAtIndex:0];
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:@"yyyy-MM-dd HH-mm"];
NSString *filename = [NSString stringWithFormat:@"%@.aac", [format stringFromDate:NSDate.date]];
Созданные файлы могут воспроизводиться на Mac, на устройстве iOS, но не на устройстве Android. Если расширение файла было вручную изменено на ".m4a", то файл воспроизводится на Android.
(Преимущество формата ".aac" заключается в том, что старые версии приложения могут получать эти файлы и воспроизводить их - я поддерживал обратную совместимость.)
Итак, я сделал это изменение:
NSString *filename = [NSString stringWithFormat:@"%@.m4a", [format stringFromDate:NSDate.date]];
Однако полученный файл (который создается без ошибок из AVAudioRecorder) не может быть воспроизведен ни на Mac, ни на устройствах iOS. И я жду, чтобы услышать, работает ли он на Android.
Когда AVAudioPlayer пытается открыть этот файл, он выводит:
Ошибка Domain=NSOSStatusErrorDomain Code=1685348671 "Операция не может быть завершена. (Ошибка OSStatus 1685348671.)" Code 1685348671 -> "dta?": Файл имеет неправильный формат, не является допустимым экземпляром аудиофайла своего типа, или не распознается как аудиофайл.
Простое переименование файла в ".aac" снова не меняет того факта, что его нельзя загрузить ни на что на Mac или iOS.
Сейчас кажется, что лучшим решением было бы создать файл ".aac", а затем в конце Android заменить ".aac" на ".m4a" и попытаться воспроизвести его.
Вопрос 1: Кто-нибудь знает, почему изменение расширения файла может привести к сбою AVAudioPLayer? Кстати, файл ".m4a", который я создал выше, не может быть открыт ни с чем, что у меня есть на Mac, поэтому я не могу сказать, связана ли проблема с форматом файла или неспособностью iOS или Mac прочитать этот тип файла,
Для любого любопытного я помещаю копию файла ".aac" и ".m4a" из AVAudioRecorder, здесь:
https://dl.dropboxusercontent.com/u/14939586/2013-07-08%2013-24.m4a https://dl.dropboxusercontent.com/u/14939586/2013-07-08%2010-11.aac
Вопрос 2: Хотя я установил AVAudioRecorder на один канал, результирующий файл является стереофоническим. Зачем? (По крайней мере, это то, что VLC говорит о метаданных)
Вопрос 3: Есть ли способ указать AAC-LC для кодирования без потерь? Или я могу сделать это только в случае перехода с AVAudioRecorder на API более низкого уровня?
3 ответа
Ответ на вопрос 1 заключается в том, что вы должны правильно установить аудио сеанс, иначе файл m4a не будет отформатирован правильно. Код аудиосеанса, который я сейчас установил непосредственно перед началом записи:
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryRecord error:nil];
[session setActive:YES error:nil];
Я вернул сеанс для воспроизведения после завершения записи, чтобы можно было воспроизводить аудиофайлы.
Вопрос 2 - проблема в VLC, который отображал неверное количество каналов. Аудиофайл в окне "Информация" в MacOS Finder отображается как один канал.
Вопрос 3 остается без ответа.
Для создания и записи аудио в файле ".m4a", которые воспроизводятся как в iOS, так и в Android, я использую следующий код:
NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
AudioRecorder = [[AVAudioRecorder alloc] initWithURL:fileOutPutUrl settings:recordSetting error:nil];
[AudioRecorder setDelegate:self];
[AudioRecorder recordForDuration:RecordLimitTime]; // Record Limit if require
if ([AudioRecorder prepareToRecord]) {
[AudioRecorder record];
}
В Android, мне не нужно менять код для воспроизведения только файла ".mp3", в Android просто измените расширение с "fileName.m4a" на "fileName.mp3", и это удивительно работает.и в iOS file = "fileName.m4a" играть гладко.
У меня была такая же проблема, я получал NSOSStatusErrorDomain 560030580 при создании
AVAudioPlayer
с локальным файлом.
Проблема была не в файле или его формате, а в том, что я настраивал
AVAudioSession
неправильно.
Я звонил
setCategory(.playAndRecord)
и путь до записи звука, а затем и при его воспроизведении, а я никогда не звонил.
Согласно документам Apple, для некоторых приложений для воспроизведения и записи деактивация должна происходить явно, поэтому я сделал следующее:
- Вызов
setCategory(.record)
и прямо перед записью, и при окончании разговора - Вызов
setCategory(.playback)
иsetActive(yes)
прямо перед воспроизведением файла и по окончании разговораsetActive(false)
Кроме того, я нашел этот https://www.osstatus.com/, который дает дополнительную информацию об ошибках, возникающих при работе с аудио / файлами.