使用 JS 语音识别构建虚拟助手

2025-06-08

使用 JS 语音识别构建虚拟助手

新的学年即将开始,我的妻子(一位高中西班牙语老师)对她的课程有了个想法。所以,让我向大家介绍我们的最新作品:教师助理弗里达 (Frida)。一个动画角色,她会用西班牙语聆听并回答一些基本问题。

弗里达·卡罗的漫画

该漫画基于El Creata 的插图
 

它是使用原生 JavaScript 和内联 SVG 构建的。遗憾的是,目前它只能在特定浏览器中运行,因为它使用了两个尚未得到广泛支持的实验性 Web API(语音合成语音识别)。

它仍在开发中,需要不断完善,但看起来有望实现我们的需求。毕竟,它只用了一个下午就快速开发完成(包括 SVG),HTML、JS 和 CSS 代码不到 250 行。

在我们继续之前,这是 Frida 的一个演示(要查看正在运行的演示,请转到本文底部):

为什么选择 JavaScript?为什么选择 Frida?

拥有一个能够分析语音并做出相应回复的虚拟助手,听起来需要的不仅仅是原生 JavaScript。即使有可能,构建这样的东西可能也有更好的替代方案……但我们还是遇到了一些限制。

该助理是为一所高中服务的,学校 IT 部门有限制:

  • 我们无法安装任何软件。因此,开发应用程序是不可能的,这极大地限制了我们可以使用的技术。
  • 我们无法访问某些网站,因为学校防火墙阻止了其中的许多网站(在某些情况下,列表有点荒谬。)
  • 我们无法将内容导入网站(这与上一点相关)。

我们以前曾在学校的网络工具中嵌入过原生 JavaScript,所以这看起来是个不错的选择。而且,它还能把学习曲线降低到只需要 Web Speech API 的程度。

我们并没有期待太多。毕竟,我们想要的是简单的东西。不过,我不得不承认,结果比我们预期的要好得多。

为什么选择弗里达·卡罗?这个助教是西班牙语课的,我们想要一个与西班牙语和西班牙文化相关的、容易辨认的人物。弗里达·卡罗的漫画很符合这个要求……而且画起来也很简单。

你可能已经注意到,我们的大多数决策都有一个规律。大多数决策都基于这样一个问题:“这个问题最简单的解决方案是什么?” 一开始没必要把事情搞得太复杂(反正以后总会有的)。

语音识别 API

语音识别 API 非常庞大,本文不会深入探讨。我们只会查看与虚拟助手相关的代码。访问MDN 网站,了解更多关于该 API 的信息

这是语音识别代码的简化版本:

// new speech recognition object in Spanish!
var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.lang = "es";

recognition.onstart = function () {
  // actions to be performed when speech recognition starts
};

recognition.onspeechend = function () {
  // stop speech recognition when the person stops talking
  recognition.stop();
}

recognition.onresult = function (event) {
  // get the results of the speech recognition
  const transcript = event.results[0][0].transcript.toLowerCase();
  const confidence = event.results[0][0].confidence;

  // perform actions based on transcript and level of confidence
}
Enter fullscreen mode Exit fullscreen mode

出于安全考虑,语音识别代码只能在用户触发事件后执行。这很合理。我们不希望网站在用户不知情的情况下监听他们的对话(尽管他们会被要求提供麦克风访问权限)。

为了解决这个问题,我们添加了一个占据整个屏幕的按钮,单击该按钮即可启动语音识别:

recognition.start();
Enter fullscreen mode Exit fullscreen mode

这样,老师就可以在教室里走动,用鼠标或指针点击按钮。然后,他们可以模拟与助手的对话,或者让学生提出一些要求。

此外,我们可以使用语音识别事件来为助手添加动画效果,并在其聆听时执行某些操作。例如,弗里达扬起了眉毛(这可能是一个错误,因为它会让她看起来像是已经结束了对话。)

现在,我们来谈谈兼容性和支持。Chromium和最新版本的 Safari 支持语音识别 API ,但 Firefox 和大多数移动浏览器不支持:

caniuse.com 的屏幕截图显示了对语音识别 API 的支持

由于用户(老师)拥有并且将专门使用支持该功能的浏览器(Chrome),因此这对我们来说不是问题。

语音合成API

与语音识别 API 一样,这不会是深入探讨,而是助手如何使用 API 的演示。

我们的助理接下来的任务是回答老师和学生的问题。当然,我们可以录下所有答案,并在合适的时间播放,但那样会很费时间,也有点麻烦……而且,别忘了,我们一直在寻找一种更简单的方案。

最简单的解决方案是使用语音合成 API:为什么每次处理新功能时都要记录一个又一个句子?如果计算机能够读取我们提供的任何短语,那不是更好吗?

而且代码比我们想象的要简单得多。四行代码就帮我们说出了以下几句话:

let speech = new SpeechSynthesisUtterance();
speech.lang = "es";
speech.text = "This is the text to read.";
window.speechSynthesis.speak(speech);
Enter fullscreen mode Exit fullscreen mode

与语音识别 API 类似,在使用语音合成 API 之前,我们需要等待用户交互。幸运的是,我们可以将这两个操作集成到同一个事件中:点击按钮后,助手会监听并处理语音;语音处理完毕并转换为文本后,我们就可以让助手说话了。

语音合成 API 远比这四行代码复杂得多。它允许完全自定义语音:速度、音调,甚至可以从可用列表中选择语音。

在我们的例子中,默认速度很好。对于母语人士来说可能有点慢,但对于学生来说还可以。我们主要关注的是语音本身。Frida 是女声,但默认语音取决于许多因素(浏览器、语言),在某些情况下,它可能是男声。但我们可以通过指定voice属性来选择它。

让我们来谈谈支持。虽然语音合成 API 仍处于实验阶段,但它已得到广泛支持(它兼容95% 的浏览器!),所以这根本不是问题:

caniuse.com 的屏幕截图显示了对语音合成器 API 的支持

我们可以使用(而且我们也确实使用了)语音合成器事件为助手添加更多动画。例如,在计算机朗读文本时让她的嘴唇动起来……虽然这有点麻烦,因为时间安排并非 100% 准确,但我们需要让它与 CSS 动画匹配,以避免出现奇怪的跳跃。虽然不是很理想,但仍然可行。

这不是人工智能!只是一堆条件语句而已

网上有一个关于人工智能和if声明的笑话:

电视剧《史酷比》的截图,一个角色正在摘下一个人的面具。面具上写着

人工智能 (AI) 一词经常被误用(图片来源

这正是我们的助手。我们不会假装它是人工智能。它并非真正的人工智能,而是一堆链式条件语句(甚至不是嵌套的)。

一旦我们获得语音识别的结果,我们就会得到两个值:语音文本本身以及系统对识别结果的置信度。我们注意到,当置信度高于 75% 时,结果通常比较好。

如果是这种情况,那么我们会检查成绩单中的子字符串:

  • 现在是奌?
  • 今天天气预报怎么样
  • 今天星期
  • 今天星期
  • 谁是最好的老师

并使用其他 JavaScript API 或预定义句子将它们与自动生成的答案进行匹配:

// default text
let textToSpeak = "Sorry, I didn't understand.";

if (confidence > 0.75) {
  if (transcript.indexOf("time") > -1) {
    const d = new Date();
    const hours = d.getHours();
    let minutes = d.getMinutes();
    if (minutes === 0) minutes = "o'clock";
    textToSpeak = `It is ${hours} ${minutes}`;
  } else if (transcript.indexOf("best teacher") > -1) {
    textToSpeak = "Miss Montoro is the best teacher";
  } else if...
}

// Speech Synthesis code goes here
Enter fullscreen mode Exit fullscreen mode

语音识别 API 允许使用语法来对结果进行分类。虽然我们现在没有使用它们(if当时的说法似乎更简单),但对于第二个版本来说,这可能是一个令人兴奋的增强功能。

正在运行的演示。下一步是什么?

以下是教师助理 Frida 的演示

注意:由于iframe安全策略原因,该演示在 DEV 版本中嵌入时可能无法运行。点击上方链接或在 CodePen 上编辑即可查看运行效果。

作为一款最低可行产品,这款课堂助手功能尚可,但远未完善。以下是我们考虑改进的一些方面:

  • 添加更多句子和问题以理解
  • 向语音识别系统添加语法,以便我们可以简化代码(并删除丑陋的条件)
  • 添加自定义/设置,以便其他教师可以在小更新后使用它。
  • 使用其他 Web API 扩展新功能。我们有一些想法:
    • 检测环境噪音,如果达到阈值,让弗里达看起来很生气并说:“请安静!”
    • 根据日期和天气为弗里达穿上不同的衣服。
    • 让弗里达变得更友善一些(在动画片中她总是看起来很生气。)
    • 添加一个包含学生姓名的列表,以便 Frida 可以随机叫他们回答问题/进行测试。
鏂囩珷鏉ユ簮锛�https://dev.to/alvaromontoro/using-js-speech-recognition-to-build-a-virtual-assistant-1957
PREV
使用 CSS 😜 将自定义表情符号用作光标。
NEXT
我的 2022 年十月节绘画作品