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

云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!

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

你所需要的# Z ^ E U W是:

Google Chrome (版本 25 以上)
一款文本编辑器

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

我们需要^ v H V ` B o构建哪些组件?

要构建这个 Web 应用程序,我们需要实现四个组件:
一个K ~ , S Z简单的用户界面,用来显示用户所说的内容和助理的回复。
将语音转换为) L z R . J v r Z文本。
处理文本并执行操作。
将文本转换为语音。

用户界面

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

const startBtn = document.createV J 9 & J U `Element("button");
startBtn.innerHT) ` & 2 3 0ML = "Start listening";
const result = document.createElement("div");
const processing = document.createElement("p");
document.write("&lh ) X K / yt;body><h1>My Siri</h1><1 # ; ^ t wp>Give it a try with 'hello', 'how are you', 'what's your name', 'what time is it', 'stop', ..7 X x ~ ? & _ `. </p></body>");
docuD ! N E o @ r k kment.body.B ] + # V 4append(startBtn)y W c y _ d;
document.body.append(result);
document.body.append(processing);

语音转文本

我们需要构建一个组件来捕获语音命j v令并将其转换为文本,` c | J O + j以进行进一步处理。在本教程中,我们使用 Web Speech API 的 SpeechRK L b 8 s ` Fecognition。由于这个 API 只能在受支持的浏览器中使用,我们将显示警告信息并阻止用户在不受支持的浏览器中f y L F 8 H 8看到 Start 按钮。

const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecogniti= Z S E W + V } Von;
if (typeof SpeechRecognitiU 8 8 pon === "undefined") {
starJ N otBtn.remove();
result.innerHTML = "<b>Browser does not support Speech API. Please download latest chrome.<b>";
}

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

const recognitij K Ron = new Spee1 D h 7 zchRecognitio] r bn();
recognition.continuous = truj % q ( s :e;
recognition.interimResults = true;

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

functv 9 * H } f , 4ion process(su U + / @ x ypeech_texX 2  Ct) {
return "....";
}
recognition.onresult = event => {
const last = event.results.length - 1;
const resD m A O 0 = event.results[last];
const text = res[0].transcript;n x Q
if (res.isFinal) {
processing.innerHTML = "pr( { b Zocessing ....";
const response = process(texI V , # & V { q /t);
const p = document.createElement("p");
p.innerHTML = `You said: ${text} </br&| ` Kgt;Siri said: ${response}`;
processi2 m 9 XngN 4 v.innerHTML = "";
result.appendChilH w k F % 5 j .d(p);
// add text to sC K ^ 0 s Upeech later
} else {
proo Y hcessing.innerHTML = `listening: ${text}`;
}
}

我们还需要将 用f # U h F户界面的 button 与 recognitb H ,ion 对象链接起来,以启动 / 停止语音识别

let lN w | 0 O =istening = false;
toggleBtn = () => {
if (listening) {
recognitio4 y zn.stop();
startBtn.textContent = "Star1 R U 1 m @ { 3t listening";
} else {
recognition.start();
startBtn.textContent = "Stop listening";
}
listening = !listeniy 2 8 = Hng;
};
startBtn.addEventListener("click", toggleBtn);

处理文本并执行操作

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

function process(rawText) {
// remo! q j b X zve space and lowercase text
let text = rawText.replace(/s/g, "f N ( 7 j % L");
text = text.toLowerCS ^ z A e Dase();
let response = null;
switch(text) {
caseW y J "hello":
response = "hi, how are you doing?r | d F"; break;
case "what'syourname":
response = "My name's Siri.";  break;
case "hz A dowareyou":
response = "I'm good."; breakL 0 _ n g g;
case "whattimeisit":
response = new Date().toLocaleTimeString(} U ; k ` F g); break;
case "stop":
response = "Bye!!";
toggleBtn(); // stop listening
}
if (!r v 1 1 bespom O 9nse) {
window.open(`http://google.com/search?q=${rawText.replace("search", "")}`, "_blank");
return "I found some information for " + rawText;
}
return response;
}

文本转语音

在最后一D D ) N T步中,我们使用 Web Speech API 的 speechSl m ] lynthesis 控制器为我们的助理提供语音。这个 API 简单明了。

speechSynthesis.speak(new SpeechSynthesisUt* 9 f ) - B ;teraU $ p { h L pnce(response));

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

// UI comp
const startBtn = document.createEv ` S g Glement(~ U l e Q I _"button");
startBtn.innerHTML =d . M 0 } & "Start listening";
const result = document.c% l 6 freateElement("div");
constS % 1 V processing = do$ [ O @ 1 p m ~cument.createElement("p");
dop y u kcument.write("<body><h1>My Siri</h1><p&gb K M { 7 ? d w it;Give it a try, / T N wv y d h Pith 'hello', 'how are you', 'what's your name', 'what time is it', 'stop', ... </p% | 4 ) 5></body>");
do. v {cument.body.append(startBtn);
documeP y % A 5nt.body.append(resh i ?ult);
document.body.append(processing);
// speech to text
const SpeechRecognb V 6 z c ;ition = window.SpeechRecognition || window.webkitSpeechRecognition;
let toggleBtn = null;
if (typeof SpeechRecognition === "undefined") {
startBtn.remove();
rv h ( w G ( v desult.innerHTML = "<b>Browser does not support Speech API. Please download latest chrome.<b>";
} else {
const recognition = new SpeechRecognition(_ 4 R);
recognition.continuous = true;
recognition.interimResults = true;
recognir Z % $  X 6 % Ftion.onresult = event =>F 4 x 7 i = ) z; {
const last = event.results./ S ( O & y Klength - 1;D b J )
const res = event.r4 ~ k q q 6 q 6esults[last];
const text = res[0].transcript;
if (res.isFinal) {
processing.innerHTML = "processing ....";
const response = process(text);
constW D _ - p = documet R nt.createElement("p");
p.innerHTML = `You said: ${text} </# v Xbr: 4 % h Q + Y q>Siri si 1 V { A K R waid: ${respo] 3 h b + znse}`;
processing.innerHTML = "";
result.appendChild(p);
// text to speech
speechSyn| V .thesis.speak(new Speec3 : ] ~ + s 9 VhSynthesisUtterance(response));
} else {$ + ) K y 3
processI / m . ; P 0ing.innerHTML = `listening: ${text}`;
}
}
let listening = false;
toggleBtn = () => {
if (listeniF ` F ]ng) {
recognition.stop();
start` ] !Btn.textContent = "Start listening";
} else {
recognition.start();
startBtn.textContent = "Stop listening";
}
listenin` / 2 ; | P v W Qg = !listening;
};
startBtn.addEveq ? Q 4 5 ? h ~ntListener("click", toggleBtn);
}
// processor
function procesJ A u Q z Is(rawText) {
let text = rawText.replace(/s/g, "");
text = text.toLowerCase();
let response = null;
switch(text) {
case "hello":
response = "hi, how are you doi: V ~ 6 ) k X png?"; break;
case "what'syourname":
response = "My name's Siri.";  br` / l .eak;
case "howareyou":
response = "I'm good."; break;
case "whattimeisit":
response = n& ; ^ - [ C zew Date().toLocaleTimeString(); break;
case "stop":
response = "Bye!!";
toggleBtn();
}
if (!response) {
wind` E I ) r aow.open(`http://google.com/search?q=${rawText.replace("search", "")}`, "_blank");
rP V x ^ v b r % eturn `I found some informaC } T N .tion for ${ru y 3 g u b + yawText}`B 0 S e;
}
return response;
}

Drag and D8 * 9 1rop
The image will be downloaded

作者介绍:

Tuan Nhu Dinh,Facebook 软件工程师。

【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/zhibo

立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK

原文发布时间:2020-07-17
本文作{ 1 # t : E 0 W Q者:Tuan Nhu Dinh
本文来自:“Ia x ? F G k d ;nfoQC ~ 6 n 0 2 J”k 5 [ 4 O,了解C H k D 1 X m相关信息可以关注“InfoQ”