用 80 行 Javascript 代码构建自己的语音助手
作者 | Tuan Nhu Dinh
译者 | Sambodhi
策划 | 蔡芳芳
本文演示了如何使用 Web Speech API 构建一个简单的人工智能聊天机器人。
在本教程中,我们将使用 80 行 JavaScript 代码在浏览器中构建一个虚拟助理(如 Siri 或 Google 助理)。你可以前往下方网址测试这款应用程序,它将会听取用户的语音命令,然后用合成语音进行回复。
https://nhudinhtuan.github.io/mysiri/
你所需要的是:
- Google Chrome(版本 25 以上)
- 一款文本编辑器
由于 Web Speech API 仍处于试验阶段,该应用程序只能在 受支持的浏览器 上运行:Chrome(版本 25 以上)和 Edge(版本 79 以上)。
我们需要构建哪些组件?
要构建这个 Web 应用程序,我们需要实现四个组件:
- 一个简单的用户界面,用来显示用户所说的内容和助理的回复。
- 将语音转换为文本。
- 处理文本并执行操作。
- 将文本转换为语音。
用户界面
第一步就是创建一个简单的用户界面,它包含一个按钮用来触发助理,一个用于显示用户命令和助理响应的 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 API 的 SpeechRecognition
。由于这个 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
的实例,可以设置一组各种 属性 来定制语音识别。在这个应用程序中,我们将 continuous
和 interimResults
设置为 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}`;
}
}
我们还需要将 用户界面的 button
与 recognition
对象链接起来,以启动 / 停止语音识别。
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 行代码就有了一个很酷的助理。程序的演示可以在下方链接中找到。
https://nhudinhtuan.github.io/mysiri/
// UI comp
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);
// speech to text
const 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);
}
// processor
function 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 Drop
The image will be downloaded
作者介绍:
Tuan Nhu Dinh,Facebook 软件工程师。
参考阅读:
https://medium.com/swlh/build-your-own-hi-siri-with-80-lines-of-javascript-code-653540c77502
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 干货 | 从0到1,搭建一个体系完善的前端React组件库
- LeetCode 01两数之和&02两数相加
- 给GitHub "彩蛋" readme 生成自定义统计信息
- Android |《看完不忘系列》之okhttp
- pt-osc改表过程中的中文乱码问题
- Hive Query生命周期 —— 钩子(Hook)函数篇
- python快速排序
- 扩展 Microsoft.Owin.Security
- Angular 2 版本的 ng-bootstrap 初体验
- 揭开MySQL“锁”的神秘面纱
- 从0到1开发测试平台(九)后端对接口response的封装
- 在 Mac OS X 上安装和配置 Wine
- 性能测试之nginx访问日志分析
- Pytest之断言
- R语言单因素方差分析简单小例子