Запись AVAudioRecorder AAC/m4a

Я пытаюсь записать аудио на устройстве с помощью AVAudioRecorder. Этот файл передается на веб-сервер, и я хочу воспроизвести полученный файл в веб-браузере.

Я пробовал различные комбинации настроек на устройстве... ничто не заставляет кодировать файл в правильный формат AAC.

QuickTime говорит, что он не знает, как воспроизвести этот файл.

Пример кода

    private void InitializeRecordingSession() {
         string fileName = string.Format("{0}.m4a", Guid.NewGuid());
         string tmpdir = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/audio";
          if (!Directory.Exists(tmpdir))
               Directory.CreateDirectory(tmpdir);
          audioFilePath = Path.Combine(tmpdir, fileName);

          Console.WriteLine("Audio File Path: " + audioFilePath);

          var url = NSUrl.FromFilename(audioFilePath);
          var settings = new AVAudioRecorderSettings() {
               AudioFormat = AudioFormatType.MPEG4AAC,
               SampleRate = 44100,
               NumberChannels = 1,
               AudioQuality = AVAudioQuality.High,    
          };

          recorder = AVAudioRecorder.ToUrl(url, settings, out error);

          //Set Recorder to Prepare To Record
          recorder.PrepareToRecord();  
     }

Изменить -Вставьте этот код перед строкой

recorder = AVAudioRecorder.ToUrl(url, settings, out error);

Все сработало.

NSError error;    
AVAudioSession audioSession = AVAudioSession.SharedInstance();
audioSession.SetCategory(AVAudioSession.CategoryRecord, out error);
audioSession.SetActive(true, out error);

Ответ 1

IOS SDK, по-видимому, глупо. Установка ключа идентификатора формата на kAudioFormatMPEG4AAC недостаточно для его фактического кодирования файла; в QuickTime он будет воспроизводиться, но в его свойствах вы увидите только AAC и никаких дополнительных сведений. Изменение расширения выходного файла на m4a должно помочь сделать трюк и заставить его применять правильную кодировку.

Ответ 2

Для аппаратно-ускоренных кодеров только один сеанс может быть активным в любой момент времени. Это означает, что для AAC он будет работать в симуляторе (где используется программный кодер), но может быть неудачным на устройстве (где используется аппаратный кодер), если ваше приложение не активирует AVAudioSession.

Я также пытался использовать AVAudioRecorder для записи звука в кодированном формате AAC, предпочтительно в файле .m4a. У меня был зверь, занимающийся этим. Я быстро смог получить код для записи в AAC внутри основного звукового файла (.caf), но я не мог заставить AVAudioRecorder правильно форматировать .m4a. Я как раз собирался переписать код записи в своем приложении, используя более низкий уровень Audio Units API, но вместо этого я поместил его на задний план и добавил в код для обработки общей аудио сессии. Как только это было настроено, я вернулся и попытался сохранить как .m4a, и он просто сработал.

Вот пример кода:

NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
NSURL *tmpFileUrl = [NSURL fileURLWithPath:[docsDir stringByAppendingPathComponent:@"tmp.m4a"]];
NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                        [NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
                        [NSNumber numberWithFloat:16000.0], AVSampleRateKey,
                        [NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
                        nil];
NSError *error = nil;
AVAudioRecorder *recorder = [[AVAudioRecorder alloc] initWithURL:tmpFileUrl settings:recordSettings error:&error];
[recorder prepareToRecord];

AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryRecord error:nil];
[session setActive:YES error:nil];

[recorder record];

Затем, чтобы закончить запись, я использовал:

[recorder stop];
AVAudioSession *session = [AVAudioSession sharedInstance];
int flags = AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation;
[session setActive:NO withFlags:flags error:nil];

Тогда файл в 'tmpFileUrl' может быть использован как вам угодно.

Ответ 3

Советы по AVAudioSession очень полезны!

Так как setActive:withFlags:error: устарел в iOS 6.0 код для остановки сеанса аудио должен быть отрегулирован так:

AVAudioSession *session = [AVAudioSession sharedInstance];
int flags = AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation;
[session setActive:NO withOptions:flags error:nil];