问题
I am working with Speech Recognition in Swift and have a problem with canceling SFSpeechRecognitionTask
.
I have implemented the following logic:
- I have a mic button
- Speech is being recognized while button is pressed
- When the mic button is released I need to finish the speech recognition, to get the results in completion block (
recognitionTask
is used for it). So I usestopRecording()
function for this purpose. This function works properly. - I also need to cancel
recognitionTask
when I do some other logic. So I needrecognitionTask
to stop immediately the completion handler and to return error or result. For that purpose I'd writtencancelTask()
. I've tried different variants of this function, but non works. The problem is that I always get completion after some delay when app is running with slow internet connection (for example edge).
I've checked recognitionTask.isCanceled
just after recognitionTask?.cancel()
and this property is always false
. Any ideas why this is not working?
func startRecording() throws {
guard speechRecogniser.isAvailable else {
// Speech recognition is unavailable, so do not attempt to start.
return
}
if let recognitionTask = recognitionTask {
// We have a recognition task still running, so cancel it before starting a new one.
recognitionTask.cancel()
self.recognitionTask = nil
}
guard SFSpeechRecognizer.authorizationStatus() == .authorized else {
SFSpeechRecognizer.requestAuthorization({ _ in })
return
}
let audioSession = AVAudioSession.sharedInstance()
try audioSession.setCategory(AVAudioSessionCategoryRecord)
try audioSession.setMode(AVAudioSessionModeMeasurement)
try audioSession.setActive(true, with: .notifyOthersOnDeactivation)
recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
let inputNode = audioEngine.inputNode
guard let recognitionRequest = recognitionRequest else {
throw SpeechControllerError.noAudioInput
}
recognitionTask = speechRecogniser.recognitionTask(with: recognitionRequest) { [unowned self] result, error in
if let result = result {
self.delegate?.speechController(self, didRecogniseText: result.bestTranscription.formattedString)
}
if result?.isFinal ?? (error != nil) {
inputNode.removeTap(onBus: SpeechController.inputNodeBus)
}
}
let recordingFormat = inputNode.outputFormat(forBus: SpeechController.inputNodeBus)
inputNode.installTap(onBus: SpeechController.inputNodeBus, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
self.recognitionRequest?.append(buffer)
}
audioEngine.prepare()
try audioEngine.start()
}
/// Ends the current speech recording session.
func stopRecording() {
audioEngine.stop()
recognitionRequest?.endAudio()
}
func cancelTask() {
audioEngine.inputNode.removeTap(onBus: 0)
audioEngine.stop()
recognitionRequest?.endAudio()
recognitionTask?.cancel()
recognitionTask = nil
speechRecognizer = nil
recognitionRequest = nil
}
来源:https://stackoverflow.com/questions/47859791/swift-sfspeechrecognitiontask-is-not-canceled