如何重置SFSpeechAudioBufferRecognitionRequest缓冲区?无需销毁对象
问题
我编写了如下record函数:
func record(sketchVM: SketchViewModel, isRecording: Binding<Bool>) { // MARK: 1. Create a recognizer. guard let recognizer = SFSpeechRecognizer(), recognizer.isAvailable else { handleError(withMessage: "Speech recognizer not available.") return } // MARK: 2. Create a speech recognition request. recognitionRequest = SFSpeechAudioBufferRecognitionRequest() guard let recognitionRequest = recognitionRequest else { return } recognitionRequest.shouldReportPartialResults = true recognizer.recognitionTask(with: recognitionRequest) { result, error in guard error == nil else { self.handleError(withMessage: error!.localizedDescription); return } guard let result = result else { return } print("got a new result: \(result.bestTranscription.formattedString), final : \(result.isFinal)") } // MARK: 3. Create a recording and classification pipeline. audioEngine = AVAudioEngine() guard let audioEngine = audioEngine else { return } inputNode = audioEngine.inputNode guard let inputNode = inputNode else { return } let recordingFormat = inputNode.outputFormat(forBus: 0) inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in self.recognitionRequest?.append(buffer) } // Build the graph. audioEngine.prepare() // MARK: 4. Start recognizing speech. do { // Activate the session. audioSession = AVAudioSession.sharedInstance() guard let audioSession = audioSession else { return } try audioSession.setActive(false) try audioSession.setCategory(.record, mode: .default) try audioSession.setActive(true, options: .notifyOthersOnDeactivation) // Start the processing pipeline. try audioEngine.start() Task { @MainActor in isRecording.wrappedValue = true } } catch { handleError(withMessage: error.localizedDescription) } }
该函数功能正常,但result.bestTranscription会持续追加之前的录音内容。我希望重启录音,但不想销毁所有会话、请求、引擎对象,请问是否可以在保留这些对象的前提下,清除已保存的录音内容?
解决方案
不行,没办法在保留现有SFSpeechAudioBufferRecognitionRequest和识别任务的前提下清除已积累的转录内容——因为SFSpeechRecognitionTask和请求是绑定的,请求一旦开始接收音频缓冲区,转录结果就会持续累加,苹果没有提供公开API来重置这个状态。
不过你不需要销毁所有对象,只需要重置识别请求和任务,音频引擎和AVAudioSession可以保留复用,步骤如下:
1. 先停止当前的识别任务与音频输入
先把正在运行的识别任务结束,移除音频输入节点的tap并停止引擎:
// 建议在类中添加属性保存当前的识别任务 var recognitionTask: SFSpeechRecognitionTask? private func resetCurrentRecording() { // 结束旧的识别任务 recognitionTask?.finish() recognitionTask = nil // 移除输入节点的tap,避免重复安装导致崩溃 inputNode?.removeTap(onBus: 0) // 停止音频引擎 audioEngine?.stop() }
2. 复用引擎与会话,重新创建请求和任务
重启录音时,不需要重新初始化audioEngine和audioSession,只需要重新创建识别请求和任务,再重新配置输入tap并启动引擎:
func restartRecording(sketchVM: SketchViewModel, isRecording: Binding<Bool>) { resetCurrentRecording() guard let recognizer = SFSpeechRecognizer(), recognizer.isAvailable else { handleError(withMessage: "Speech recognizer not available.") return } // 重新创建识别请求 recognitionRequest = SFSpeechAudioBufferRecognitionRequest() guard let recognitionRequest = recognitionRequest else { return } recognitionRequest.shouldReportPartialResults = true // 重新创建识别任务并保存引用 recognitionTask = recognizer.recognitionTask(with: recognitionRequest) { result, error in guard error == nil else { self.handleError(withMessage: error!.localizedDescription); return } guard let result = result else { return } print("got a new result: \(result.bestTranscription.formattedString), final : \(result.isFinal)") } // 重新安装输入tap guard let inputNode = audioEngine?.inputNode else { return } let recordingFormat = inputNode.outputFormat(forBus: 0) inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in self.recognitionRequest?.append(buffer) } audioEngine?.prepare() do { // 复用已有的AVAudioSession,无需重复设置类别(只要之前配置正确) try audioSession?.setActive(true, options: .notifyOthersOnDeactivation) try audioEngine?.start() Task { @MainActor in isRecording.wrappedValue = true } } catch { handleError(withMessage: error.localizedDescription) } }
关键注意点
SFSpeechAudioBufferRecognitionRequest是一次性对象,一旦开始接收音频就无法重置内部缓存,必须重新创建。- 音频引擎和AVAudioSession可以安全复用,只要在重启前正确停止引擎、移除tap,就能避免资源泄漏和崩溃。
- 一定要调用
recognitionTask?.finish()结束旧任务,否则会导致资源占用、识别结果混乱,甚至新任务无法正常启动。
内容的提问来源于stack exchange,提问作者erotsppa
相关产品推荐
相关产品推荐

