I got this error while implementing speech to text:
Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: _recordingTap == nil'
and:
ERROR: [0x1b2df5c40] >avae> AVAudioNode.mm:565: CreateRecordingTap: required condition is false: _recordingTap == nil
Here is the code of my viewController:
public class ViewController: UIViewController, SFSpeechRecognizerDelegate { // MARK: Properties private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))! private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? private var recognitionTask: SFSpeechRecognitionTask? private let audioEngine = AVAudioEngine() @IBOutlet var textView : UITextView! @IBOutlet var recordButton : UIButton! // MARK: UIViewController public override func viewDidLoad() { super.viewDidLoad() // Disable the record buttons until authorization has been granted. recordButton.isEnabled = false } override public func viewDidAppear(_ animated: Bool) { speechRecognizer.delegate = self SFSpeechRecognizer.requestAuthorization { authStatus in /* The callback may not be called on the main thread. Add an operation to the main queue to update the record button's state. */ OperationQueue.main.addOperation { switch authStatus { case .authorized: self.recordButton.isEnabled = true case .denied: self.recordButton.isEnabled = false self.recordButton.setTitle("User denied access to speech recognition", for: .disabled) case .restricted: self.recordButton.isEnabled = false self.recordButton.setTitle("Speech recognition restricted on this device", for: .disabled) case .notDetermined: self.recordButton.isEnabled = false self.recordButton.setTitle("Speech recognition not yet authorized", for: .disabled) } } } } private func startRecording() throws { // Cancel the previous task if it's running. if let recognitionTask = recognitionTask { recognitionTask.cancel() self.recognitionTask = nil } let audioSession = AVAudioSession.sharedInstance() try audioSession.setCategory(AVAudioSessionCategoryRecord) try audioSession.setMode(AVAudioSessionModeMeasurement) try audioSession.setActive(true, with: .notifyOthersOnDeactivation) recognitionRequest = SFSpeechAudioBufferRecognitionRequest() guard let inputNode = audioEngine.inputNode else { fatalError("Audio engine has no input node") } guard let recognitionRequest = recognitionRequest else { fatalError("Unable to created a SFSpeechAudioBufferRecognitionRequest object") } // Configure request so that results are returned before audio recording is finished recognitionRequest.shouldReportPartialResults = true // A recognition task represents a speech recognition session. // We keep a reference to the task so that it can be cancelled. recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in var isFinal = false if let result = result { self.textView.text = result.bestTranscription.formattedString isFinal = result.isFinal } if error != nil || isFinal { self.audioEngine.stop() inputNode.removeTap(onBus: 0) self.recognitionRequest = nil self.recognitionTask = nil self.recordButton.isEnabled = true self.recordButton.setTitle("Start Recording", for: []) } } let recordingFormat = inputNode.outputFormat(forBus: 0) inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in self.recognitionRequest?.append(buffer) } audioEngine.prepare() try audioEngine.start() textView.text = "(Go ahead, I'm listening)" } // MARK: SFSpeechRecognizerDelegate public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) { if available { recordButton.isEnabled = true recordButton.setTitle("Start Recording", for: []) } else { recordButton.isEnabled = false recordButton.setTitle("Recognition not available", for: .disabled) } } // MARK: Interface Builder actions @IBAction func recordButtonTapped() { if audioEngine.isRunning { audioEngine.stop() recognitionRequest?.endAudio() recordButton.isEnabled = false recordButton.setTitle("Stopping", for: .disabled) } else { try! startRecording() recordButton.setTitle("Stop recording", for: []) } } }
You can try to use it on stop recording
Swift 3:
audioEngine.inputNode?.removeTap(onBus: 0)
It's helped me and should help you too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With