react-speech-recognition

repository·master·Indexed 21 days ago

https://github.com/jamesbrill/react-speech-recognition

A React hook and global object for converting microphone speech into text using the Web Speech API. Version 4.0.1 provides the useSpeechRecognition hook for accessing transcripts and microphone state, and the SpeechRecognition object for controlling the microphone and applying polyfills. It supports custom voice commands with pattern matching, continuous listening, and language configuration. Requires React 16.8 or higher.

Tokens
7K
Snippets
18
Records
26
Agent score
71%

What's inside react-speech-recognition

  1. Use command symbols for pattern matching

    master

    To simplify command writing, react-speech-recognition supports special symbols within command strings:

    • Splats (*): Matches multi-word text. Each word/group matched by a splat is passed as a separate argument to the callback.
      • Example: 'I would like to order *' matches 'I would like to order pizza' (where pizza is passed to the callback).
    • Named variables (:<name>): Matches a single word.
      • Example: 'I am :height metres tall' matches 'I am 6 metres tall' (where 6 is passed to the callback).
    • Optional words ( ): Phrases wrapped in parentheses are not required to match.
      • Example: 'Pass the salt (please)' matches both 'Pass the salt' and 'Pass the salt please'.
    const commands = [
      { command: 'I am :height metres tall', callback: (height) => console.log(height) },
      { command: 'Order *', callback: (item) => console.log(item) },
      { command: 'Hello (there)', callback: () => console.log('Matched') }
    ]
  2. How react-speech-recognition works

    master

    The library consists of two main parts:

    1. useSpeechRecognition: A React hook that provides access to the speech transcript and microphone state within a component.
    2. SpeechRecognition: A global object that manages the Web Speech API state. It provides methods to control the microphone (on/off) and applies polyfills. Because SpeechRecognition manages global state, actions taken on this object affect all components using the useSpeechRecognition hook.

    This library requires React 16.8 or higher.

  3. Apply a polyfill to SpeechRecognition

    master

    To ensure consistent cross-browser support and control over data processing, you can apply a polyfill (e.g., Azure). Use createSpeechServicesPonyfill from your provider's package to create a recognition object, then call SpeechRecognition.applyPolyfill(YourPolyfillObject).

    import React from 'react';
    import createSpeechServicesPonyfill from 'web-speech-cognitive-services';
    import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition';
    
    const SUBSCRIPTION_KEY = '<INSERT_SUBSCRIPTION_KEY_HERE>';
    const REGION = '<INSERT_REGION_HERE>';
    
    const { SpeechRecognition: AzureSpeechRecognition } = createSpeechServicesPonyfill({
      credentials: {
        region: REGION,
        subscriptionKey: SUBSCRIPTION_KEY,
      }
    });
    
    SpeechRecognition.applyPolyfill(AzureSpeechRecognition);
    
    const Dictaphone = () => {
      const { transcript, resetTranscript, browserSupportsSpeechRecognition } = useSpeechRecognition();
    
      const startListening = () => SpeechRecognition.startListening({
        continuous: true,
        language: 'en-US'
      });
    
      if (!browserSupportsSpeechRecognition) return null;
    
      return (
        <div>
          <button onClick={startListening}>Start</button>
          <button onClick={SpeechRecognition.abortListening}>Abort</button>
          <button onClick={resetTranscript}>Reset</button>
          <p>{transcript}</p>
        </div>
      );
    };
    
    export default Dictaphone;
  4. Handle browser support and microphone permissions

    master

    Because the Web Speech API and microphone access vary by browser and user settings, you should implement fallback UI using the properties provided by useSpeechRecognition.

    Browser Support

    Check browserSupportsSpeechRecognition to render fallback content if the API is unavailable.

    Continuous Listening Support

    If your app relies on continuous listening, check browserSupportsContinuousListening (available in the hook output) to provide fallback behavior for browsers that don't support it.

    Microphone Permissions

    If isMicrophoneAvailable is false, the user has denied microphone access. You should disable voice features and prompt the user to enable permissions.

    const { 
      browserSupportsSpeechRecognition, 
      isMicrophoneAvailable 
    } = useSpeechRecognition();
    
    if (!browserSupportsSpeechRecognition) {
      // Render fallback for unsupported browser
    }
    
    if (!isMicrophoneAvailable) {
      // Render fallback for denied microphone access
    }
  5. Enable continuous listening

    master

    By default, the microphone stops listening when the user stops speaking. To keep the microphone active even after pauses, set continuous: true in the startListening method.

    Note on Browser Support: Not all browsers support continuous listening reliably. Chrome on Android may experience frequent restarts and noise. Use the browserSupportsContinuousListening property from the useSpeechRecognition hook to detect support and provide a fallback behavior.

    import SpeechRecognition from 'react-speech-recognition'
    import { useSpeechRecognition } from 'react-speech-recognition'
    
    // Inside a component
    const { browserSupportsContinuousListening } = useSpeechRecognition()
    
    const handleStart = () => {
      if (browserSupportsContinuousListening) {
        SpeechRecognition.startListening({ continuous: true })
      } else {
        // Fallback behavior for browsers without reliable continuous support
      }
    }
  6. Migrate from v2 to v3 using React Hooks

    master

    In v3, react-speech-recognition has moved from a Higher Order Component (HOC) pattern to a React Hooks pattern. Instead of wrapping your component with SpeechRecognition(Component), you should now use the useSpeechRecognition hook to access transcript and state data.

    Key architectural changes in v3:

    • Hooks over HOC: Use useSpeechRecognition() to consume state.
    • Commands: New functionality to execute functions when specific phrases are spoken.
    • Global vs Local State: Global state (like whether the microphone is active) is separated from local state (like individual component transcripts). This allows multiple components to listen to the same microphone while maintaining independent transcripts.
    • Manual Start: autoStart is no longer a global option. Browsers often block automatic microphone access for privacy, so you should trigger listening via user interaction (e.g., a button click).
    import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition'
    
    const Dictaphone = () => {
      const { transcript, resetTranscript, browserSupportsSpeechRecognition } = useSpeechRecognition()
      const startListening = () => SpeechRecognition.startListening({ continuous: true })
    
      if (!browserSupportsSpeechRecognition) {
        return null
      }
    
      return (
        <div>
          <button onClick={startListening}>Start</button>
          <button onClick={resetTranscript}>Reset</button>
          <p>{transcript}</p>
        </div>
      )
    }
    export default Dictaphone
  7. Detect browser support and microphone availability

    master

    Browser Support

    If the user's browser does not support the Web Speech API, use browserSupportsSpeechRecognition from the hook to render fallback content:

    if (!browserSupportsSpeechRecognition) {
      // Render fallback content
    }

    Microphone Access

    If a user denies microphone permissions, the isMicrophoneAvailable state from the hook will become false. You should use this to disable voice features and notify the user:

    if (!isMicrophoneAvailable) {
      // Render fallback content
    }
  8. Use Microsoft Azure Cognitive Services as a polyfill

    master

    You can use Microsoft Azure's speech recognition service to provide speech capabilities in browsers that lack native support. This requires the web-speech-cognitive-services ponyfill and the microsoft-cognitiveservices-speech-sdk.

    Setup

    1. Install dependencies: web-speech-cognitive-services and microsoft-cognitiveservices-speech-sdk.
    2. Configure the ponyfill with your Azure region and either a subscriptionKey or an authorizationToken.
    3. Pass the resulting SpeechRecognition implementation to SpeechRecognition.applyPolyfill().

    Production Security

    Do not use a subscriptionKey in production, as it will be exposed in the client-side code. Instead, fetch a short-lived authorizationToken from your backend and pass that to the polyfill configuration.

    Known Limitations & Tips

    • Continuous Listening: There is a known bug in the stop method when continuous: true is used. Use SpeechRecognition.abortListening() instead of stopListening() to end the session.
    • Language Switching: On Safari and Firefox, calling startListening with a new language without first calling stopListening may throw an error. Always call stopListening() before changing languages.
    • Explicit Language: Azure requires an explicit language code. If you don't provide one, it may return a 400 error. Use codes like en-US or en-GB.
    • iOS: Support is currently untested.
    import React from 'react';
    import createSpeechServicesPonyfill from 'web-speech-cognitive-services';
    import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition';
    
    const REGION = '<INSERT_REGION_HERE>';
    const AUTHORIZATION_TOKEN = '<INSERT_TOKEN_FROM_BACKEND>';
    
    // Create the ponyfill implementation
    const { SpeechRecognition: AzureSpeechRecognition } = createSpeechServicesPonyfill({
      credentials: {
        region: REGION,
        authorizationToken: AUTHORIZATION_TOKEN,
      }
    });
    
    // Apply it to react-speech-recognition
    SpeechRecognition.applyPolyfill(AzureSpeechRecognition);
    
    const Dictaphone = () => {
      const { transcript, browserSupportsSpeechRecognition } = useSpeechRecognition();
    
      const startListening = () => SpeechRecognition.startListening({
        continuous: true,
        language: 'en-US'
      });
    
      if (!browserSupportsSpeechRecognition) return null;
    
      return (
        <div>
          <button onClick={startListening}>Start</button>
          <button onClick={() => SpeechRecognition.abortListening()}>Abort</button>
          <p>{transcript}</p>
        </div>
      );
    };
  9. Fix 'regeneratorRuntime is not defined' error

    master

    If you encounter the regeneratorRuntime is not defined error, you must install the regenerator-runtime package:

    npm i --save regenerator-runtime

    Then, import it at the very top of your entry file:

    • NextJS: Add import 'regenerator-runtime/runtime' to the top of _app.js.
    • Other Frameworks: Add import 'regenerator-runtime/runtime' to the top of index.js.
    // Top of index.js or _app.js
    import 'regenerator-runtime/runtime'
  10. Basic usage of useSpeechRecognition

    master

    To implement basic speech recognition, import SpeechRecognition and useSpeechRecognition. Use the hook to access transcript, listening, resetTranscript, and browserSupportsSpeechRecognition.

    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;