JavaScript
JavaScript 部分会介绍更多细节。
带前缀的属性
浏览器目前通过带有前缀的属性提供语音识别的支持。因此在代码开始部分我们添加了以下代码,以便同时支持带前缀的属性和未来可能支持的不带前缀的属性:
jsconst SpeechRecognition =
window.SpeechRecognition || window.webkitSpeechRecognition;
const SpeechGrammarList =
window.SpeechGrammarList || window.webkitSpeechGrammarList;
const SpeechRecognitionEvent =
window.SpeechRecognitionEvent || window.webkitSpeechRecognitionEvent;
语法
代码的下一部分定义了我们希望应用程序识别的语法。定义了以下变量以保存我们的语法:
jsconst colors = [
"aqua",
"azure",
"beige",
"bisque",
"black",
"blue",
"brown",
"chocolate",
"coral" /* … */,
];
const grammar = `#JSGF V1.0; grammar colors; public
" | ",
)};`;
语法格式使用的是 JSpeech Grammar Format(JSGF)——你可以在前面的链接中了解更多关于语法格式的规范。不过现在,让我们快速地浏览它:
每一行用分号分隔,和 JavaScript 中一样
第一行——#JSGF V1.0——说的是语法使用的格式和版本。这总是需要首先包括在内
第二行表示我们想要识别的术语类型。public 声明这是一条公共规则,尖括号中的字符串定义需要识别术语的名字(color),等号后面的是这个术语可以被识别和接受的具体值。得注意每一个值如何被一个管道符号分割开的
你可以按照上面的结构,在多行中,想定义多少就定义多少术语,也可以包括相当复杂的语法定义。对于我们这个简单的演示,就把语法定义的简单些。
将语法插入语音识别
接下来是使用 SpeechRecognition() 构造函数,定义一个语音识别实例,控制对于这个应用的识别。还需要使用 SpeechGrammarList() 构造函数,创建一个语音语法列表对象来包含我们的语法。
jsconst recognition = new SpeechRecognition();
const speechRecognitionList = new SpeechGrammarList();
使用 SpeechGrammarList.addFromString() 把语法添加到列表 (list),这个方法接收两个参数,第一个是我们想要添加的包含语法内容的字符串,第二个是对添加的这条语法的权重 (权重值范围是 0~1),权重其实是相对于其他语法,这一条语法的重要程度。添加到列表的语法就是可用的,并且是一个SpeechGrammar 实例。
jsspeechRecognitionList.addFromString(grammar, 1);
我们然后通过设置 SpeechRecognition.grammars 属性值,把我们的SpeechGrammarList 添加到 speech recognition 实例。在继续往前走之前,我们还需要设置 recognition 实例其他的一些属性:
SpeechRecognition.lang :设置识别的是什么语言。这个设定是良好的做好,因此墙裂推荐~
SpeechRecognition.interimResults :定义 speech recognition 系统要不要返回临时结果 (interim results),还是只返回最终结果。对于这个简单 demo,只返回最终结果就够了。
SpeechRecognition.maxAlternatives :定义每次结果返回的可能匹配值的数量。这有时有用,比如要的结果不明确,你想要用一个列表展示所有可能值,让用户自己从中选择一个正确的。但这里这个简单 demo 就不用了,因此我们设置为 1(1 也就是默认值)。
jsrecognition.grammars = speechRecognitionList;
recognition.continuous = false;
recognition.lang = "en-US";
recognition.interimResults = false;
recognition.maxAlternatives = 1;
开始语音识别
在获取输出的
jsconst diagnostic = document.querySelector(".output");
const bg = document.querySelector("html");
const hints = document.querySelector(".hints");
let colorHTML = "";
colors.forEach((color, i) => {
console.log(color, i);
colorHTML += ` ${color} `;
});
hints.innerHTML = `Tap or click then say a color to change the background color of the app. Try ${colorHTML}.`;
document.body.onclick = () => {
recognition.start();
console.log("Ready to receive a color command.");
};
接收、处理结果
一旦语音识别开始,有许多 event handlers 可以用于做结果返回的后续操作,除了识别的结果外还有些零碎的相关信息可供操作 (可查看 SpeechRecognition event handlers list )。最常见会使用的一个是 SpeechRecognition.onresult ,这在收到一个成功的结果时候触发。
jsrecognition.onresult = (event) => {
const color = event.results[0][0].transcript;
diagnostic.textContent = `Result received: ${color}.`;
bg.style.backgroundColor = color;
console.log(`Confidence: ${event.results[0][0].confidence}`);
};
代码中第三行看上去有一点复杂,让我们一步一步解释以下。SpeechRecognitionEvent.results 属性返回的是一个SpeechRecognitionResultList 对象 (这个对象会包含SpeechRecognitionResult 对象们),它有一个 getter,所以它包含的这些对象可以像一个数组被访问到——所以[last] 返回的是排在最后位置 (最新) 的SpeechRecognitionResult对象。每个SpeechRecognitionResult 对象包含的 SpeechRecognitionAlternative 对象含有一个被识别的单词。这些SpeechRecognitionResult 对象也有一个 getter,所以[0] 返回的是其中包含的第一个SpeechRecognitionAlternative 对象。最后返回的transcript属性就是被识别单词的字符串,把背景颜色设置为这个颜色,并在 UI 中报告出这个结果信息。
也使用了 SpeechRecognition.onspeechend 这个 handle 停止语音识别服务 (具体工作在SpeechRecognition.stop()) ,一旦一个单词被识别就不能再说咯 (必须再点击屏幕再次开启语音识别)
jsrecognition.onspeechend = () => {
recognition.stop();
};
处理错误和未能识别的语音
最后两个处理器处理的两种情况,一种是你说的内容不在定义的语法中所以识别不了,另一种是出现了 error。
SpeechRecognition.onnomatch 支持的就是第一种,但是得注意它似乎在 Firefox 或者 Chrome 中触发会有问题;它只是返回任何被识别的内容:
jsrecognition.onnomatch = (event) => {
diagnostic.textContent = "I didn't recognize that color.";
};
SpeechRecognition.onerror 处理的是第二种情况,识别成功了但是有 error 出现——SpeechRecognitionError.error 属性包含的信息就是返回的确切的 error 是什么。
jsrecognition.onerror = (event) => {
diagnostic.textContent = `Error occurred in recognition: ${event.error}`;
};
