You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# 使用Speech Recognition开发语音助手出现循环播报故障如何解决

问题根源

  • 你使用了RecognizeMode.Multiple持续识别模式,麦克风会采集所有音频输入,包括SpeechSynthesizer播报的内容
  • 你的语法库(grammer.txt)包含播报内容里的触发关键词(如Hi、Hello),播报的声音被麦克风采集后会再次触发SpeechRecognized事件,形成“识别→播报→识别播报内容→再次播报”的死循环
  • 你调用RecognizeAsyncCancel()不生效是因为没有在播报前暂停识别,也没有在播报结束后恢复识别,调用时机不符合逻辑

修复方案

你可以任选以下两种方案中的一种解决问题:

方案1:新增播报状态标记位(实现更简单,性能消耗更低)

  1. 首先在Form1类中新增全局状态标记:
// 标记当前是否处于播报状态
bool isSpeaking = false;
  1. 在构造函数中绑定播报完成事件,播报结束后自动重置标记位:
public Form1()
{
    InitializeComponent();
    // ... 保留你原有其他代码
    speech.SelectVoiceByHints(VoiceGender.Male);
    // 新增播报完成事件绑定
    speech.SpeakCompleted += (s, e) => { isSpeaking = false; };
}
  1. 修改识别触发逻辑,播报状态下直接忽略识别结果:
private void RecEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
    // 播报期间直接跳过处理
    if (isSpeaking) return;

    string recognizedText = e.Result.Text;
    string replyContent = "";
    if (recognizedText == "Hello")
    {
        replyContent = "Hi, my name is Jarvis, how can I help you";
    }
    else if (recognizedText == "Hi")
    {
        replyContent = "It is currently " + DateTime.Now.ToLongTimeString();
    }
    // 没有匹配回复直接返回,不播报空内容
    if(string.IsNullOrEmpty(replyContent)) return;

    isSpeaking = true;
    speech.SpeakAsync(replyContent);
    lblresult.Text = replyContent;
    MessageBox.Show("a");
}

方案2:播报时暂停识别,播报结束后恢复

修改识别触发逻辑如下即可:

private void RecEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
    string recognizedText = e.Result.Text;
    string replyContent = "";
    if (recognizedText == "Hello")
    {
        replyContent = "Hi, my name is Jarvis, how can I help you";
    }
    else if (recognizedText == "Hi")
    {
        replyContent = "It is currently " + DateTime.Now.ToLongTimeString();
    }
    if(string.IsNullOrEmpty(replyContent)) return;

    // 播报前先停止识别
    RecEngine.RecognizeAsyncCancel();
    // 播报完成后重新开启识别
    speech.SpeakCompleted += (s, args) => {
        RecEngine.RecognizeAsync(RecognizeMode.Multiple);
    };
    speech.SpeakAsync(replyContent);
    lblresult.Text = replyContent;
    MessageBox.Show("a");
}

额外优化建议

不要用同一个变量存储识别结果和回复内容,避免逻辑混淆;不要给SpeakAsync方法传入空字符串,避免触发无意义的播报。

内容的提问来源于stack exchange,提问作者Kazuya Kimihiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 04:18:05