Browser Voice Synthesis Using Web Speech API

The Web Speech API provides built-in browser support for text-to-speech functionality via its Speech Synthesis interface. This allows developers to convert written text into spoken audio directly in client-side JavaScript without requiring external libraries or server-side audio generation. This article explains the core architecture of the Speech Synthesis API, demonstrates how to configure and execute voice commands, and outlines best practices for handling voices and lifecycle events.


Core Interfaces

Voice synthesis in the Web Speech API relies primarily on two main objects:

  1. SpeechSynthesis: The controller interface accessed via window.speechSynthesis. It manages playback state (speaking, paused, pending), retrieves available system voices, and queues utterances to be spoken.
  2. SpeechSynthesisUtterance: The request object representing the speech unit. It contains the text content to be read and configurable properties such as pitch, rate, volume, language, and selected voice.

Basic Implementation

To perform speech synthesis, create an instance of SpeechSynthesisUtterance with your text, configure its properties if necessary, and pass it to window.speechSynthesis.speak().

// Check for browser support
if ('speechSynthesis' in window) {
  // 1. Create a speech utterance
  const utterance = new SpeechSynthesisUtterance("Hello! This is browser-based speech synthesis.");

  // 2. Configure basic properties
  utterance.pitch = 1.0;   // Range: 0 to 2
  utterance.rate = 1.0;    // Range: 0.1 to 10
  utterance.volume = 1.0;  // Range: 0 to 1

  // 3. Queue the utterance for playback
  window.speechSynthesis.speak(utterance);
} else {
  console.warn("Speech Synthesis is not supported in this browser.");
}

Selecting and Loading Voices

The browser provides a list of installed system and browser voices through the speechSynthesis.getVoices() method. Because voices are loaded asynchronously, you must listen for the voiceschanged event to ensure the voice list is populated before selection.

function speakWithCustomVoice(text) {
  const utterance = new SpeechSynthesisUtterance(text);
  const voices = window.speechSynthesis.getVoices();

  // Find a specific English voice or fallback to default
  const selectedVoice = voices.find(voice => voice.lang === 'en-US' && voice.name.includes('Google')) || voices[0];

  if (selectedVoice) {
    utterance.voice = selectedVoice;
    utterance.lang = selectedVoice.lang;
  }

  window.speechSynthesis.speak(utterance);
}

// Ensure voices are loaded
if (window.speechSynthesis.onvoiceschanged !== undefined) {
  window.speechSynthesis.onvoiceschanged = () => {
    const availableVoices = window.speechSynthesis.getVoices();
    console.log(`Loaded ${availableVoices.length} voices.`);
  };
}

Managing Playback and Listening to Events

The SpeechSynthesisUtterance object emits events during its lifecycle, allowing you to track playback status and update user interface elements accordingly.

const utterance = new SpeechSynthesisUtterance("Monitoring speech events.");

utterance.onstart = () => console.log("Playback started.");
utterance.onend = () => console.log("Playback finished.");
utterance.onerror = (event) => console.error("Synthesis error:", event.error);

window.speechSynthesis.speak(utterance);

To control playback globally across the browser session, use the controller methods on window.speechSynthesis:


Key Considerations