Easy Speech

repository·master·Indexed 42 days ago

https://github.com/leaonline/easy-speech

A cross-browser wrapper for the Web Speech API's synthesis part, providing an asynchronous, Promise-based API to handle browser-specific quirks and inconsistent voice loading behaviors. Version 2.4.1-rc.1 includes features for detecting TTS support, managing playback (pause, resume, cancel), and filtering available voices.

Tokens
3K
Snippets
10
Records
17
Agent score
54%

What's inside Easy Speech

  1. How to install or change available voices

    master

    EasySpeech is a wrapper for the Web Speech API, meaning it can only access voices provided by the browser or the operating system. You cannot install new voices via JavaScript. To provide better voice options to your users, they must take action at the browser or OS level:

  2. Install easy-speech

    master

    You can install easy-speech via npm:

    $ npm install easy-speech

    Alternatively, you can use various builds from the dist folder for different environments:

    • /dist/EasySpeech.js - ESM
    • /dist/EasySpeech.cjs.js - CommonJs
    • /dist/EasySpeech.es5.js - Legacy node compatible
    • /dist/EasySpeech.iife.js - Legacy compatible build (works with older/exotic browsers that support Promises)
    • /dist/index.d.ts - TypeScript type definitions

    For browser-based usage via CDN:

    ESM:

    <script type="module">
      import easySpeech from 'https://cdn.jsdelivr.net/npm/easy-speech/+esm'
    </script>

    Classic/IIFE:

    <script src="https://cdn.jsdelivr.net/npm/easy-speech/dist/EasySpeech.iife.js"></script>
  3. Initialize EasySpeech

    master

    Because cross-browser voice loading can be inconsistent, use the asynchronous EasySpeech.init() function to prepare the environment. This routine handles detecting support, loading voices via onvoiceschanged, and falling back to a timeout mechanism if voices aren't immediately available.

    Configuration Options:

    • maxTimeout: The maximum time to wait for voices to load (in milliseconds).
    • interval: The interval at which to reload voices if they haven't loaded yet (in milliseconds).

    Fallback Voice Logic: If voices are found, easy-speech automatically selects a fallback voice using these rules:

    1. A voice with the default property set to true.
    2. The first matching voice for the current navigator.language.
    3. The first voice in the available array.

    Note: This fallback is separate from EasySpeech.defaults() and ensures a voice is always available if EasySpeech.speak() is called.

    EasySpeech.init({ maxTimeout: 5000, interval: 250 })
        .then(() => console.debug('load complete'))
        .catch(e => console.error(e))
  4. Workaround for iOS Safari autoplay restrictions

    master

    On iOS Safari, speechSynthesis.speak() is often blocked if it is not triggered by a direct user interaction (like a click). If you try to trigger speech from an asynchronous source (e.g., an API response or useEffect), it will fail.

    Workaround: Create a "trusted session" by calling EasySpeech.speak() with a silent, fast dummy utterance during the initial user interaction. Once this session is established, subsequent programmatic calls to .speak() will work.

    // Call this during a button click or user gesture
    await EasySpeech.speak({
    text: " ",     // whitespace
    volume: 0,     // muted
    rate: 10       // very fast
    });
    await EasySpeech.speak({
    text: " ",     // whitespace
    volume: 0,     // muted
    rate: 10       // very fast
    });
  5. Fix 'EasySpeech: not initialized. Run EasySpeech.init() first'

    master
    This error occurs because EasySpeech.init() has not been called. You must initialize the library before attempting to use any other methods (like .speak()). Refer to the API documentation for the correct initialization sequence.
  6. Fix Safari speech delay after audio interaction

    master
    If Safari experiences delays in speech playback after interacting with other audio, you can attempt to prime the speech engine by calling speak with volume: 0 before the intended speech begins.
  7. Handle 'EasySpeech: text exceeds max length of 4096 bytes.'

    master

    Some voices have a maximum text processing limit. If your text exceeds 4096 bytes, you must split the text into smaller chunks and play them sequentially.

    Example of recursive chunk playback:

    let index = 0
    const text = [
      'This is the first sentence.',
      'This is the second sentence.',
    ]
    
    
    async function playToEnd () {
      const chunk = text[index++]
      if (!chunk) { return true } // done
      
      await EasySpeech.speak({ text: chunk })
      return playToEnd()
    }
  8. Speak text with EasySpeech.speak()

    master

    The primary method for speech synthesis. It constructs an utterance by combining provided parameters with module defaults.

    Parameters

    • options (object, required): Configuration for the utterance.
    • text (string, required): The text to be spoken.
    • voice (object, optional): A SpeechSynthesisVoice instance or similar object.
    • handlers (object, optional): Local event handlers for this specific utterance.

    Options Object Keys

    • pitch (number): Value between 0 and 2.
    • rate (number): Value between 0.1 and 10.
    • volume (number): Value between 0 and 1.
    • force (boolean): If true, forces speaking regardless of internal state.
    • infiniteResume (boolean): Controls the internal resumeInfinity pattern.
    • noStop (boolean): If true, will not stop current voices.

    Handlers Object Keys

    • boundary: Function called when a word boundary is reached.
    • end: Function called when speech ends.
    • error: Function called on error.
    • mark: Function called on mark event.
    • pause: Function called when speech is paused.
    • resume: Function called when speech is resumed.
    • start: Function called when speech starts.

    Returns

    Returns a Promise that:

    • Resolves with a SpeechSynthesisEvent on the end event.
    • Rejects with a SpeechSynthesisErrorEvent on the error event.
    const voice = EasySpeech.voices()[10]
    
    EasySpeech.speak({
      text: 'Hello, world',
      voice: voice,
      pitch: 1.2,
      rate: 1.7,
      boundary: event => console.debug('word boundary reached', event.charIndex),
      error: e => notify(e)
    })
  9. Inspect module status and features

    master

    Detect Web Speech API support with detect()

    Returns an object containing the presence and status of Web Speech API components in the global scope:

    {
        "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"
    }

    Check internal state with status()

    Returns a shallow copy of the current internal status.

    • Uninitialized: { status: 'created' }
    • Initialized: Returns an object containing status, initialized, detected features, defaults, handlers, and voices.
  10. Configure global event handlers and defaults

    master

    Set Global Handlers with on()

    Attach handlers that will run for every utterance instance. These run in parallel with local handlers passed to .speak().

    Supported Handlers: boundary, end, error, mark, pause, resume, start.

    Set Global Defaults with defaults()

    Sets the fallback values for all future utterances. Invalid values are ignored.

    Supported Options:

    • voice: SpeechSynthesisVoice instance.
    • pitch: number (0 to 2).
    • rate: number (0.1 to 10).
    • volume: number (0 to 1).