3

I know that similar questions already were asked but proposed solutions didn't help me.

In my app I have to recognize user's speech and to synth text-to-speech as well. The problem is, I have random crashes when the app trying to recognize (especially after text-to-speech, but also in other cases: on the second recognition attempt, for example).

I have a special class Speecher with several obvious vars (some private) and two main functions: startRecord and killRecord.

func startRecord() {

    session = AVAudioSession.sharedInstance()

    do {
        try session.setCategory(AVAudioSession.Category.playAndRecord, mode: .spokenAudio, options: [.defaultToSpeaker, .mixWithOthers])
    } catch {
        print("audio session \(error)")
        return
    }

    audioEngine = AVAudioEngine()

    inputNode = audioEngine.inputNode
    inputNode.removeTap(onBus: 0)
    let recordingFormat = inputNode.inputFormat(forBus: 0)

    recognitionRequest = SFSpeechAudioBufferRecognitionRequest()

    guard let recognitionRequest = recognitionRequest else { fatalError("Unable to create a SFSpeechAudioBufferRecognitionRequest object") }
    recognitionRequest.shouldReportPartialResults = true

    if #available(iOS 13, *) {
        recognitionRequest.requiresOnDeviceRecognition = true
    }

    inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
        self.recognitionRequest.append(buffer)
    }

    audioEngine.prepare()

    do {
        try audioEngine.start()
    } catch {
        return print("audio engine start error \(error)")
    }

    guard let myRecognizer = SFSpeechRecognizer() else {
        print("recognizer error")
        return
    }

    if !myRecognizer.isAvailable {
        print("Recognizer is not available right now error")
        return
    }

    recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { result, error in
            if let result = result {

                let bestString = result.bestTranscription.formattedString
                print(bestString)
                self.speecherDelegate?.sendSpeechString(str: bestString)
            } else if let error = error {
                print("result error \(error)")
            }
        })

}

The next function is called before I'm trying to use text-to-speech or before I want to cancel/stop recognition session:

func killRecord() {
    if recognitionRequest != nil {
        recognitionRequest.endAudio()
    }


    if audioEngine != nil {

        audioEngine.stop()

        if audioEngine.inputNode != nil {
            audioEngine.inputNode.removeTap(onBus: 0)
        }
    }

    if recognitionTask != nil {
        recognitionTask?.cancel()
    }

    if session != nil {

        do {
            try session.setCategory(AVAudioSession.Category.playback, mode: .spokenAudio, options: [.allowBluetooth, .allowBluetoothA2DP, .defaultToSpeaker, .mixWithOthers])
            try session.setActive(false, options: .notifyOthersOnDeactivation)
        } catch {
            print("switch audiosession error not nil \(error)")
            return
        }

    } else {
        session = AVAudioSession.sharedInstance()

        do {
            try session.setCategory(AVAudioSession.Category.playback, mode: .spokenAudio, options: [.allowBluetooth, .allowBluetoothA2DP, .defaultToSpeaker, .mixWithOthers])
            try session.setActive(false, options: .notifyOthersOnDeactivation)
        } catch {
            print("switch audiosession error \(error)")
            return
        }
    }
}

What I'm getting a lot is a lldb errors. It looks like that:

enter image description here

The problem string in the code seems to be inputNode = audioEngine.inputNode but I don't know how to solve it. I've already tried audioEngine.inputNode.removeTap(onBus: 0) just before inputNode = audioEngine.inputNode but to no avail.

lithium
  • 1,272
  • 1
  • 14
  • 28

0 Answers0