重启录制时AVAudioEngine inputNode installTap崩溃

时间:2017-01-23 11:31:59

标签: ios swift3 speech-recognition avaudioengine sfspeechrecognizer

我正在我的应用中实现语音识别。当我第一次使用语音识别逻辑呈现视图控制器时,一切正常。但是,当我再次尝试呈现视图控制器时,我遇到了以下崩溃:

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's 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()
}

}
我们请求授权后,在viewDidLoad中调用

startRecording()。解除视图控制器时调用stopRecording()

请协助。我很难找到这次崩溃的解决方案

6 个答案:

答案 0 :(得分:7)

首先,一个小问题。点击设备的麦克风时,您需要使用输入总线的格式:

let recordingFormat = node.inputFormat(forBus: 0)

其次,经过一些挖掘后,这种崩溃似乎最常见于应用程序的共享AVAudioSession类别设置。如果您要进行实时麦克风音频处理,请确保您的音频会话配置如此:

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

答案 1 :(得分:3)

在拨打电话时尝试使用语音识别时发生trade_type崩溃,这导致采样率等于零。 我的解决方案是创建下面的required condition is false: IsFormatSampleRateAndChannelCountValid(format)函数,并在audioInputIsBusy()之前调用它 这样可以防止崩溃,我显示了一条消息,指出“语音识别不可用”,然后使用try audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)重设audioEngine。

audioEngine = AVAudioEngine()

ps:func audioInputIsBusy(recordingFormat: AVAudioFormat) -> Bool { guard recordingFormat.sampleRate == 0 || recordingFormat.channelCount == 0 else { return false } return true }

答案 2 :(得分:2)

您可以替换此代码:

let recordingFormat = node.outputFormat(forBus: 0)

以下内容:

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

此代码解决了问题。

答案 3 :(得分:2)

有两种方法可以解决此问题。

  1. 选中inputFormat.channelCount。可能会引发错误,因为麦克风正在另一个应用程序或您自己的其他地方使用。
if(inputNode.inputFormat(forBus: 0).channelCount == 0){
    NSLog("Not enough available inputs!")
    return
}
  1. 尝试重置audioEngine
audioEngine.reset()

答案 4 :(得分:0)

尝试此操作,然后每次开始运行:

audioEngine = AVAudioEngine()

答案 5 :(得分:0)

我必须在 installTap 之前调用 removeTap() 才能使其工作。以上解决方案都不适合我。

//Remove tap first.
inputNode.removeTap(onBus: 0)

// Configure the microphone input.
let recordingFormat = inputNode.inputFormat(forBus: 0)            
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
            //process buffer...
        }