首页 经验

诗词速通,漫游泡泡,词汇宝,新维日语,简易物理,点此下载


LocalSpeechRecognizer对比

时间: 2026-04-16 13:26:54

(部分内容来自网络,其真实性存疑,为了避免对您造成误导,请谨慎甄别。)

好的,我来一行行对比你的两个 LocalSpeechRecognizer


📋 完整 Diff 对比


行号坏的版本(不录音)好的版本(能录音)
1import Speechimport Speech ✅ 相同
2import AVFoundationimport AVFoundation ✅ 相同
3(空行)(空行) ✅ 相同
4class LocalSpeechRecognizer: NSObject, ObservableObject {class LocalSpeechRecognizer: NSObject, ObservableObject { ✅ 相同
5@Published var isRecognizing = false@Published var isRecognizing = false ✅ 相同
6@Published var recognizedText = ""@Published var recognizedText = "" ✅ 相同
7@Published var errorMessage: String?@Published var errorMessage: String? ✅ 相同
8(空行)(空行) ✅ 相同
9private var speechRecognizer: SFSpeechRecognizer?private var speechRecognizer: SFSpeechRecognizer? ✅ 相同
10private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? ✅ 相同
11private var recognitionTask: SFSpeechRecognitionTask?private var recognitionTask: SFSpeechRecognitionTask? ✅ 相同
12private let audioEngine = AVAudioEngine()private let audioEngine = AVAudioEngine() ✅ 相同
13(空行)(空行) ✅ 相同
14override init() {override init() { ✅ 相同
15super.init()super.init() ✅ 相同
16self.speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))self.speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US")) ✅ 相同
17self.speechRecognizer?.delegate = selfself.speechRecognizer?.delegate = self ✅ 相同
18}} ✅ 相同
19(空行)(空行) ✅ 相同
20func setLanguage(locale: String) {func setLanguage(locale: String) { ✅ 相同
21guard !isRecognizing else {guard !isRecognizing else { ✅ 相同
22errorMessage = "请先停止录音再切换语言"errorMessage = "请先停止录音再切换语言" ✅ 相同
23returnreturn ✅ 相同
24}} ✅ 相同
25speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: locale))speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: locale)) ✅ 相同
26speechRecognizer?.delegate = selfspeechRecognizer?.delegate = self ✅ 相同
27print("已切换到语言: $locale)")print("已切换到语言: $locale)") ✅ 相同
28}} ✅ 相同
29(空行)(空行) ✅ 相同
30func checkAuthorization() {func checkAuthorization() { ✅ 相同
31(空行)(空行) ✅ 相同
32AVAudioSession.sharedInstance().requestRecordPermission { granted inAVAudioSession.sharedInstance().requestRecordPermission { granted in ✅ 相同
33print("麦克风权限: $granted)")print("麦克风权限: $granted)") ✅ 相同
34}} ✅ 相同
35(空行)(空行) ✅ 相同
36SFSpeechRecognizer.requestAuthorization { [weak self] status inSFSpeechRecognizer.requestAuthorization { [weak self] status in ✅ 相同
37DispatchQueue.main.async {DispatchQueue.main.async { ✅ 相同
38switch status {switch status { ✅ 相同
39case .authorized:case .authorized: ✅ 相同
40print("语音识别权限已授权")print("语音识别权限已授权") ✅ 相同
41case .denied:case .denied: ✅ 相同
42self?.errorMessage = "请在设置中开启语音识别权限"self?.errorMessage = "请在设置中开启语音识别权限" ✅ 相同
43case .restricted:case .restricted: ✅ 相同
44self?.errorMessage = "设备不支持语音识别"self?.errorMessage = "设备不支持语音识别" ✅ 相同
45case .notDetermined:case .notDetermined: ✅ 相同
46print("语音识别权限未确定")print("语音识别权限未确定") ✅ 相同
47@unknown default:@unknown default: ✅ 相同
48self?.errorMessage = "未知错误"self?.errorMessage = "未知错误" ✅ 相同
49}} ✅ 相同
50}} ✅ 相同
51}} ✅ 相同
52(空行)(空行) ✅ 相同
53func startRecording(completion: @escaping (String) -> Void) {func startRecording() throws {不同!
54guard !isRecognizing else { return }guard !isRecognizing else { return } ✅ 相同
55(空行)(空行) ✅ 相同
56if recognitionTask != nil {guard let speechRecognizer = speechRecognizer, speechRecognizer.isAvailable else {不同!
57recognitionTask?.cancel()throw NSError(...)不同!
58recognitionTask = nil}不同!
59}(空行) ❌ 不同!
60(空行)if recognitionTask != nil {不同!
61guard let speechRecognizer = speechRecognizer, speechRecognizer.isAvailable else {recognitionTask?.cancel()不同!
62DispatchQueue.main.async {recognitionTask = nil不同!
63self.errorMessage = "请开启 Siri 和听写权限"}不同!
64completion("")(空行) ❌ 不同!
65}let audioSession = AVAudioSession.sharedInstance() ✅ 相同(位置不同)
66returntry audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)不同!
67}try audioSession.setActive(true, options: .notifyOthersOnDeactivation)不同!
68(空行)(空行) ✅ 相同
69DispatchQueue.main.async {recognitionRequest = SFSpeechAudioBufferRecognitionRequest() ✅ 相同(位置不同)
70self.isRecognizing = trueguard let recognitionRequest = recognitionRequest else {不同!
71self.recognizedText = ""throw NSError(...)不同!
72}}不同!
73(空行)(空行) ✅ 相同
74let audioSession = AVAudioSession.sharedInstance()recognitionRequest.shouldReportPartialResults = true ✅ 相同(位置不同)
75do {recognitionRequest.requiresOnDeviceRecognition = true ✅ 相同(位置不同)
76try audioSession.setCategory(.record, mode: .default)(空行) ❌ 不同!
77try audioSession.setActive(true)let inputNode = audioEngine.inputNode ✅ 相同(位置不同)
78} catch {let recordingFormat = inputNode.outputFormat(forBus: 0) ✅ 相同(位置不同)
79print("音频会话失败: $error)")(空行) ❌ 不同!
80DispatchQueue.main.async {inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in不同!
81self.isRecognizing = falserecognitionRequest.append(buffer)不同!
82completion("")}不同!
83}(空行) ❌ 不同!
84returnaudioEngine.prepare() ✅ 相同(位置不同)
85}try audioEngine.start() ✅ 相同(位置不同)
86}(空行) ❌ 不同!
87(空行)isRecognizing = true ✅ 相同(位置不同)
88recognitionRequest = SFSpeechAudioBufferRecognitionRequest()(空行) ❌ 不同!
89guard let recognitionRequest = recognitionRequest else {recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { [weak self] result, error in不同!
90DispatchQueue.main.async {DispatchQueue.main.async { ✅ 相同
91self.isRecognizing = falseif let result = result { ✅ 相同(位置不同)
92completion("")self?.recognizedText = result.bestTranscription.formattedString ✅ 相同(位置不同)
93}} ✅ 相同
94return(空行) ❌ 不同!
95}if error != nil(result?.isFinal ?? false) { ✅ 相同(位置不同)
96}_ = self?.stopRecording() ✅ 相同(位置不同)
97(空行)} ✅ 相同
98recognitionRequest.shouldReportPartialResults = false} ✅ 相同
99recognitionRequest.requiresOnDeviceRecognition = false} ✅ 相同
100(空行)(空行) ✅ 相同
101let inputNode = audioEngine.inputNode}不同!
102let recordingFormat = inputNode.outputFormat(forBus: 0)(文件结束) ❌ 不同!
103(空行)
104inputNode.removeTap(onBus: 0)
105inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, when in
106recognitionRequest.append(buffer)
107}
108(空行)
109audioEngine.prepare()
110do {
111try audioEngine.start()
112print("✅ 录音已启动")
113} catch {
114print("音频引擎启动失败: $error)")
115DispatchQueue.main.async {
116self.isRecognizing = false
117completion("")
118}
119return
120}
121(空行)
122recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in
123DispatchQueue.main.async {
124if let result = result {
125if result.isFinal {
126let text = result.bestTranscription.formattedString
127print("✅ 识别结果: $text)")
128self.stopRecording()
129completion(text)
130}
131} else if let error = error {
132print("识别错误: $error.localizedDescription)")
133self.stopRecording()
134completion("")
135}
136}
137}
138}


🎯 核心区别(一句话总结)


坏的版本(不录音)好的版本(能录音)
startRecording(completion: @escaping (String) -> Void)startRecording() throws
音频会话用 mode: .default音频会话用 mode: .measurement, options: .duckOthers
requiresOnDeviceRecognition = falserequiresOnDeviceRecognition = true
inputNode.removeTap(onBus: 0)没有这行
回调里只处理 result.isFinal回调里实时更新 recognizedText


把坏的版本的 startRecording 方法整个替换成好的版本的 startRecording 方法就行了。


还有问题,向AI提问。


上一个 App Store Rejection Explanation 文章列表 下一个 苹果阿里合作AI功能

(汉语/英语/日语/法语/德语)语音助手(识别/合成),智能翻译,高中物理动画,数据分析,数据可视化,电话: 18201798243(同v)

© 2019-至今 适观科技

沪ICP备17002269号