SpeechRecognitionEngine 默认不监听麦克风,需显式调用 SetInputToDefaultAudioDevice();中文识别依赖系统中文语言包,语法应加载于设输入后、识别前;SpeechRecognizer 适合前台应用,SpeechRecognitionEngine 用于后台或自定义音频流。

System.Speech.Recognition 为什么识别不了麦克风输入
默认情况下,SpeechRecognitionEngine 不自动监听系统麦克风,它需要你显式指定输入源。如果你只初始化了引擎但没调用 SetInputToDefaultAudioDevice() 或 SetInputToWaveFile(),识别器会处于“就绪但无输入”状态,RecognizeAsync() 看似运行却永不触发 SpeechRecognized 事件。
实操建议:
- 必须在
SpeechRecognitionEngine实例化后、调用RecognizeAsync()前,执行recognitionEngine.SetInputToDefaultAudioDevice() - 确保系统默认录音设备已启用且未被其他程序独占(如 Teams、Zoom 占用麦克风会导致
InvalidOperationException: "The audio device is in use") - 若需后台持续识别,推荐用
RecognizeAsync(RecognizeMode.Multiple);仅识别一次用RecognizeMode.Single
如何加载中文语音识别语法(Grammar)
System.Speech 的中文识别依赖于操作系统预装的中文语言包和对应语法定义。直接用 DictationGrammar() 支持自由听写,但准确率低;更可靠的是用 GrammarBuilder 或 Grammar 加载自定义词表或 SGRML 文件。
实操建议:
- 确认系统已安装“中文(简体,中国)”语音识别语言包(控制面板 → 轻松使用 → 语音识别 → 安装语言)
- 用
new Grammar(new GrammarBuilder("打开浏览器"))构建简单命令语法,比纯听写稳定 - 避免在
SpeechRecognitionEngine初始化前加载语法;应在调用SetInputToDefaultAudioDevice()后、RecognizeAsync()前执行LoadGrammar() - 中文识别对语速、静音间隔敏感,建议在
SpeechRecognized事件中检查e.Result.Confidence,过滤低于 0.4 的结果
SpeechRecognitionEngine 和 SpeechRecognizer 的关键区别
SpeechRecognitionEngine 是底层引擎,完全可控但需手动管理音频输入与线程;SpeechRecognizer 是封装好的前台识别器,自动绑定默认麦克风并运行在 UI 线程,适合 WinForms/WPF 快速集成,但不支持后台服务或自定义音频流。
实操建议:
- 开发桌面应用且无需后台运行 → 用
SpeechRecognizer,省去SetInputToDefaultAudioDevice()和线程同步处理 - 需离线运行、自定义音频源(如从文件/网络流读取)、或部署为 Windows Service → 必须用
SpeechRecognitionEngine,并自行处理LoadGrammar()、异常捕获和线程生命周期 - 两者都要求目标机器安装对应语言的 TTS + SR 引擎;仅装了 TTS(文本转语音)无法支撑识别
常见错误:InvalidOperationException: "The recognition engine is not ready"
这个错误通常发生在调用 RecognizeAsync() 时,引擎尚未完成初始化:语法未加载、输入未设置、或上一次识别尚未结束(尤其是 Multiple 模式下重复调用未等待 RecognizeCompleted)。
实操建议:
- 检查
recognitionEngine.State是否为SpeechRecognizerState.Stopped或Ready,非此状态不可调用RecognizeAsync() - 每次
RecognizeAsync()前,确保已调用UnloadAllGrammars()再重新LoadGrammar(),避免语法冲突 - 在
SpeechDetected或SpeechHypothesized事件中不要直接调用RecognizeAsync()—— 这会引发嵌套调用,改用recognitionEngine.RecognizeAsyncStop()+ 延迟重启 - 调试时加一句
Console.WriteLine($"Engine state: {recognitionEngine.State}");,比看异常信息更快定位卡点
C# 的语音识别不是“配好就能用”的功能,System.Speech 对系统环境、语言包、音频设备状态极度敏感。最容易被忽略的是:它不报错也不提示缺语言包,只是静默返回空结果或抛出看似无关的 InvalidOperationException。动手前先确认控制面板里语音识别已成功训练过中文模型。










