生成式AI领域的最新成果都在这里!抢 QCon 展区门票 了解详情
写点什么

用 80 行 JavaScript 代码构建自己的语音助手

  • 2020-07-17
  • 本文字数:3429 字

    阅读完需:约 11 分钟

用 80 行 JavaScript 代码构建自己的语音助手

在本教程中,我们将使用 80 行 JavaScript 代码在浏览器中构建一个虚拟助理(如 Siri 或 Google 助理)。你可以在这里测试这款应用程序,它将会听取用户的语音命令,然后用合成语音进行回复。

你所需要的是:


由于 Web Speech API 仍处于试验阶段,该应用程序只能在受支持的浏览器上运行:Chrome(版本 25 以上)和 Edge(版本 79 以上)。

我们需要构建哪些组件?

要构建这个 Web 应用程序,我们需要实现四个组件:


  1. 一个简单的用户界面,用来显示用户所说的内容和助理的回复。

  2. 将语音转换为文本。

  3. 处理文本并执行操作。

  4. 将文本转换为语音。

用户界面

第一步就是创建一个简单的用户界面,它包含一个按钮用来触发助理,一个用于显示用户命令和助理响应的 div、一个用于显示处理信息的 p 组件。


const startBtn = document.createElement("button");startBtn.innerHTML = "Start listening";const result = document.createElement("div");const processing = document.createElement("p");document.write("<body><h1>My Siri</h1><p>Give it a try with 'hello', 'how are you', 'what's your name', 'what time is it', 'stop', ... </p></body>");document.body.append(startBtn);document.body.append(result);document.body.append(processing);
复制代码

语音转文本

我们需要构建一个组件来捕获语音命令并将其转换为文本,以进行进一步处理。在本教程中,我们使用 Web Speech APISpeechRecognition。由于这个 API 只能在受支持的浏览器中使用,我们将显示警告信息并阻止用户在不受支持的浏览器中看到 Start 按钮。


const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;if (typeof SpeechRecognition === "undefined") {  startBtn.remove();  result.innerHTML = "<b>Browser does not support Speech API. Please download latest chrome.<b>";}
复制代码


我们需要创建一个 SpeechRecognition 的实例,可以设置一组各种属性来定制语音识别。在这个应用程序中,我们将 continuousinterimResults 设置为 true,以便实时显示语音文本。


const recognition = new SpeechRecognition();recognition.continuous = true;recognition.interimResults = true;
复制代码


我们添加一个句柄来处理来自语音 API 的 onresult 事件。在这个处理程序中,我们以文本形式显示用户的语音命令,并调用函数 process 来执行操作。这个 process 函数将在下一步实现。


function process(speech_text) {    return "....";}recognition.onresult = event => {   const last = event.results.length - 1;   const res = event.results[last];   const text = res[0].transcript;   if (res.isFinal) {      processing.innerHTML = "processing ....";      const response = process(text);      const p = document.createElement("p");      p.innerHTML = `You said: ${text} </br>Siri said: ${response}`;      processing.innerHTML = "";      result.appendChild(p);      // add text to speech later   } else {      processing.innerHTML = `listening: ${text}`;   }}
复制代码


我们还需要将 用户界面的 buttonrecognition 对象链接起来,以启动/停止语音识别。


let listening = false;toggleBtn = () => {   if (listening) {      recognition.stop();      startBtn.textContent = "Start listening";   } else {      recognition.start();      startBtn.textContent = "Stop listening";   }   listening = !listening;};startBtn.addEventListener("click", toggleBtn);
复制代码

处理文本并执行操作

在这一步中,我们将构建一个简单的会话逻辑并处理一些基本操作。助理可以回复“hello”、“what's your name?”、“how are you?”、提供当前时间的信息、“stop”听取或打开一个新的标签页来搜索它不能回答的问题。你可以通过使用一些 AI 库进一步扩展这个 process 函数,使助理更加智能。


function process(rawText) {   // remove space and lowercase text   let text = rawText.replace(/\s/g, "");   text = text.toLowerCase();   let response = null;   switch(text) {      case "hello":         response = "hi, how are you doing?"; break;      case "what'syourname":         response = "My name's Siri.";  break;      case "howareyou":         response = "I'm good."; break;      case "whattimeisit":         response = new Date().toLocaleTimeString(); break;      case "stop":         response = "Bye!!";         toggleBtn(); // stop listening   }   if (!response) {      window.open(`http://google.com/search?q=${rawText.replace("search", "")}`, "_blank");      return "I found some information for " + rawText;   }   return response;}
复制代码

文本转语音

在最后一步中,我们使用 Web Speech API 的 speechSynthesis 控制器为我们的助理提供语音。这个 API 简单明了。


speechSynthesis.speak(new SpeechSynthesisUtterance(response));
复制代码


就是这样!我们只用了 80 行代码就有了一个很酷的助理。程序的演示可以在这里找到。


// UI compconst startBtn = document.createElement("button");startBtn.innerHTML = "Start listening";const result = document.createElement("div");const processing = document.createElement("p");document.write("<body><h1>My Siri</h1><p>Give it a try with 'hello', 'how are you', 'what's your name', 'what time is it', 'stop', ... </p></body>");document.body.append(startBtn);document.body.append(result);document.body.append(processing);// speech to textconst SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;let toggleBtn = null;if (typeof SpeechRecognition === "undefined") {  startBtn.remove();  result.innerHTML = "<b>Browser does not support Speech API. Please download latest chrome.<b>";} else {  const recognition = new SpeechRecognition();  recognition.continuous = true;  recognition.interimResults = true;  recognition.onresult = event => {    const last = event.results.length - 1;    const res = event.results[last];    const text = res[0].transcript;    if (res.isFinal) {      processing.innerHTML = "processing ....";      const response = process(text);      const p = document.createElement("p");      p.innerHTML = `You said: ${text} </br>Siri said: ${response}`;      processing.innerHTML = "";      result.appendChild(p);      // text to speech      speechSynthesis.speak(new SpeechSynthesisUtterance(response));    } else {      processing.innerHTML = `listening: ${text}`;    }  }  let listening = false;  toggleBtn = () => {    if (listening) {      recognition.stop();      startBtn.textContent = "Start listening";    } else {      recognition.start();      startBtn.textContent = "Stop listening";    }    listening = !listening;  };  startBtn.addEventListener("click", toggleBtn);}// processorfunction process(rawText) {  let text = rawText.replace(/\s/g, "");  text = text.toLowerCase();  let response = null;  switch(text) {    case "hello":      response = "hi, how are you doing?"; break;    case "what'syourname":      response = "My name's Siri.";  break;    case "howareyou":      response = "I'm good."; break;    case "whattimeisit":      response = new Date().toLocaleTimeString(); break;    case "stop":      response = "Bye!!";      toggleBtn();  }  if (!response) {    window.open(`http://google.com/search?q=${rawText.replace("search", "")}`, "_blank");    return `I found some information for ${rawText}`;  }  return response;}×Drag and DropThe image will be downloaded
复制代码


作者介绍:


Tuan Nhu Dinh,Facebook 软件工程师。


原文链接:


https://medium.com/swlh/build-your-own-hi-siri-with-80-lines-of-javascript-code-653540c77502


公众号推荐:

2024 年 1 月,InfoQ 研究中心重磅发布《大语言模型综合能力测评报告 2024》,揭示了 10 个大模型在语义理解、文学创作、知识问答等领域的卓越表现。ChatGPT-4、文心一言等领先模型在编程、逻辑推理等方面展现出惊人的进步,预示着大模型将在 2024 年迎来更广泛的应用和创新。关注公众号「AI 前线」,回复「大模型报告」免费获取电子版研究报告。

AI 前线公众号
2020-07-17 11:363306

评论 1 条评论

发布
用户头像
然而谷歌接口要翻墙
2020-07-28 13:16
回复
没有更多了
发现更多内容

为你总结了N个真实线上故障,从容应对面试官!

AI乔治

Java 架构 GC

区块链助力跨省、零材料办理 成都武侯打造“中国政务服务第一链”

CECBC

区块链

甲方日常 39

句子

工作 随笔杂谈 日常

记一次Jvm参数调优实战

AI乔治

Java 架构 JVM 编程思维 jvm调优

算法学习1-- 数组常见问题

菜鸟小sailor 🐕

算法和数据结构

32个问题,学习Java虚拟机的运行时数据区

AI乔治

Java 架构 JVM JVM虚拟机原理

30 岁的码农人生 ——人生至暗时,你依然能窥见光明

cxuan

程序员 程序人生 感悟

今天你的idea崩了吗?分享6种“白嫖”正版idea的途径,真香定律

小Q

学习 架构 面试 开发 IntelliJ IDEA

它可能是分布式系统中最重要的枢纽

架构师修行之路

分布式 微服务 注册

【JSRC小课堂】Web安全专题(一)认证缺失和认证缺陷漏洞

京东科技开发者

WEB安全

实用!8个 chrome插件玩转GitHub,单个文件下载小意思

程序员小富

GitHub

阿里巴巴专属著作超赞,就是名字起得有点狂“成神之路”???

Java架构师迁哥

JVM系列-第一节:JVM简介、运行时数据区、内存分代模型

诸葛小猿

Java JVM JVM简介 运行时数据区 内存分代模型

10 张图打开 CPU 缓存一致性的大门

小林coding

缓存 cpu 操作系统 计算机

如何在微信公众号图文中插入外链

Ceelog

微信公众号

LeetCode题解:47. 全排列 II,回溯,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

中国银行前行长李礼辉:区块链技术优势与产业前景

CECBC

区块链 数字货币

即构SDK10月迭代:新增多款语音音效、外部采集码流控制及Android SDK 最低支持操作系统版本调整

ZEGO即构

android RTC

什么是动态代理

Rayjun

Java 动态代理

AES加密模式

Mars

AES

分布式系统使用网关到底是好还是坏?

架构师修行之路

分布式 微服务 网关

新基建下区块链基础设施建设

CECBC

区块链

你有时间吗?

池建强

时间

谈谈贪官污吏

空山

可视化数据科学中的概率分布以帮你更好地理解各种分布

计算机与AI

学习 数据科学

系统从初期到支撑亿级流量,都经历了哪些架构的变迁?

冰河

分布式 微服务 系统架构 SOA 垂直架构

英特尔老矣,尚能“转”否?

脑极体

"全能"人才的概念真的对吗

supernova

创业 读书笔记 随笔杂谈

谷歌朝南,华为朝北

脑极体

一次艰难的内存泄露排查,BeanUtils的锅

AI乔治

Java 架构

Dubbo 微服务调用时序图

Acker飏

用 80 行 JavaScript 代码构建自己的语音助手_语言 & 开发_Tuan Nhu Dinh_InfoQ精选文章