iOS项目中SFSpeechRecognizer运行数分钟后失效问题求助
Hey Jerry, let's tackle this frustrating issue you're facing with SFSpeechRecognizer. Based on what you described—initial success then sudden failure after 1-2 minutes, plus you're storing recognized words in an array for analysis—here are the most likely fixes to check:
1. 检查识别请求与任务的生命周期管理
This is the #1 culprit when modifying Apple's sample code for continuous recognition. If you're not properly cleaning up old tasks or reusing requests incorrectly, the recognizer can get stuck or stop receiving input.
- Use class-level variables for
recognitionRequestandrecognitionTask(avoid local variables that get deallocated mid-session). - Cancel and reset old tasks before starting a new session to avoid conflicts.
- Handle final results/errors properly—don't leave hanging tasks that block new input.
Here's a cleaned-up snippet of how to manage this:
import Speech import AVFoundation class SpeechManager: NSObject { private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))! private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? private var recognitionTask: SFSpeechRecognitionTask? private let audioEngine = AVAudioEngine() var recognizedWords: [String] = [] // Your word storage array func startContinuousRecognition() { // Step 1: Clean up existing tasks/requests if let recognitionTask = recognitionTask { recognitionTask.cancel() self.recognitionTask = nil } recognitionRequest = nil // Step 2: Initialize new recognition request recognitionRequest = SFSpeechAudioBufferRecognitionRequest() guard let recognitionRequest = recognitionRequest else { fatalError("Failed to create recognition request") } recognitionRequest.shouldReportPartialResults = true // Critical for continuous updates // Step 3: Start recognition task recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { [weak self] result, error in guard let self = self else { return } // Handle recognized results if let result = result { let transcript = result.bestTranscription // Extract words and add to your array for segment in transcript.segments { let wordRange = transcript.formattedString.range(from: segment.range)! let word = String(transcript.formattedString[wordRange]) if !self.recognizedWords.contains(word) { // Avoid duplicates if needed self.recognizedWords.append(word) } } } // Handle errors or final results if error != nil || result?.isFinal == true { print("Recognition ended with error: \(error?.localizedDescription ?? "No error")") // Restart engine to keep continuous recognition self.audioEngine.stop() self.audioEngine.inputNode.removeTap(onBus: 0) self.startContinuousRecognition() } } // Step 4: Configure audio engine input let inputNode = audioEngine.inputNode let recordingFormat = inputNode.outputFormat(forBus: 0) inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, time in self.recognitionRequest?.append(buffer) } audioEngine.prepare() do { try audioEngine.start() } catch { print("Audio engine failed to start: \(error)") } } func stopRecognition() { audioEngine.stop() recognitionRequest?.endAudio() recognitionTask?.cancel() recognitionRequest = nil recognitionTask = nil } }
2. 排查音频引擎的运行状态
If the AVAudioEngine stops running (due to system interruptions, audio route changes, or unhandled errors), the recognizer will stop receiving audio input entirely. Add checks to confirm the engine is still active when recognition fails:
- Print
audioEngine.isRunningin your error handler to see if it's stopped. - Listen for audio session notifications (like
AVAudioSession.interruptionNotification) to handle interruptions gracefully and restart the engine when needed.
3. 清理你的单词存储数组
While this won't directly break recognition, a continuously growing array can lead to memory bloat over time. If your app hits a memory warning, iOS might terminate the recognition process to free up resources. Add logic to prune the array periodically:
// Example: Keep only the last 100 words to prevent memory overload if recognizedWords.count > 100 { recognizedWords.removeFirst(recognizedWords.count - 100) }
4. 检查识别错误日志
Always log the error returned in the recognitionTask completion handler—this will tell you exactly why recognition stopped. Common issues include:
SFSpeechRecognitionError.network: No internet access (needed for cloud-based recognition).SFSpeechRecognitionError.busy: The recognizer is already in use.SFSpeechRecognitionError.audioSession: Issues with the audio session configuration.
Add this to your completion block to get detailed error info:
if let error = error as? SFSpeechRecognitionError { print("Speech recognition error code: \(error.code.rawValue)") print("Error message: \(error.localizedDescription)") }
Start with checking the error logs first—they'll give you the clearest clue about what's going wrong. Then verify your task/request lifecycle and audio engine state. That should get your continuous recognition running smoothly again!
内容的提问来源于stack exchange,提问作者Jerry Chang

