Swift SFSpeechRecognitionTask is not canceled

陌路散爱 提交于 2020-01-15 07:18:09

问题


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 use stopRecording() function for this purpose. This function works properly.
  • I also need to cancel recognitionTask when I do some other logic. So I need recognitionTask to stop immediately the completion handler and to return error or result. For that purpose I'd written cancelTask(). 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!