AVAudioEngine inputNode installTap crash при перезапуске записи

Я использую распознавание речи в своем приложении. Когда я впервые представляю контроллер представления с логикой распознавания речи, все работает нормально. Однако, когда я пытаюсь представить контроллер представления снова, я получаю следующий сбой:

ERROR:    [0x190bf000] >avae> AVAudioNode.mm:568: CreateRecordingTap: required condition is false: IsFormatSampleRateAndChannelCountValid(format)
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: IsFormatSampleRateAndChannelCountValid(format)'

Вот код, используемый для запуска и остановки записи:

@available(iOS 10.0, *)
extension DictationViewController {

fileprivate func startRecording() throws {
    guard let recognizer = speechRecognizer else {
        debugLog(className, message: "Not supported for the device locale")
        return
    }

    guard recognizer.isAvailable else {
        debugLog(className, message: "Recognizer is not available right now")
        return
    }

    mostRecentlyProcessedSegmentDuration = 0
    guard let node = audioEngine.inputNode else {
        debugLog(className, message: "Could not get an input node")
        return
    }

    let recordingFormat = node.outputFormat(forBus: 0)
    node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { [weak self] (buffer, _) in
        self?.request.append(buffer)
    }

    audioEngine.prepare()
    try audioEngine.start()

    recognitionTask = recognizer.recognitionTask(with: request, resultHandler: {/***/})
}

fileprivate func stopRecording() {
    audioEngine.stop()
    audioEngine.inputNode?.removeTap(onBus: 0)
    request.endAudio()
    recognitionTask?.cancel()
}

}

startRecording() вызывается в viewDidLoad после того, как мы запросили авторизацию. stopRecording() вызывается, когда диспетчер представлений отклоняется.

Помогите. Я изо всех сил пытаюсь найти решение этой аварии

Ответ 1

Во-первых, небольшая проблема. При нажатии микрофона устройства вы хотите использовать формат входной шины:

let recordingFormat = node.inputFormat(forBus: 0)

Во-вторых, после некоторого копания кажется, что этот сбой чаще всего связан с настройками категории AVAudioSession вашего приложения. Убедитесь, что у вас настроен звуковой сеанс, если вы собираетесь выполнять звуковую обработку в реальном времени:

private func configureAudioSession() {
    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord, with: .mixWithOthers)
        try AVAudioSession.sharedInstance().setActive(true)
    } catch { }
}

Ответ 2

Вы можете заменить этот код:

let recordingFormat = node.outputFormat(forBus: 0)

со следующим:

let recordingFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 1)

Этот код исправил проблему.

Ответ 3

Есть два возможных способа решения этой проблемы.

  1. Проверьте inputFormat.channelCount. Возможно, возникла ошибка, поскольку микрофон используется в другом приложении или в другом месте, где вы находитесь.
if(inputNode.inputFormat(forBus: 0).channelCount == 0){
    NSLog("Not enough available inputs!")
    return
}
  1. Попробуйте сбросить настройки audioEngine.
audioEngine.reset()

Ответ 4

Сбой из-за частоты дискретизации. Когда мы находимся на вызове или случайной ситуации выборки, частота обнуляется. До этого разрешено, только если частота дискретизации больше нуля.