Exception with AVFoundation using Speech framework

I'm using the Speech framework to perform recognition on live audio. When I open a recording/recognition session two times in a row, I get the following error:

*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: _recordingTap == nil'


Let's assume that I have user permission and that the speech recognizer is available (both are true at the time of the crash). The method I invoke is:


private func listen() throws {
    if let recognitionTask = self.recognitionTask {
      recognitionTask.cancel()
      self.recognitionTask = nil
    }
    self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
    guard let recognitionRequest = self.recognitionRequest else { fatalError("Unable to created a SFSpeechAudioBufferRecognitionRequest object") }
    guard let inputNode = audioEngine.inputNode else { fatalError("Audio engine has no input node") }
    recognitionRequest.shouldReportPartialResults = true

    self.recognitionTask = speechRecognizer?.recognitionTaskWithRequest(recognitionRequest, resultHandler: { (result, error) in
        // Code here in which I look for certain phrases - irrelevant
    })

    let recordingFormat = inputNode.outputFormatForBus(0)
    inputNode.installTapOnBus(0, bufferSize: 2048, format: recordingFormat, block: { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
      recognitionRequest.appendAudioPCMBuffer(buffer)
    })

    self.audioEngine.prepare()
    try self.audioEngine.start()
}


Most of these variables are declared or defined outside of the method body:


  private let audioEngine = AVAudioEngine()
  private var speechRecognizer: SFSpeechRecognizer?
  private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
  private var recognitionTask: SFSpeechRecognitionTask?


And, before the method is invoked, I call the following method to close the recording and recognition session. This method is invoked much before (let's say a minute or so) I call listen() again.


  func stopListening()
    self.audioEngine.stop()
    self.recognitionRequest?.endAudio()
    self.recognitionTask?.cancel()
    self.recognitionTask = nil
  }


In stopListening(), anything that I zero out is later reinitialized in listen().


Just to reiterate, this crash happens on a second invoke of listen() only after I invoke stopListening(), with these methods being called minutes apart.

Replies

Hi!


I'm having the same problem here.


Did you find a way to fix it?


Thanks,

Catarina

The error is telling you that you already have a tap installed on that bus and that you can't have another one.


When you call listen() initially you install the tap on the bus.

Then you call stopListening() and you stop your recognition but you don't do anything about the tap.

Then when you call listen() again you are trying to install the tap again - that produces the error.


You could add something to removeTapOnBus when you stopListening() - this should mean that you can add it back on again when you start listening again.

I have a similar implementation and I was able to solve the error by removing the tap on the bus before creating it. Plase this line in between line 15 and 16, basically before you install the tap.


input.removeTap(onBus: 0)


Hope this helps! [R]