多次调用SpeechKit函数结果

我正在使用SpeechKit将语音返回到文本列表中。例如列出杂货店清单。但是我不断获得多个价值。我没什么问题我知道该函数仅被调用一次,但是它返回多个值。下面是它的外观和代码的gif图像。请给我一些指导。

多次调用SpeechKit函数结果

func prepareAudioEngine() {
    let node = audioEngine.inputNode
    let recordingFormat = node.outputFormat(forBus: 0)
    node.installTap(onBus: 0,bufferSize: 1024,format: recordingFormat) { (buffer,_) in
        self.request.append(buffer)
    }

    audioEngine.prepare()
    do {
        try audioEngine.start()
    } catch {
        return print(error)
    }

    guard let myRecogizer = speechRecognizer else { return }

    if !myRecogizer.isAvailable {
        return
    }

    recordandRecognizeSpeech()
}

func recordandRecognizeSpeech() {
    recognitionTask = speechRecognizer?.recognitionTask(with: request,resultHandler: { (result,error) in
        if let result = result {
            let stringArray = result.bestTranscription.formattedString
            let size = stringArray.reversed().firstIndex(of: " ") ?? stringArray.count
            let startWord = stringArray.index(stringArray.endIndex,offsetBy: -size)
            let last = stringArray[startWord...]
            self.detectedTextLabel.text = String(last).capitalized

        } else if let error = error {
            print("There was an error",error)
        }

        self.ingredients.append(Ingredient(name: self.detectedTextLabel.text ?? "Default",imageName: "?"))
        let indexPath = IndexPath(item: self.ingredients.count - 1,section: 0)
        self.tableView.insertRows(at: [indexPath],with: .automatic)
    })
}
pumplee 回答:多次调用SpeechKit函数结果

因此,我认为这是在request.shouldReportPartialResults = true时,随着SpeechRecognizer解析它们而返回多个SFSpeechRecognitionResult的结果。将您的recognitionTask代码替换为以下内容:

        let df = DateFormatter()
        df.dateFormat = "y-MM-dd H:m:ss.SSSS"
        recognitionTask = speechRecognizer?.recognitionTask(with: request,resultHandler: { (result,error) in
            if let result = result {
                let d = Date()
                print(df.string(from: d)) // -> "2016-11-17 17:51:15.1720"
                print("isFinal: \(result.isFinal)")
                for (isegment,segment) in result.bestTranscription.segments.enumerated() {
                    print("\(isegment): \(segment.substring) (ts \(segment.timestamp),dur \(segment.duration),conf \(segment.confidence)")
                }

            } else if let error = error {
                print("There was an error",error)
            }
        })

在iPad上进行测试时,还要检查Xcode控制台的输出...

这是我启动音频引擎时看到的内容,说:“嘿,”,暂时停顿一下(约1秒钟),然后说“你听到了我的声音”

2020-06-07 17:31:14.0330
isFinal: false
0: Hey (ts 0.0,dur 0.0,conf 0.0)
2020-06-07 17:31:14.2190
isFinal: false
0: Hey (ts 0.0,conf 0.0)
1: do (ts 0.0,conf 0.0)
2020-06-07 17:31:14.2560
isFinal: false
0: Hey (ts 0.0,conf 0.0)
2020-06-07 17:31:14.5600
isFinal: false
0: Hey (ts 0.0,conf 0.0)
2020-06-07 17:31:14.6690
isFinal: false
0: Hey (ts 0.0,conf 0.0)
2020-06-07 17:31:14.7930
isFinal: false
0: Hey (ts 0.55,dur -0.55,conf 0.745)
1: do (ts 0.84,dur -0.84,conf 0.816)
2020-06-07 17:31:15.6900
isFinal: false
0: Hey (ts 0.0,conf 0.0)
2: you (ts 0.0,conf 0.0)
2020-06-07 17:31:15.8630
isFinal: false
0: Hey (ts 0.0,conf 0.0)
3: hear (ts 0.0,conf 0.0)
2020-06-07 17:31:16.1120
isFinal: false
0: Hey (ts 0.0,conf 0.0)
4: me (ts 0.0,conf 0.0)
2020-06-07 17:31:16.1950
isFinal: false
0: Hey (ts 0.55,conf 0.93)
1: do (ts 0.84,conf 0.915)
2: you (ts 1.92,dur -1.92,conf 0.927)
3: hear (ts 2.2800000000000002,dur -2.2800000000000002,conf 0.932)
4: me (ts 2.5100000000000002,dur -2.5100000000000002,conf 0.923)

等一会儿(〜2秒),然后停止audioEngine:

2020-06-07 17:31:18.4710
isFinal: false
0: Hey (ts 0.55,conf 0.923)
2020-06-07 17:31:18.5200
isFinal: true
0: Hey (ts 0.55,dur 0.2899999999999999,dur 0.42000000000000004,dur 0.3600000000000003,dur 0.22999999999999998,dur 0.3099999999999996,conf 0.923)

注意几件事:

  • result仍在“解析”(或发生的任何事情)时,SFTranscriptionSegment上的时间戳为0.0
  • 当解析器对它们感到满意时,所有时间戳都变为合理的值。
  • 随着更多音频的馈入,添加了其他片段。这些时间戳最终变为有效,正如您所期望的,我们获得了带有单调递增时间戳的令牌列表。先前解析的音频段报告的时间戳保持不变。
  • result上的isFinal标志只有在audioEngine停止时才为True。

不幸的是,我没有在SFTranscriptionSegmentSFSpeechRecognitionResult类中看到任何其他标志来帮助区分“仍在解析中”与“好,我已经完成了”。 / p>

推荐

对于实时处理转录,我建议根据其时间戳过滤结果。保留令牌和时间戳(或其他内容)的输出列表,并且仅在令牌以较大的时间戳到达时才添加到列表中。

我希望在RecognitionTask决定在整个音频片段的末尾确定要从片段的开头更改单词的情况下,这种情况可能会崩溃。然后,您将在该段的早期获得更改的令牌和时间戳。

对于您的特定情况,如果音频中有一段时间没有声音,则停止audioEngine并重新启动它可能会有所帮助。这将迫使RecognitionTask完成音频的解析,并确保片段/时间戳/令牌不发生变化。

本文链接:https://www.f2er.com/3126550.html

大家都在问