29

我正在使用 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
}
4

4 回答 4

25

当用户按预期停止说话时,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 秒内没有说话。您可以安全地停止音频会话并退出

于 2017-03-21T11:21:12.117 回答
4

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

于 2018-09-03T08:33:11.230 回答
2

我目前正在一个应用程序中使用 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)
        }
    })
于 2018-04-24T14:47:24.473 回答
0
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是您想要在话语结束后停止的时间。

于 2020-07-31T07:15:13.507 回答