如何用语音控制你的React应用
几个月前,我写了一篇关于使用TensorflowJS进行网络语音识别的文章。尽管它的实现超级有趣,但对很多人来说,它的扩展却超级麻烦。原因很简单,如果你想检测比我提供的模型更多的词,就需要训练一个深度学习模型,而这个模型是非常基本的。
对于那些需要更实用的方法的人来说,那篇文章是不够的。根据你们的要求,我今天写的是如何使用Web Speech API将完整的语音识别带到你们的网络应用中。
但在我们讨论实际实现之前,让我们先了解一下这种功能可能会有帮助的一些场景:
- 为不可能使用键盘或触摸设备的情况建立一个应用程序。例如,在野外工作的人或特殊的地球仪使输入设备的交互变得困难。
- 为了支持残疾人士。
- 因为它很厉害!
用语音识别驱动网络应用的秘密是什么?
鼓声......秘密是Chrome(或Chromium)网络语音API。这个API适用于基于Chromium的浏览器,非常棒,为我们做了所有繁重的工作,让我们只关心如何利用语音构建更好的界面。
无论这个API多么令人难以置信,截至2020年11月,它没有得到广泛支持,这可能是一个问题,取决于你的要求。这里是目前的支持状态,我可以使用吗?此外,它只在在线时工作,所以如果你离线,你将需要一个不同的设置。
当然,这个API是通过JavaScript提供的,而且它不是唯一的,也不限于React。尽管如此,有一个很好的React库可以进一步简化API,这就是我们今天要使用的东西。
如果你想在vanilla JS或其他框架上进行实现,请自由阅读MDN Docs上的语音识别API文档。
世界你好,我正在转录
我们将从基础开始,我们将建立一个Hello World应用程序,它将实时转录用户所说的内容。在做所有好事之前,我们需要一个良好的工作基础,所以让我们开始设置我们的项目。为了简单起见,我们将使用create-react-app来设置我们的项目。
npx create-react-app voice-command
接下来,用react-speech-recognition 库进行安装。
npm i react-speech-recognition
接下来,我们将对文件App.js 。CRA(create-react-app)为我们创造了一个良好的起点。开玩笑,我们不需要任何东西,所以从一个空白的App.js 文件开始,和我一起编码。
在我们可以做任何事情之前,我们需要imports 。
import { useEffect } from 'react';
import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition';
接下来,我们将创建一个带有几个按钮的简单功能组件,与语音引擎进行交互。
function App() {
const { transcript } = useSpeechRecognition();
return (
<div>
<h3>Hello World!</h3>
<p>{transcript ? transcript : 'Start listening for transcript'}</p>
<button onClick={SpeechRecognition.startListening}>Start listening</button>
<button onClick={SpeechRecognition.stopListening}>Stop listening</button>
</div>
);
}
很简单,对吗?让我们详细看看我们在做什么,从useSpeechRecognition钩子开始。
这个钩子负责捕获语音识别过程的结果。它是我们产生预期结果的通道。在它最简单的形式中,我们可以提取用户在启用麦克风时所说的transcript ,就像我们在这里做的那样。
const { transcript } = useSpeechRecognition();
即使我们激活了钩子,我们也不会立即开始听;为此,我们需要与我们在开始时导入的对象SpeechRecognition进行交互。这个对象暴露了一系列的方法,这些方法将帮助我们控制语音识别API,这些方法可以在麦克风上开始聆听,停止,改变语言,等等。
我们的接口只是暴露了两个控制麦克风状态的按钮;如果你复制了所提供的代码,你的接口应该看起来和表现都是这样。
如果你试过演示程序,你可能注意到,如果你也许在听完后暂停,就会有遗漏的单词。这是因为库默认设置了这种行为,但你可以通过在startListening 方法上设置参数continuous 来改变它,像这样
SpeechRecognition.startListening({ continuous: true });
兼容性检测
我们的应用程序很好!但是如果你的浏览器不支持,会怎么样呢?我们可以为这些情况设置一个回退行为吗?是的,我们可以。如果你需要根据语音识别API是否被支持来改变你的应用程序的行为,react-speech-recognition 有一个方法正是为了这个目的。下面是一个例子。
useEffect(() => {
if (!SpeechRecognition.browserSupportsSpeechRecognition()) {
alert("Ups, your browser is not supported!");
}
}, []);
检测命令
到目前为止,我们涵盖了如何将语音转换为文本,但现在我们将更进一步,在我们的应用程序中识别预先定义的命令。构建这一功能将使我们有可能构建能够完全通过语音发挥作用的应用程序。
如果我们需要建立一个命令解析器,可能会有很多工作要做,但庆幸的是,语音识别API已经有一个内置的命令识别功能。
为了在用户说一个特定的短语时做出反应,你可以向useSpeechRecognition 钩子传入一个命令列表。每个命令都是一个具有以下属性的对象
command:这是一个字符串或正则表达式,代表你想听的短语callback:当命令被说出时被执行的函数。这个函数收到的最后一个参数将始终是一个包含以下属性的对象。resetTranscript:一个将成绩单设置为空字符串的函数matchInterim:决定是否应将 "临时 "结果与命令匹配的布尔值。这将使你的组件对命令作出更快的反应,但也使假阳性的可能性更大--即命令可能在没有被说出来时被检测到。默认情况下这是假的,应该只对简单的命令进行设置。isFuzzyMatch:布尔值,决定了语音和命令之间的比较是否基于相似性而不是精确匹配。模糊匹配对于那些容易发音错误或被语音识别引擎误解的命令(如地名、运动队、餐厅菜单项目)很有用。它适用于没有特殊字符的字符串字面的命令。如果命令是带有特殊字符的字符串或正则表达式,在模糊匹配时,它将被转换成没有特殊字符的字符串。匹配命令所需的相似度可以用fuzzyMatchingThreshold来配置。 isFuzzyMatch默认为假。当它被设置为 "true "时,它将传递四个参数给回调。- 的值是
command - 匹配命令的语音
- 的值是
- 命令和语音之间的相似度
- 上面的回调描述中提到的对象
fuzzyMatchingThreshold:当isFuzzyMatch打开时,如果语音与命令的相似度高于这个值,回调将被调用。你应该只在isFuzzyMatch为真时设置这个。它的值在0(将匹配任何东西)和1(需要精确匹配)之间。默认值是0.8。
下面是一个如何为你的应用程序预先定义命令的例子。
const commands = [
{
command: 'Hello',
callback: () => alert('You just said hi!!'),
matchInterim: true
},
]
const { transcript } = useSpeechRecognition({ commands })
你也可以有动态的命令,比如
const commands = [
{
command: 'I would like to order *',
callback: (food) => setMessage(`Your order is for: ${food}`)
},
]
const { transcript } = useSpeechRecognition({ commands })
结论
多亏了Chrome的语音识别API,构建声控应用再简单不过了,也很有趣。希望在不久的将来,我们能看到这个API被更多的浏览器支持,并具有离线功能。然后,它将成为一个非常强大的API,可能改变我们构建网络的方式。
谢谢你的阅读!