iOS 18下SFSpeechRecognitionResult长停顿丢失历史转录内容求助
iOS 18 SFSpeechAudioBufferRecognitionRequest 长停顿丢失转录内容问题
问题分析
这是iOS 18语音识别引擎的行为变更,并非你的代码错误——你的实现完全符合苹果官方示例。在iOS 18中,当使用SFSpeechAudioBufferRecognitionRequest进行实时语音识别时,系统会将较长的说话停顿判定为会话中断,导致非最终结果和最终结果都丢弃之前的转录内容,而iOS 17及以前版本会保留完整的连续转录。
解决方案
方案1:调整端点检测级别
通过设置SFSpeechRecognitionRequest的endpointDetectionLevel为.relaxed,让系统更宽松地判断说话结束的时机,避免将正常停顿误判为会话终止:
let request = SFSpeechAudioBufferRecognitionRequest() // 添加这行代码调整端点检测策略 request.endpointDetectionLevel = .relaxed let audioEngine = AVAudioEngine() let inputNode = audioEngine.inputNode let recordingFormat = inputNode.outputFormat(forBus: 0) inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, when in request.append(buffer) } audioEngine.prepare() try audioEngine.start()
方案2:手动维护转录历史
如果调整端点检测级别无效,需要自行维护全局的转录历史,避免系统重置内容时丢失之前的识别结果:
// 全局变量保存累计的转录内容 private var accumulatedTranscription = "" func recognitionHandler(result: SFSpeechRecognitionResult?, error: Error?) { if let result { let currentTranscription = result.bestTranscription.formattedString if result.isFinal { // 最终结果直接覆盖累计内容 accumulatedTranscription = currentTranscription print(accumulatedTranscription) } else { // 非最终结果:若当前内容未包含历史转录,则拼接 if !currentTranscription.hasPrefix(accumulatedTranscription) && !accumulatedTranscription.isEmpty { accumulatedTranscription += " " + currentTranscription } else { accumulatedTranscription = currentTranscription } print(accumulatedTranscription) } } else if let error { print("识别错误:\(error.localizedDescription)") } else { print("识别任务结束") } }
更精准的实现可以通过SFSpeechTranscriptionSegment的时间戳来判断新增片段,避免误拼接,但上述代码已能解决大部分场景的问题。
内容的提问来源于stack exchange,提问作者Robert Dresler
相关产品推荐
相关产品推荐

