用AI实现唤醒词检测:从语音到日历事件的完整指南

本文详细介绍了如何使用Web Speech API实现唤醒词检测系统,构建免提语音助手将“Hey Calendar”语音命令转换为Google日历事件,包含连续监听、命令提取和系统集成等核心技术实现。

[第四部分] 文本到行动:用AI实现唤醒词检测

欢迎来到“文本到行动”系列的第四部分,我们正在构建智能系统,利用AI将自然语言转化为现实世界的行动。

在[第一部分]文本到行动:构建智能日历AI助手中,我们通过创建Express.js后端连接Google Calendar API奠定了基础,使我们能够通过暴露的API端点以编程方式创建日历事件。

在[第二部分]文本到行动:文字到日历事件中,我们增加了自然语言处理(NLP)功能,使用户能够输入如“明天下午3点安排团队会议”的描述,让我们的系统智能地将这些文字转化为日历事件。

在[第三部分]文本到行动:为智能日历添加语音控制中,我们通过按住说话界面实现了语音命令,创建了通过直接对系统说话来安排事件的免提方式。

今天,我们正在实现唤醒词检测——这是我们真正实现免提日历管理的首次尝试。只需说“Hey Calendar,明天下午3点安排会议”,无需按下任何按钮。

我们正在构建的内容

我们正在为现有应用程序添加唤醒词检测功能,将:

  • 使用Web Speech API持续监听唤醒短语“Hey Calendar”
  • 检测到唤醒词时自动处理语音命令
  • 提供语音反馈和视觉状态指示器
  • 每次命令后自动重置以便重复使用

重要说明:此实现使用Web Speech API,它提供了即时功能,但在准确性和一致性方面存在限制。

将此视为唤醒词检测的版本1——在第5部分中,我们将使用自定义机器学习模型实现更可靠的解决方案。

演示流程:“Hey Calendar”检测 → 命令提取 → NLP处理 → 日历事件创建 → 语音确认

这创建了一个完整的免提日历助手,能够自然响应语音命令。

唤醒词流程

当您说“Hey Calendar,明天下午2点安排团队会议”时会发生以下情况:

  1. 持续监听:系统持续监控“Hey Calendar”
  2. 检测到唤醒词:捕获完整转录并识别唤醒词
  3. 命令提取:“Hey Calendar”之后的所有内容成为命令
  4. 语音确认:“是的,正在处理您的命令”提供即时反馈
  5. NLP处理:命令发送到现有的/api/text-to-event端点(第2部分)
  6. 日历创建:使用Google Calendar API创建事件(第1部分)
  7. 成功反馈:创建事件的视觉和语音确认
  8. 自动重置:系统返回监听下一个唤醒词

美妙之处在于这需要零后端更改——我们重用了第1-3部分的所有基础设施。

核心实现

设置持续监听

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 检查浏览器兼容性
if (!('webkitSpeechRecognition' in window) && !('SpeechRecognition' in window)) {
  alert('您的浏览器不支持语音识别API。请使用Chrome、Edge或Safari。');
  return;
}

// 初始化语音识别
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();

// 配置持续监听
recognition.continuous = true;
recognition.interimResults = true;
recognition.lang = 'en-US';

// 简单状态管理
let isWakeWordEnabled = false;
let isProcessingCommand = false;
let lastProcessedCommand = '';

唤醒词检测逻辑

我们系统的核心是监听“Hey Calendar”的语音识别处理:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
recognition.onresult = (event) => {
  if (isProcessingCommand) return; // 忙碌时防止处理
  
  let finalTranscript = '';
  
  // 提取最终转录
  for (let i = event.resultIndex; i < event.results.length; i++) {
    if (event.results[i].isFinal) {
      finalTranscript += event.results[i][0].transcript;
    }
  }
  
  // 仅处理最终结果
  if (finalTranscript) {
    processTranscript(finalTranscript.toLowerCase().trim());
  }
};

function processTranscript(transcript) {
  // 防止重复命令处理
  if (transcript === lastProcessedCommand) {
    return;
  }
  
  // 简单但有效的唤醒词检测
  if (transcript.includes('hey calendar')) {
    lastProcessedCommand = transcript;
    handleWakeWordCommand(transcript);
  }
}

命令处理

当检测到唤醒词时,我们提取命令并进行处理:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function handleWakeWordCommand(transcript) {
  isProcessingCommand = true;
  
  // 视觉反馈
  statusEl.textContent = '检测到唤醒词!正在处理命令...';
  
  // 提取唤醒词后的命令
  const command = transcript.replace(/hey calendar,?/gi, '').trim();
  
  if (command) {
    speak('是的,正在处理您的命令。');
    processVoiceCommand(command); // 重用第3部分的功能
  } else {
    speak('我听到了Hey Calendar,但没有命令。请重试。');
    resetToListening();
  }
}

自动重启机制

关键功能是在语音识别停止时自动重启:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
recognition.onend = () => {
  // 如果仍启用且未处理,则自动重启
  if (isWakeWordEnabled && !isProcessingCommand) {
    setTimeout(() => {
      if (isWakeWordEnabled && !isProcessingCommand) {
        try {
          recognition.start();
        } catch (error) {
          // 如果重启失败,延迟后重试
          setTimeout(() => {
            if (isWakeWordEnabled) {
              recognition.start();
            }
          }, 1000);
        }
      }
    }, 100);
  }
};

连接到现有基础设施

我们架构的美妙之处在于唤醒词检测与现有系统无缝集成:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
async function processVoiceCommand(text) {
  try {
    const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
    
    // 发送到第2部分的现有NLP端点
    const response = await fetch('/api/text-to-event', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Timezone': timezone
      },
      body: JSON.stringify({ text })
    });
    
    const data = await response.json();
    
    if (data.success) {
      const eventData = data.eventData;
      speak(`事件已创建:${eventData.summary}。`);
      // 显示成功消息
    } else {
      speak('抱歉,我无法创建该事件。');
    }
    
  } catch (error) {
    speak('抱歉,我无法创建该事件。');
  }
  
  // 自动重置到监听模式
  setTimeout(resetToListening, 2000);
}

请注意,我们只是将识别出的语音文本发送到第2部分中现有的/api/text-to-event端点。这展示了良好架构设计的力量——我们可以添加新的接口模式而无需重新创建核心功能。

架构集成

此实现需要零后端更改:

  • 重用第2部分的/api/text-to-event端点
  • 利用第1部分的Google Calendar集成
  • 使用第3部分的相同语音合成功能
  • 与现有接口并行工作而无冲突

模块化设计允许用户选择他们喜欢的交互方法,同时保持一致的底层系统。

视觉和语音反馈

界面为所有状态提供全面的反馈:

视觉状态指示器

  • 唤醒词:开启 - 绿色圆点带有呼吸动画,主动监听
  • 处理中 - 黄色圆点带有旋转动画,创建日历事件
  • 唤醒词:关闭 - 灰色圆点,系统禁用

语音反馈

  • 启动时“唤醒词检测已启用”
  • 检测到唤醒词时“是的,正在处理您的命令”
  • 成功时“事件已创建:[事件名称]”
  • 出现问题时提供有用的错误消息

实时转录显示

  • 说话时显示实时“正在听取:[文本]”
  • 识别“Hey Calendar”时确认“检测到唤醒词!”
  • 显示正在处理的完整命令

测试您的唤醒词助手

  1. 启动服务器:npm start
  2. 确保Ollama正在运行llama3.2:latest模型
  3. 打开:http://localhost:3000/part-4-wake-word-detection-using-web-speech-api.html
  4. 点击“启用Hey Calendar”
  5. 说:“Hey Calendar,明天下午2点安排团队会议”
  6. 观察视觉指示器并听取语音确认

专业提示

  • 在一个短语中说出完整命令以获得最佳效果
  • 点击示例命令听它们大声朗读
  • 观察指示器圆点:绿色(监听中)、黄色(处理中)、灰色(关闭)
  • 系统对重复命令可靠工作

完整的“文本到行动”旅程

通过实现唤醒词检测,我们的日历AI助手现在提供四种不同的交互模式:

  1. 直接API调用 - 使用结构化JSON请求创建事件(第1部分)
  2. 自然语言文本 - 输入如“明天下午3点安排会议”的命令(第2部分)
  3. 按住说话语音 - 准备就绪时手动语音激活(第3部分)
  4. 始终开启唤醒词 - 使用“Hey Calendar”的免提操作(第4部分)

这种进展展示了现代Web技术如何创建日益复杂的用户体验,每个部分都建立在之前部分的基础上。

有效性与局限性

效果良好

  • 具有自动重启的持续监听
  • 清晰的视觉和语音反馈
  • 与现有日历系统的无缝集成
  • 可靠的重复命令预防

当前局限性

  • Web Speech API准确性因环境而异
  • 偶尔出现类似发音词的误报
  • 需要支持Web Speech API的现代浏览器

这些局限性突显了为什么使用机器学习进行自定义唤醒词检测是有价值的,我们将在未来的部分中探讨。

结论

我们已成功实现唤醒词检测,创建了一个真正的免提日历助手,能够响应“Hey Calendar”命令。虽然这种Web Speech API方法有一些局限性,但它提供了即时功能并展示了始终开启语音界面的核心概念。

完整代码可在GitHub上获取。

下一步:在第5部分中,我们将使用机器学习实现自定义唤醒词检测,以获得更高的准确性、个性化的唤醒短语和更好的环境噪声处理。

资源

  • Web Speech API文档
  • Google Calendar API
  • Ollama文档

在评论中告诉我您接下来想看到什么功能!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计