重启录制时AVAudioEngine inputNode installTap崩溃

App*_*e99 12 speech-recognition ios avaudioengine swift3 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)'
Run Code Online (Sandbox Code Playgroud)

以下是用于启动和停止录制的代码:

@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()
}

}
Run Code Online (Sandbox Code Playgroud)

startRecording()在我们请求授权后,在viewDidLoad中调用.stopRecording()视图控制器被关闭时调用.

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

小智 13

有两种可能的方法来解决这个问题。

  1. 检查inputFormat.channelCount。它可能会抛出错误,因为麦克风正在另一个应用程序或您的其他应用程序中使用。
if(inputNode.inputFormat(forBus: 0).channelCount == 0){
    NSLog("Not enough available inputs!")
    return
}
Run Code Online (Sandbox Code Playgroud)
  1. 尝试重置audioEngine.
audioEngine.reset()
Run Code Online (Sandbox Code Playgroud)


Won*_*ray 10

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

let recordingFormat = node.inputFormat(forBus: 0)
Run Code Online (Sandbox Code Playgroud)

其次,经过一番挖掘之后,似乎这种崩溃通常是由应用程序的共享AVAudioSession类别设置引起的。如果您要执行现场麦克风音频处理,请确保已按照以下方式配置了音频会话:

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


小智 10

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

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

    return true
}
Run Code Online (Sandbox Code Playgroud)

附:let recordingFormat = audioEngine.inputNode.outputFormat(forBus: 0)


小智 5

您可以替换此代码:

let recordingFormat = node.outputFormat(forBus: 0)
Run Code Online (Sandbox Code Playgroud)

具有以下内容:

let recordingFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 1)
Run Code Online (Sandbox Code Playgroud)

这段代码解决了这个问题。

  • 但是 AVAudioNode 类中的 installTapOnBus 方法示例显示开发人员是这样使用这个方法的;AVAudioEngine *engine = [[AVAudioEngine alloc] init]; AVAudioInputNode *input = [引擎输入节点]; AVAudioFormat *format = [input outputFormatForBus: 0]; [input installTapOnBus: 0 bufferSize: 8192 format: format block: ^(AVAudioPCMBuffer *buf, AVAudioTime *when) { // 'buf' 包含在 'when' 时间从输入节点捕获的音频 }]; 他们将 outputformatonbus 提供给 installtaponbus 方法 (2认同)