1

如果我检查了回调中的SFSpeechRecognizer recognitionTask回调标记(在 macOS 上):

        recognitionTask = speechRecognizer.recognitionTask( with: recognitionRequest )
        { result, error in
            // if more than two seconds elapsed since the last update, we send a notification
            NSLog( "speechRecognizer.recognitionTask callback" )
            :

...我观察到:

:
2019-11-08 14:51:00.35 ... speechRecognizer.recognitionTask callback
2019-11-08 14:51:00.45 ... speechRecognizer.recognitionTask callback

2019-11-08 14:51:32.31 ... speechRecognizer.recognitionTask callback

即在我最后一次发言后大约 30 秒,还有一个额外的不需要的回调。

result用于nil最后一次回调。

它接近 30 秒的事实表明它代表了最大超时。

我不希望超时,因为我已经手动关闭了我的会话(在 5 秒左右,通过单击一个按钮):

    @objc
    func stopRecording()
    {
        print( "stopRecording()" )

        // Instructs the task to stop accepting new audio (e.g. stop recording) but complete processing on audio already buffered.
        // This has no effect on URL-based recognition requests, which effectively buffer the entire file immediately.
        recognitionTask?.finish()

        // Indicate that the audio source is finished and no more audio will be appended
        recognitionRequest?.endAudio()

        //self.recognitionRequest = nil

        audioEngine.stop()

        audioEngine.inputNode.removeTap( onBus: 0 )

        //recognitionTask?.cancel()

        //self.recognitionTask = nil

        self.timer?.invalidate()

        print( "stopRecording() DONE" )
    }

有很多注释掉的代码,因为在我看来,有些进程我无法关闭,但我无法弄清楚。

完整的代码在这里

谁能看到出了什么问题?

4

1 回答 1

1

注意:在这个解决方案中,在销毁序列启动后,仍然有一个不需要的回调。因此,我还不打算接受答案。也许这个问题存在更优雅的解决方案,或者有人可能会阐明观察到的现象。

以下代码完成了这项工作:

        is_listening = true
        recognitionTask = speechRecognizer.recognitionTask( with: recognitionRequest )
        { result, error in
            if !self.is_listening {
                NSLog( "IGNORED: speechRecognizer.recognitionTask callback" )
                return
            }

            // if more than two seconds elapsed since the last update, we send a notification
            self.timer?.invalidate()
            NSLog( "speechRecognizer.recognitionTask callback" )
            self.timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { _ in
                if !self.is_listening {
                    print( "IGNORED: Inactivity (timer) Callback" )
                    return
                }
                print( "Inactivity (timer) Callback" )
                self.timer?.invalidate()
                NotificationCenter.default.post( name: Dictation.notification_paused,  object: nil )
                //self.stopRecording()
            }
        :
    }


    @objc
    func stopRecording()
    {
        print( "stopRecording()" )

        is_listening = false

        audioEngine.stop()
        audioEngine.inputNode.removeTap(onBus: 0)
        audioEngine.inputNode.reset()

        recognitionRequest?.endAudio()
        recognitionRequest = nil

        timer?.invalidate()
        timer = nil;

        recognitionTask?.cancel()
        recognitionTask = nil
    }

确切的顺序取自https://github.com/2bbb/ofxSpeechRecognizer/blob/master/src/ofxSpeechRecognizer.mm——我不确定它在多大程度上是顺序敏感的。

对于初学者来说,这个破坏序列似乎消除了 30 秒的超时?打回来。

然而,关闭后仍然受到打击stopListening

为了解决这个问题,我创建了一个is_listening标志。

我有一种预感,Apple 可能应该在框架内内化了这个逻辑,但它确实有效,我是一只快乐的兔子。

于 2019-11-09T13:34:28.397 回答