Rooks
HooksBrowser APIs

useSpeech

Converts text to speech using the Web Speech API.

About

Speech synthesis hook for React that provides an easy-to-use interface for the Web Speech API. This hook allows you to convert text to speech with customizable voice settings and playback controls.


Examples

Basic example

import { useSpeech } from "rooks";

export default function App() {
  const { start, stop, isPlaying } = useSpeech({
    text: "Hello, welcome to our application!",
  });

  return (
    <div>
      <h3>Basic Text to Speech</h3>
      <p>Text: "Hello, welcome to our application!"</p>
      <button onClick={start} disabled={isPlaying}>
        {isPlaying ? "Speaking..." : "Start Speaking"}
      </button>
      <button onClick={stop} disabled={!isPlaying}>
        Stop
      </button>
    </div>
  );
}

Advanced settings example

import { useSpeech } from "rooks";
import { useState } from "react";

export default function App() {
  const [text, setText] = useState("This is a customizable speech example.");
  const [language, setLanguage] = useState("en-US");
  const [rate, setRate] = useState(1);
  const [pitch, setPitch] = useState(1);
  const [volume, setVolume] = useState(1);

  const { start, pause, resume, stop, isPlaying } = useSpeech({
    text,
    language,
    rate,
    pitch,
    volume,
  });

  return (
    <div>
      <h3>Advanced Speech Settings</h3>

      <div>
        <label>
          Text:
          <textarea
            value={text}
            onChange={(e) => setText(e.target.value)}
            rows={3}
            cols={50}
          />
        </label>
      </div>

      <div>
        <label>
          Language:
          <select
            value={language}
            onChange={(e) => setLanguage(e.target.value)}
          >
            <option value="en-US">English (US)</option>
            <option value="en-GB">English (UK)</option>
            <option value="es-ES">Spanish</option>
            <option value="fr-FR">French</option>
            <option value="de-DE">German</option>
          </select>
        </label>
      </div>

      <div>
        <label>
          Rate: {rate}
          <input
            type="range"
            min="0.1"
            max="2"
            step="0.1"
            value={rate}
            onChange={(e) => setRate(parseFloat(e.target.value))}
          />
        </label>
      </div>

      <div>
        <label>
          Pitch: {pitch}
          <input
            type="range"
            min="0"
            max="2"
            step="0.1"
            value={pitch}
            onChange={(e) => setPitch(parseFloat(e.target.value))}
          />
        </label>
      </div>

      <div>
        <label>
          Volume: {volume}
          <input
            type="range"
            min="0"
            max="1"
            step="0.1"
            value={volume}
            onChange={(e) => setVolume(parseFloat(e.target.value))}
          />
        </label>
      </div>

      <div>
        <button onClick={start} disabled={isPlaying}>
          Start
        </button>
        <button onClick={pause} disabled={!isPlaying}>
          Pause
        </button>
        <button onClick={resume} disabled={isPlaying}>
          Resume
        </button>
        <button onClick={stop} disabled={!isPlaying}>
          Stop
        </button>
      </div>

      <p>Status: {isPlaying ? "Speaking" : "Stopped"}</p>
    </div>
  );
}

Voice selection and callbacks example

import { useSpeech } from "rooks";
import { useState, useEffect } from "react";

export default function App() {
  const [text, setText] = useState("Choose a voice and listen to this text.");
  const [selectedVoice, setSelectedVoice] = useState("");
  const [voices, setVoices] = useState([]);
  const [speechCount, setSpeechCount] = useState(0);

  const { start, pause, resume, stop, isPlaying } = useSpeech({
    text,
    voiceURI: selectedVoice,
    onEnd: () => {
      setSpeechCount((prev) => prev + 1);
      console.log("Speech finished!");
    },
  });

  useEffect(() => {
    const loadVoices = () => {
      const availableVoices = window.speechSynthesis.getVoices();
      setVoices(availableVoices);
      if (availableVoices.length > 0 && !selectedVoice) {
        setSelectedVoice(availableVoices[0].voiceURI);
      }
    };

    loadVoices();
    window.speechSynthesis.onvoiceschanged = loadVoices;

    return () => {
      window.speechSynthesis.onvoiceschanged = null;
    };
  }, [selectedVoice]);

  const handleVoiceChange = (e) => {
    setSelectedVoice(e.target.value);
  };

  return (
    <div>
      <h3>Voice Selection & Callbacks</h3>

      <div>
        <label>
          Text:
          <input
            type="text"
            value={text}
            onChange={(e) => setText(e.target.value)}
            style={{ width: "100%", marginTop: "5px" }}
          />
        </label>
      </div>

      <div>
        <label>
          Voice:
          <select value={selectedVoice} onChange={handleVoiceChange}>
            {voices.map((voice) => (
              <option key={voice.voiceURI} value={voice.voiceURI}>
                {voice.name} ({voice.lang})
              </option>
            ))}
          </select>
        </label>
      </div>

      <div>
        <button onClick={start} disabled={isPlaying}>
          Start Speaking
        </button>
        <button onClick={pause} disabled={!isPlaying}>
          Pause
        </button>
        <button onClick={resume} disabled={isPlaying}>
          Resume
        </button>
        <button onClick={stop} disabled={!isPlaying}>
          Stop
        </button>
      </div>

      <div>
        <p>Status: {isPlaying ? "🔊 Speaking" : "🔇 Stopped"}</p>
        <p>Speech completed {speechCount} times</p>
      </div>
    </div>
  );
}

Parameters

ArgumentTypeDescription
optionsObjectConfiguration options

Options

OptionTypeDescriptionDefault value
textstringThe text to be spokenrequired
languagestringLanguage code (e.g., "en-US", "es-ES", "fr-FR")"en-US"
voiceURIstringSpecific voice URI to use for speechundefined
onEndfunctionCallback function called when speech endsundefined
volumenumberVolume level (0 to 1)1
pitchnumberPitch level (0 to 2)1
ratenumberSpeech rate (0.1 to 10)1

Return value

Return valueTypeDescription
controlsObjectObject containing {start, pause, resume, stop, isPlaying} speech control functions and state

Controls Object

PropertyTypeDescription
startfunctionStart speaking the text
pausefunctionPause the current speech
resumefunctionResume paused speech
stopfunctionStop speaking and reset
isPlayingbooleanCurrent playing state of the speech synthesis

Behavior and lifecycle

start cancels any speech already queued in the page, creates a new utterance, and updates isPlaying from its start/end/error events. While playing, option changes update the current utterance. pause, resume, and stop delegate to the global speech-synthesis controller. The hook does not cancel speech on unmount; call stop in application cleanup when speech must not outlive the component.

Compatibility and accessibility

Rendering is SSR-safe, but invoking controls requires window; start logs and returns if speech synthesis is unavailable. A missing voiceURI silently uses the platform voice, and voice lists may load asynchronously. Browsers may clamp or ignore volume, pitch, and rate. Never autoplay important text, provide pause/stop controls, and keep the same information readable on screen.

On this page