https://github.com/leaonline/easy-speech
๐ Cross browser Speech Synthesis also known as Text to speech or TTS; no dependencies; uses Web Speech API
https://github.com/leaonline/easy-speech
browser cross-browser hacktoberfest hacktoberfest-accepted javascript js speech-synthesis standards text-to-speech tts web web-speech-api
Last synced: 6 months ago
JSON representation
๐ Cross browser Speech Synthesis also known as Text to speech or TTS; no dependencies; uses Web Speech API
- Host: GitHub
- URL: https://github.com/leaonline/easy-speech
- Owner: leaonline
- Created: 2021-11-26T11:46:09.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2025-02-01T11:33:20.000Z (8 months ago)
- Last Synced: 2025-04-12T23:34:17.197Z (6 months ago)
- Topics: browser, cross-browser, hacktoberfest, hacktoberfest-accepted, javascript, js, speech-synthesis, standards, text-to-speech, tts, web, web-speech-api
- Language: JavaScript
- Homepage: https://leaonline.github.io/easy-speech/
- Size: 1.12 MB
- Stars: 227
- Watchers: 5
- Forks: 24
- Open Issues: 18
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
Easy Speech
Cross browser Speech Synthesis; no dependencies.
[](https://standardjs.com)
[](https://www.repostatus.org/#active)
[](https://github.com/leaonline/easy-speech/actions/workflows/tests.yml)
[](https://github.com/leaonline/easy-speech/actions/workflows/codeql-analysis.yml)



[](https://zenodo.org/doi/10.5281/zenodo.10816462)## โญ๏ธ Why EasySpeech?
This project was created, because it's always a struggle to get the synthesis
part of `Web Speech API` running on most major browsers.## โจ Features
- ๐ช Single API for using `speechSynthesis` across multiple browsers
- ๐ Async API (Promises, async/await)
- ๐ Hooks for all events; global and/or voice-instance-specific
- ๐ฑ Easy to set up and integrate: auto-detects and loads available voices
- ๐ง Includes fixes or workarounds for many browser-specific quirks
- ๐ Internal logging via `EasySpeech.debug` hook
- ๐ฆ Multiple build targets
- ๐ฎ Live demo to test your browser
**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.## ๐ Live Demo
The live demo is available at https://leaonline.github.io/easy-speech/
You can use it to test your browser for `speechSynthesis` support and functionality.[](https://leaonline.github.io/easy-speech/)
## Table of Contents
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [๐ฆ Installation](#-installation)
- [๐จโ๐ป Usage](#-usage)
- [๐ Initialize](#-initialize)
- [๐ข Speak a voice](#-speak-a-voice)
- [๐ตโ๐ซ Troubleshooting / FAQ](#-troubleshooting--faq)
- [๐ฌ API](#-api)
- [โจ๏ธ Contribution and development](#-contribution-and-development)
- [๐ Resources](#-resources)
- [โ๏ธ License](#-license)## ๐ฆ Installation
Install from npm via
```bash
$ 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!)
- `/dist/index.d.ts` - TypeScript type definitionsYou can use them via CDN:
```html
import easySpeech from 'https://cdn.jsdelivr.net/npm/easy-speech/+esm'
```
```html
```
## ๐จโ๐ป Usage
Import `EasySpeech` and first, detect, if your browser is capable of tts (text
to speech):```javascript
import EasySpeech from 'easy-speech'EasySpeech.detect()
```it returns an Object with the following information:
```javascript
{
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.### ๐ Initialize
Preparing everything to work is not as clear as it should, especially when
targeting cross-browser functionality. The asynchronous init function will help
you with this situation:```javascript
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 and that 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 -> failIf your init routing has still not detected / loaded any voices, allthough
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 ArrayNote: 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()`### ๐ข Speak a voice
This is as easy as it gets:
```javascript
await EasySpeech.speak({
text: 'Hello, world!',
voice: myLangVoice, // optional, will use a default or fallback
pitch: 1,
rate: 1,
volume: 1,
// there are more events, see the API for supported events
boundary: e => console.debug('boundary reached')
})
```The Promise will automatically resolve when the speaking ends or rejects when
an error occurred. You can additionally attach these event listeners if you like
or use `EasySpeech.on` to attach default listeners to every time you call
`EasySpeech.speak`.### ๐ตโ๐ซ Troubleshooting / FAQ
There is an own [FAQ section](./FAQ.md) available that aims to help with common issues.
## ๐ฌ API
There is a full API documentation available: [api docs](./API.md)
## โจ๏ธ Contribution and development
Every contribution is welcomed, please open issues if anything is not working
as expected.If you intend to contribute code, please read the
[guidelines on contributing](./CONTRIBUTING.md).## ๐ Resources
This project used several resources to gain insights about how to get the best cross-browser SpeechSynthesis running:
- https://wicg.github.io/speech-api/#tts-section
- https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis
- https://gist.github.com/alrra/6741915
- https://github.com/ubershmekel/audio-language-tests
- https://stackoverflow.com/questions/33889107/speech-synthesis-in-chrome-for-android-not-loading-voices
- https://stackoverflow.com/questions/49506716/speechsynthesis-getvoices-returns-empty-array-on-windows
- https://stackoverflow.com/questions/21947730/chrome-speech-synthesis-with-longer-texts
- https://stackoverflow.com/a/34130734
- https://stackoverflow.com/a/68060634
- https://stackoverflow.com/a/48056986
- https://bugs.chromium.org/p/chromium/issues/detail?id=582455
- https://stackoverflow.com/a/65883556## โ๏ธ License
MIT, see [license file](./LICENSE)