JamesBrill / react-speech-recognition

💬Speech recognition for your React app
https://webspeechrecognition.com/
MIT License
637 stars 116 forks source link
react speech-recognition speech-to-text

react-speech-recognition

A React hook that converts speech from the microphone to text and makes it available to your React components.

npm version npm downloads license Coverage Status

How it works

useSpeechRecognition is a React hook that gives a component access to a transcript of speech picked up from the user's microphone.

SpeechRecognition manages the global state of the Web Speech API, exposing functions to turn the microphone on and off.

Under the hood, it uses Web Speech API. Note that browser support for this API is currently limited, with Chrome having the best experience - see supported browsers for more information.

This version requires React 16.8 so that React hooks can be used. If you're used to version 2.x of react-speech-recognition or want to use an older version of React, you can see the old README here. If you want to migrate to version 3.x, see the migration guide here.

Useful links

Installation

To install:

npm install --save react-speech-recognition

To import in your React code:

import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition'

Basic example

The most basic example of a component using this hook would be:

import React from 'react';
import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition';

const Dictaphone = () => {
  const {
    transcript,
    listening,
    resetTranscript,
    browserSupportsSpeechRecognition
  } = useSpeechRecognition();

  if (!browserSupportsSpeechRecognition) {
    return <span>Browser doesn't support speech recognition.</span>;
  }

  return (
    <div>
      <p>Microphone: {listening ? 'on' : 'off'}</p>
      <button onClick={SpeechRecognition.startListening}>Start</button>
      <button onClick={SpeechRecognition.stopListening}>Stop</button>
      <button onClick={resetTranscript}>Reset</button>
      <p>{transcript}</p>
    </div>
  );
};
export default Dictaphone;

You can see more examples in the example React app attached to this repo. See Developing.

Why you should use a polyfill with this library

By default, speech recognition is not supported in all browsers, with the best native experience being available on desktop Chrome. To avoid the limitations of native browser speech recognition, it's recommended that you combine react-speech-recognition with a speech recognition polyfill. Why? Here's a comparison with and without polyfills:

react-speech-recognition currently supports polyfills for the following cloud providers:

Speechly Microsoft Azure Cognitive Services

Cross-browser example

You can find the full guide for setting up a polyfill here. Alternatively, here is a quick (and free) example using Speechly:

const appId = ''; const SpeechlySpeechRecognition = createSpeechlySpeechRecognition(appId); SpeechRecognition.applyPolyfill(SpeechlySpeechRecognition);

const Dictaphone = () => { const { transcript, listening, browserSupportsSpeechRecognition } = useSpeechRecognition(); const startListening = () => SpeechRecognition.startListening({ continuous: true });

if (!browserSupportsSpeechRecognition) { return Browser doesn't support speech recognition.; }

return (

Microphone: {listening ? 'on' : 'off'}

{transcript}

); }; export default Dictaphone;


## Detecting browser support for Web Speech API

If you choose not to use a polyfill, this library still fails gracefully on browsers that don't support speech recognition. It is recommended that you render some fallback content if it is not supported by the user's browser:

```js
if (!browserSupportsSpeechRecognition) {
  // Render some fallback content
}

Supported browsers

Without a polyfill, the Web Speech API is largely only supported by Google browsers. As of May 2021, the following browsers support the Web Speech API:

For all other browsers, you can render fallback content using the SpeechRecognition.browserSupportsSpeechRecognition function described above. Alternatively, as mentioned before, you can integrate a polyfill.

Detecting when the user denies access to the microphone

Even if the browser supports the Web Speech API, the user still has to give permission for their microphone to be used before transcription can begin. They are asked for permission when react-speech-recognition first tries to start listening. At this point, you can detect when the user denies access via the isMicrophoneAvailable state. When this becomes false, it's advised that you disable voice-driven features and indicate that microphone access is needed for them to work.

if (!isMicrophoneAvailable) {
  // Render some fallback content
}

Controlling the microphone

Before consuming the transcript, you should be familiar with SpeechRecognition, which gives you control over the microphone. The state of the microphone is global, so any functions you call on this object will affect all components using useSpeechRecognition.

Turning the microphone on

To start listening to speech, call the startListening function.

SpeechRecognition.startListening()

This is an asynchronous function, so it will need to be awaited if you want to do something after the microphone has been turned on.

Turning the microphone off

To turn the microphone off, but still finish processing any speech in progress, call stopListening.

SpeechRecognition.stopListening()

To turn the microphone off, and cancel the processing of any speech in progress, call abortListening.

SpeechRecognition.abortListening()

Consuming the microphone transcript

To make the microphone transcript available in your component, simply add:

const { transcript } = useSpeechRecognition()

Resetting the microphone transcript

To set the transcript to an empty string, you can call the resetTranscript function provided by useSpeechRecognition. Note that this is local to your component and does not affect any other components using Speech Recognition.

const { resetTranscript } = useSpeechRecognition()

Commands

To respond when the user says a particular phrase, you can pass in a list of commands to the useSpeechRecognition hook. Each command is an object with the following properties:

Command symbols

To make commands easier to write, the following symbols are supported:

Example with commands

import React, { useState } from 'react'
import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition'

const Dictaphone = () => {
  const [message, setMessage] = useState('')
  const commands = [
    {
      command: 'I would like to order *',
      callback: (food) => setMessage(`Your order is for: ${food}`)
    },
    {
      command: 'The weather is :condition today',
      callback: (condition) => setMessage(`Today, the weather is ${condition}`)
    },
    {
      command: 'My top sports are * and *',
      callback: (sport1, sport2) => setMessage(`#1: ${sport1}, #2: ${sport2}`)
    },
    {
      command: 'Pass the salt (please)',
      callback: () => setMessage('My pleasure')
    },
    {
      command: ['Hello', 'Hi'],
      callback: ({ command }) => setMessage(`Hi there! You said: "${command}"`),
      matchInterim: true
    },
    {
      command: 'Beijing',
      callback: (command, spokenPhrase, similarityRatio) => setMessage(`${command} and ${spokenPhrase} are ${similarityRatio * 100}% similar`),
      // If the spokenPhrase is "Benji", the message would be "Beijing and Benji are 40% similar"
      isFuzzyMatch: true,
      fuzzyMatchingThreshold: 0.2
    },
    {
      command: ['eat', 'sleep', 'leave'],
      callback: (command) => setMessage(`Best matching command: ${command}`),
      isFuzzyMatch: true,
      fuzzyMatchingThreshold: 0.2,
      bestMatchOnly: true
    },
    {
      command: 'clear',
      callback: ({ resetTranscript }) => resetTranscript()
    }
  ]

  const { transcript, browserSupportsSpeechRecognition } = useSpeechRecognition({ commands })

  if (!browserSupportsSpeechRecognition) {
    return null
  }

  return (
    <div>
      <p>{message}</p>
      <p>{transcript}</p>
    </div>
  )
}
export default Dictaphone

Continuous listening

By default, the microphone will stop listening when the user stops speaking. This reflects the approach taken by "press to talk" buttons on modern devices.

If you want to listen continuously, set the continuous property to true when calling startListening. The microphone will continue to listen, even after the user has stopped speaking.

SpeechRecognition.startListening({ continuous: true })

Be warned that not all browsers have good support for continuous listening. Chrome on Android in particular constantly restarts the microphone, leading to a frustrating and noisy (from the beeping) experience. To avoid enabling continuous listening on these browsers, you can make use of the browserSupportsContinuousListening state from useSpeechRecognition to detect support for this feature.

if (browserSupportsContinuousListening) {
  SpeechRecognition.startListening({ continuous: true })
} else {
  // Fallback behaviour
}

Alternatively, you can try one of the polyfills to enable continuous listening on these browsers.

Changing language

To listen for a specific language, you can pass a language tag (e.g. 'zh-CN' for Chinese) when calling startListening. See here for a list of supported languages.

SpeechRecognition.startListening({ language: 'zh-CN' })

Troubleshooting

regeneratorRuntime is not defined

If you see the error regeneratorRuntime is not defined when using this library, you will need to ensure your web app installs regenerator-runtime:

How to use react-speech-recognition offline?

Unfortunately, speech recognition will not function in Chrome when offline. According to the Web Speech API docs: On Chrome, using Speech Recognition on a web page involves a server-based recognition engine. Your audio is sent to a web service for recognition processing, so it won't work offline.

If you are building an offline web app, you can detect when the browser is offline by inspecting the value of navigator.onLine. If it is true, you can render the transcript generated by React Speech Recognition. If it is false, it's advisable to render offline fallback content that signifies that speech recognition is disabled. The online/offline API is simple to use - you can read how to use it here.

Developing

You can run an example React app that uses react-speech-recognition with:

npm i
npm run dev

On http://localhost:3000, you'll be able to speak into the microphone and see your speech as text on the web page. There are also controls for turning speech recognition on and off. You can make changes to the web app itself in the example directory. Any changes you make to the web app or react-speech-recognition itself will be live reloaded in the browser.

API docs

View the API docs here or follow the guide above to learn how to use react-speech-recognition.

License

MIT