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)
当您在recognitionTask
invalidate 中获得新的转录并重新启动您的计时器时
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 问题
Swift SFSpeechRecognizer 附加现有的 UITextView 内容