繁体   English   中英

SFSpeechRecognizer - 检测话语结束

[英]SFSpeechRecognizer - detect end of utterance

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

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

SFSpeechRecognizer是否能够检测到句子的结尾?

这是我的代码 - 它基于互联网上的示例,它主要是从麦克风源识别所需的样板。 我通过添加识别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
}

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

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

  • 你必须建立一个“沉默的间隔”。 这意味着如果用户没有说话的时间超过您的间隔时间,则他已经停止说话(即 2 秒)。

  • audio session开始时创建一个计时器

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

  • 当您在recognitionTask中获得新的转录时任务无效并重新启动您的计时器

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

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

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

我目前正在一个应用程序中使用 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)
        }
    })
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是你想要在话语结束后停止的时间。

我有一种不同的方法,我发现在确定识别任务何时完成猜测时更可靠: confidence分数。

shouldReportPartialResults设置为 true 时,部分结果的置信度分数将为0.0 只有最终的猜测会以超过 0 的分数返回。

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

    if let result = result {
        let confidence = result.bestTranscription.segments[0].confidence
        print(confidence)
        self.transcript = result.bestTranscription.formattedString
    }

}

上面的segments数组包含转录中的每个单词。 0是最安全的检查索引,所以我倾向于使用那个。

你如何使用它取决于你,但如果你只想知道猜测者何时完成猜测,你可以调用:

let myIsFinal = confidence > 0.0 ? true : false

您还可以查看分数(100.0 完全有信心)并将响应分组为低 -> 高置信度猜测组,如果这有助于您的应用程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM