写点什么

用 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


2020-07-17 11:363701

评论 1 条评论

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

政企服务机构如何进行数字化转型?

优秀

数字化转型

Apache Doris 1.2.2 Release 版本正式发布

SelectDB

大数据 数据分析 OLAP 分析型数据库 数据库·

海泰方圆受邀参加中关村网信联盟会议并斩获三项殊荣

电子信息发烧客

飞桨助力南京邮电大学智能芯片测试团队斩获“互联网+”大赛全国银奖

飞桨PaddlePaddle

paddle 芯片 大学生 飞桨 国赛

2022年最新数据库调查报告:超八成DBA月薪过万,你拖后腿了吗?

墨天轮

MySQL 数据库 oracle 工资 dba

使用 NGINX 在 Kubernetes 中实现多租户和命名空间隔离

NGINX开源社区

nginx NGINX Ingress Controller NGINX Kubernetes Gateway 企业号 2 月 PK 榜

海量并发低延时 RTC-CDN 系统架构设计(上)

网易云信

实时音视频 音视频开发

Greenfield

股市老人

性能测试中获取JVM资源信息

FunTester

如何在现实场景中随心放置AR虚拟对象?

HarmonyOS SDK

HMS Core

Wallys /industrial wifi6 router/ Ipq6010 /ipq6018/ipq6000 2x2 2.4G & 5G

Cindy-wallys

IPQ6010 ipq6018 IPQ6000

软件测试 | 常用模拟器使用

测吧(北京)科技有限公司

测试

一文读懂Guava EventBus(订阅\发布事件)

京东科技开发者

架构 观察者模式 Guava EventBus 企业号 2 月 PK 榜

开源指南针发布在即:估量有尺,开源有道

kk-OSC

开源

聊一聊 gRPC 中的拦截器

江南一点雨

gRPC

CNCF社区首个!KubeEdge达到软件供应链SLSA L3等级

华为云开发者联盟

云原生 华为云 企业号 2 月 PK 榜 华为云开发者联盟

进击中的 Zebec 生态,Web2 与 Web3 世界的连接器

股市老人

DR-AP40X9-A-Qualcomm-IPQ4019/IPQ4029-2.4G&5G

Cindy-wallys

IPQ4019 ipq4029

Bytebase 体验官之勇闯新手村

朱亚光

构建云边端一体的分布式云架构,软硬结合驱动边缘计算创新场景

Baidu AICLOUD

边缘计算 分布式云

软件测试/测试开发 | web自动化测试-PageObject 设计模式

测试人

软件测试 自动化测试 测试开发 Web自动化测试

为什么大多数团队推行自动化测试最后却不了了之?

Liam

测试 自动化测试 测试自动化

Seal 0.4 发布:软件供应链安全洞察更上一层楼!

SEAL安全

软件供应链安全 SEAL 企业号 2 月 PK 榜

IoT设备数据业务价值洞察实践——实践类

阿里云AIoT

阿里云 物联网 IoT

软件测试/测试开发 | web自动化测试-文件上传与弹框处理

测试人

软件测试 自动化测试 测试开发 Web自动化测试 selenium

李宏伟 安警官的IP地址已经锁定你!IP地址究竟如何定位到莽村附近?

郑州埃文科技

IP地址 IP定位查询

GaiaX开源解读 | 表达式作为逻辑动态化的基础,我们是如何设计的

阿里巴巴文娱技术

开源 研发效能 服务端 多端开发

rust入坑指南之ownership

京东科技开发者

rust JVM 内存 企业号 2 月 PK 榜 ownership

设计模式第六讲:责任链模式和迭代器模式详解

C++后台开发

设计模式 责任链模式 迭代器模式 后端开发 Linux服务器开发

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