如何将语音搜索添加到React应用中

601 阅读6分钟

Adding Voice Search to a React Application

语音命令不仅适用于谷歌或Alexa等助手。它们也可以被添加到你的移动和桌面应用程序中,为你的终端用户提供额外的功能甚至乐趣。而且,在你的应用程序中添加语音命令或语音搜索可以非常容易实现。在这篇文章中,我们将使用Web Speech API来构建一个语音控制的图书搜索应用。

我们要构建的完整代码可以在GitHub上找到。对于没有耐心的人来说,在文章的结尾处有一个我们将建立的工作演示

网络语音API简介

在我们开始之前,需要注意的是,Web Speech API目前对浏览器的支持有限。要跟上这篇文章,你需要使用一个支持的浏览器

各大浏览器对mdn-api__SpeechRecognition功能的支持数据

首先,让我们看看启动和运行网络语音API有多容易。(你可能还想阅读SitePoint对网络语音API的介绍,并查看一些其他的网络语音API的实验)。要开始使用语音API,我们只需要实例化一个新的SpeechRecognition 类,以使我们能够监听用户的声音。

const SpeechRecognition = webkitSpeechRecognition;
const speech = new SpeechRecognition();
speech.onresult = event => {
   console.log(event);
};
speech.start();

我们首先创建一个SpeechRecognition 常数,它等于全局浏览器厂商前缀webkitSpeechRecognition 。在此之后,我们就可以创建一个语音变量,它将是我们的SpeechRecognition 类的新实例。这将使我们能够开始聆听用户的讲话。为了能够处理来自用户语音的结果,我们需要创建一个事件监听器,当用户停止说话时就会触发。最后,我们在我们的类实例上调用start 函数。

当第一次运行这段代码时,用户将被提示允许访问麦克风。这是浏览器为防止不必要的窥探而设置的安全检查。一旦用户接受了,他们就可以开始说话了,而且不会再被要求在该领域获得许可。在用户停止说话后,onresult 事件处理函数将被触发。

onresult 事件被传递给一个SpeechRecognitionEvent 对象,该对象是由一个SpeechRecognitionResultList 结果数组组成的。SpeechRecognitionResultList 对象包含SpeechRecognitionResult 对象。数组中的第一项返回一个SpeechRecognitionResult 对象,其中又包含一个数组。这个数组中的第一项包含了用户所讲内容的记录。

上述代码可以从Chrome DevTools或普通的JavaScript文件中运行。现在我们已经了解了基础知识,让我们来看看如何将其构建为一个React应用程序。我们可以看到下面通过Chrome DevTools控制台运行时的结果。

Browser devtools showing SpeechRecognitionResultList

在React中使用网络语音

利用我们已经学到的知识,将Web Speech API添加到React应用程序中是一个简单的过程。我们要处理的唯一问题是React组件的生命周期。首先,让我们用Create React App创建一个新的项目,遵循其入门指南。这假定你的机器上已经安装了Node

npx create-react-app book-voice-search
cd book-voice-search
npm start

接下来,我们用下面的代码替换App 文件,以定义一个基本的React组件。然后我们可以给它添加一些语音逻辑。

// App.js
import React from 'react';

const App = () => {
  return (
    <div>
      Example component
    </div>
  );
};

export default App;

这个简单的组件渲染了一个里面有一些文字的div。现在我们可以开始向该组件添加我们的语音逻辑。我们要建立一个组件来创建语音实例,然后在React生命周期中使用这个实例。当React组件第一次渲染时,我们要创建语音实例,开始聆听结果,并为用户提供一种开始语音识别的方式。我们首先需要导入一些React钩子(你可以在这里了解更多关于React核心钩子的信息),一些CSS样式,以及一个供用户点击的麦克风图片

// App.js

import { useState, useEffect } from "react";

import "./index.css";

import Mic from "./microphone-black-shape.svg";

在这之后,我们将创建我们的语音实例。我们可以使用我们之前在看网络语音API的基础知识时学到的东西。我们必须对我们粘贴在浏览器开发工具中的原始代码做一些修改。首先,我们通过添加浏览器支持检测,使代码更加健壮。我们可以通过检查窗口对象上是否存在webkitSpeechRecognition 类来做到这一点。这将告诉我们浏览器是否知道我们要使用的API。

然后我们将continuous 设置改为true。这样就可以将语音识别API配置为持续监听。在我们的第一个例子中,这被默认为假,意味着当用户停止说话时,onresult 事件处理程序将被触发。但由于我们允许用户控制他们希望网站停止监听的时间,我们使用continuous ,让用户想说多久就说多久。

// App.js
let speech;
if (window.webkitSpeechRecognition) {
  // eslint-disable-next-line
  const SpeechRecognition = webkitSpeechRecognition;
  speech = new SpeechRecognition();
  speech.continuous = true;
} else {
  speech = null;
}

const App = () => { ... };

现在我们已经设置了语音识别代码,我们可以开始在React组件内使用它。正如我们之前看到的,我们导入了两个React钩子--useStateuseEffect 钩子。这些将允许我们添加onresult 事件监听器,并将用户的成绩单存储为状态,这样我们就可以在用户界面上显示它。

// App.js
const App = () => {
 const [isListening, setIsListening] = useState(false);
 const [text, setText] = useState("");
 const listen = () => {
   setIsListening(!isListening);
   if (isListening) {
     speech.stop();
   } else {
     speech.start();
   }
 };

 useEffect(() => {
  //handle if the browser does not support the Speech API
   if (!speech) {
      return;
    }
   speech.onresult = event => {
     setText(event.results[event.results.length - 1][0].transcript);
   };
 }, []);

 return (
   <>
     <div className="app">
       <h2>Book Voice Search</h2>
       <h3>Click the Mic and say an author's name</h3>
       <div>
         <img
           className={`microphone ${isListening && "isListening"}`}
           src={Mic}
           alt="microphone"
           onClick={listen}
         />
       </div>
       <p>{text}</p>
     </div>
   </>
 );
}

export default App;

在我们的组件中,我们首先声明两个状态变量--一个用来保存用户讲话的记录文本,另一个用来确定我们的应用程序是否在听用户讲话。我们调用React的useState 钩子,为isListening ,传递默认值false ,为文本传递一个空字符串。这些值将在以后的组件中根据用户的交互进行更新。

在我们设置好状态后,我们创建一个函数,当用户点击麦克风图像时,该函数将被触发。这将检查应用程序当前是否正在收听。如果是,我们就停止语音识别;否则,我们就启动它。这个函数后来被添加到麦克风图像的onclick

然后,我们需要添加我们的事件监听器来捕获来自用户的结果。我们只需要创建一次这个事件监听器,而且我们只需要在用户界面渲染后才需要它。因此,我们可以使用useEffect 钩子来捕获组件的安装时间,并创建我们的onresult 事件。我们还向useEffect 函数传递一个空数组,这样它就只运行一次。

最后,我们可以渲染出所需的UI元素,让用户开始说话并看到文本结果。

继续阅读在SitePoint上为React应用程序添加语音搜索