SFSpeechRecognizer - 检测话语结束

Posted

技术标签:

【中文标题】SFSpeechRecognizer - 检测话语结束【英文标题】:SFSpeechRecognizer - detect end of utterance 【发布时间】:2017-03-01 11:34:11 【问题描述】:

我正在开发一个使用 ios 10 内置语音识别的小项目。我使用设备的麦克风有工作结果,我的语音被非常准确地识别。

我的问题是每个可用的部分转录都会调用识别任务回调,我希望它检测人停止说话并调用回调并将isFinal 属性设置为true。它没有发生 - 应用正在无限期地监听。

SFSpeechRecognizer 是否能够检测到句尾?

这是我的代码 - 它基于 Internet 上的示例,它主要是从麦克风源中识别所需的样板。 我通过添加识别taskHint对其进行了修改。我也将shouldReportPartialResults设置为false,但似乎被忽略了。

    func startRecording() 

    if recognitionTask != nil 
        recognitionTask?.cancel()
        recognitionTask = nil
    

    let audioSession = AVAudioSession.sharedInstance()
    do 
        try audioSession.setCategory(AVAudioSessionCategoryRecord)
        try audioSession.setMode(AVAudioSessionModeMeasurement)
        try audioSession.setActive(true, with: .notifyOthersOnDeactivation)
     catch 
        print("audioSession properties weren't set because of an error.")
    

    recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
    recognitionRequest?.shouldReportPartialResults = false
    recognitionRequest?.taskHint = .search

    guard let inputNode = audioEngine.inputNode else 
        fatalError("Audio engine has no input node")
    

    guard let recognitionRequest = recognitionRequest else 
        fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")
    

    recognitionRequest.shouldReportPartialResults = true

    recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler:  (result, error) in

        var isFinal = false

        if result != nil 
            print("RECOGNIZED \(result?.bestTranscription.formattedString)")
            self.transcriptLabel.text = result?.bestTranscription.formattedString
            isFinal = (result?.isFinal)!
        

        if error != nil || isFinal 
            self.state = .Idle

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

            self.recognitionRequest = nil
            self.recognitionTask = nil

            self.micButton.isEnabled = true

            self.say(text: "OK. Let me see.")
        
    )

    let recordingFormat = inputNode.outputFormat(forBus: 0)
    inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat)  (buffer, when) in
        self.recognitionRequest?.append(buffer)
    

    audioEngine.prepare()

    do 
        try audioEngine.start()
     catch 
        print("audioEngine couldn't start because of an error.")
    

    transcriptLabel.text = "Say something, I'm listening!"

    state = .Listening

【问题讨论】:

【参考方案1】:

当用户按预期停止说话时,isFinal 标志似乎没有变为真。我猜这是 Apple 想要的行为,因为“用户停止说话”事件是一个未定义的事件。

我认为实现目标的最简单方法是执行以下操作:

您必须建立“静默间隔”。这意味着如果用户没有说话的时间超过您的间隔时间,他就停止了说话(即 2 秒)。

audio session的开头创建一个定时器

var timer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "didFinishTalk", userInfo: nil, repeats: false)

当您在recognitionTaskinvalidate 中获得新的转录并重新启动您的计时器时

timer.invalidate() timer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "didFinishTalk", userInfo: nil, repeats: false)

如果计时器到期,这意味着用户在 2 秒内没有说话。您可以安全地停止音频会话并退出

【讨论】:

为什么苹果会发现这个凝灰岩?只需要实现有用的委托方法。 FWIW,可以通过更新其fireDate 属性来延迟它,而不是使计时器失效并重新创建。 对我来说似乎是一个重大失败。使用这些预定的计时器感觉就像是 hack 在此路径中执行时会出现一些同步问题。假设我们在客户端或服务器端有一些互联网连接问题,最好听音频而不是重置话语回调上的计时器。 如果 Apple 有半个大脑,他们会暴露一些 seconds_silence_to_trigger_did_finish_utterance_callback 变量并内化这个计时器机制。【参考方案2】:

根据我在 iOS10 上的测试,当 shouldReportPartialResults 设置为 false 时,需要等待 60 秒才能得到结果。

【讨论】:

【参考方案3】:

我目前正在一个应用程序中使用 Speech to text,它对我来说运行良好。我的识别任务块如下:

recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler:  (result, error) in
        var isFinal = false

        if let result = result, result.isFinal 
            print("Result: \(result.bestTranscription.formattedString)")
            isFinal = result.isFinal
            completion(result.bestTranscription.formattedString, nil)
        

        if error != nil || isFinal 
            self.audioEngine.stop()
            inputNode.removeTap(onBus: 0)

            self.recognitionRequest = nil
            self.recognitionTask = nil
            completion(nil, error)
        
    )

【讨论】:

这不是问题的反面吗?问题是关于语音识别的,这似乎涵盖了语音合成。 哎呀。我的答案已被编辑。一直在研究语音到文本和文本到语音的东西,只是感到困惑。阅读 OP 对代表的评论并立即想到这一点。 completion() 如何在两个地方工作?【参考方案4】:
if result != nil 
    self.timerDidFinishTalk.invalidate()
    self.timerDidFinishTalk = Timer.scheduledTimer(timeInterval: TimeInterval(self.listeningTime), target: self, selector:#selector(self.didFinishTalk), userInfo: nil, repeats: false)

    let bestString = result?.bestTranscription.formattedString

    self.fullsTring =  bestString!.trimmingCharacters(in: .whitespaces)
    self.st = self.fullsTring
  

这里的self.listeningTime 是您在讲话结束后想要停止的时间。

【讨论】:

以上是关于SFSpeechRecognizer - 检测话语结束的主要内容,如果未能解决你的问题,请参考以下文章

iOS 应用程序上的 SFSpeechRecognizer(Siri 转录)超时错误

在 AVSpeechUtterance 之后使用 SFSpeechRecognizer 时出现 AVAudioSession 问题

从 SFSpeechRecognizer 获取语音幅度

Swift SFSpeechRecognizer 附加现有的 UITextView 内容

SFSpeechRecognizer kAFAssistantErrorDomain Code=203 "重试"

从训练数据中分类聊天机器人随机话语的意图,并使用随机森林给出不同的图形可视化?