使用Speech kit ios时,由于未被捕获的应用程序崩溃而终止应用程序
我在实现语音文本时遇到了这个错误:
因未捕获的exception’com.apple.coreaudio.avfaudio’而终止应用程序,原因:’必需条件为false:_recordingTap == nil’
和:
错误:[0x1b2df5c40]> avae> AVAudioNode.mm:565:CreateRecordingTap:必需条件为false:_recordingTap == nil
这是我的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: []) } } }
您可以尝试在停止录制时使用它
斯威夫特3 :
audioEngine.inputNode?.removeTap(onBus: 0)
这对我很有帮助,也应该帮助你。
你可能已经在公共汽车上轻敲了,你不能在同一辆公共汽车上有另一个。 停止引擎时应该删除TapOnBus。
audioEngine.inputNode?.removeTap(onBus: 0)