Easy Speech


Cross browser Speech Synthesis also known as Text to speech or TTS; no dependencies; uses Web Speech API



Easy Speech

JavaScript Style Guide

Project Status: Active – The project has reached a stable, usable state and is being actively developed.

Test suite

CodeQL Semantic Analysis


npm bundle size

Cross browser Speech Synthesis; no dependencies.

This project was created because it's always a struggle to get the synthesis part of Web Speech API running on most major browsers.

Note: This is not a polyfill package. If your target browser does not support speech synthesis or the Web Speech API, this package is not usable.


Install from npm via:

$ npm install easy-speech

You can also use the various builds for different targets, see the dist folder:

  • /dist/EasySpeech.js - ESM
  • /dist/EasySpeech.cjs.js - CommonJs
  • /dist/EasySpeech.es5.js - Legacy node compatible
  • /dist/EasySpeech.iife.js - Legacy compatible build, works even with older or exotic browsers, as long as they support Promises (PRs welcome to transform to callbacks!)

You can use them via CDN:

<script src="https://cdn.jsdelivr.net/npm/easy-speech/+esm"></script>


Import EasySpeech and first detect if your browser is capable of text-to-speech (tts):

import EasySpeech from 'easy-speech'


It returns an Object with the following information:

  speechSynthesis: SpeechSynthesis|undefined,
  speechSynthesisUtterance: SpeechSynthesisUtterance|undefined,
  speechSynthesisVoice: SpeechSynthesisVoice|undefined,
  speechSynthesisEvent: SpeechSynthesisEvent|undefined,
  speechSynthesisErrorEvent: SpeechSynthesisErrorEvent|undefined,
  onvoiceschanged: Boolean,
  onboundary: Boolean,
  onend: Boolean,
  onerror: Boolean,
  onmark: Boolean,
  onpause: Boolean,
  onresume: Boolean,
  onstart: Boolean

If at least SpeechSynthesis and SpeechSynthesisUtterance are defined, you are good to go.


Preparing everything to work is not as clear as it should be, especially when targeting cross-browser functionality. The asynchronous init function will help you with this situation:

EasySpeech.init({ maxTimeout: 5000, interval: 250 })
    .then(() => console.debug('load complete'))
    .catch(e => console.error(e))

Loading voices

The init-routine will go through several stages to setup the environment:

  • Detect if SpeechSynthesis is basically supported. If not, fail.
  • Load voices directly.
  • If not loaded but onvoiceschanged is available, use onvoiceschanged
  • If onvoiceschanged is not available, fallback to timeout.
  • If onvoiceschanged is fired but no voices available, fallback to timeout.
  • Timeout reloads voices in a given interval until a maxTimeout is reached.
  • If voices are loaded until then, complete.
  • If no voices found, fail.

If your init routing has still not detected or loaded any voices, although speechSynth is supported, please leave an issue!

Placing a fallback voice

If voices are found, it will place a fallback voice by the following rules:

  • If there is a voice among all voices with the default property set to true, use this as fallback voice.
  • Otherwise, find the first matching voice by current navigator.language.
  • Otherwise, use the first voice in the Array.

Note: This fallback voice is not overridden by EasySpeech.defaults(). Your default voice will be used in favor, but the fallback voice will always be there in case no voice is found when calling EasySpeech.speak().

Company Screenshot