speech

Playback API

The playback API is a high-level API that provides a simple interface for playing, pausing, and stopping speech. ReadiumSpeechNavigator wraps a ReadiumSpeechPlaybackEngine that you provide — e.g. WebSpeechEngine or SpeechServerEngine, each documented separately for construction/options; this page covers the shared engine contract and navigator API.

Once initialized, you can use the navigator to load content (utterances) and control playback.

ReadiumSpeechNavigator

ReadiumSpeechNavigator implements ReadiumSpeechNavigatorContract, which extends Configurable<SpeechSettings, SpeechPreferences> — see Preferences for verbosity/prosody settings (settings, preferencesEditor, submitPreferences(), omitted below):

interface ReadiumSpeechNavigatorContract {
  // Voice Management
  getVoices(): Promise<ReadiumSpeechVoice[]>;
  setVoice(voice: ReadiumSpeechVoice | string): void;
  getCurrentVoice(): ReadiumSpeechVoice | null;
  setSpeakInContentLanguage(enabled: boolean): void;
  getSpeakInContentLanguage(): boolean;
  
  // Content Management
  loadContent(content: ReadiumSpeechUtterance | ReadiumSpeechUtterance[]): void;
  loadGndContent(nodes: GndObject[]): Promise<void>;
  getCurrentContent(): ReadiumSpeechUtterance | null;
  getContentQueue(): ReadiumSpeechUtterance[];
  
  // Playback Control
  play(): void;
  pause(): void;
  stop(): void;
  
  // Navigation
  next(): boolean;
  previous(): boolean;
  jumpTo(utteranceIndex: number): void;
  
  // State
  getState(): ReadiumSpeechPlaybackState;
  
  // Events
  on(
    event: ReadiumSpeechPlaybackEvent["type"] | "contentchange",
    listener: (event: ReadiumSpeechPlaybackEvent) => void
  ): () => void;
  
  // Lifecycle
  destroy(): Promise<void>;
}

Example Usage

import { WebSpeechEngine, ReadiumSpeechNavigator } from "@readium/speech";

const navigator = new ReadiumSpeechNavigator(new WebSpeechEngine());

navigator.loadContent([
  { plain: "Hello world.", language: "en" }
]);

function togglePlayback() {
  const state = navigator.getState();
  if (state === "playing") {
    navigator.pause();
  } else {
    navigator.play();
  }
}

togglePlayback();

Two ways to load content — simple and advanced:

contextualizationOverrides

Set once at construction — not part of submitPreferences(), since it doesn’t change at runtime:

const navigator = new ReadiumSpeechNavigator(engine, {
  contextualizationOverrides: { contextualizations, shapes, params },
});

Each field forwards to the matching extractUtterances option — see that doc for what each does and worked examples for every use case (rewording a role, adding a role the catalog has none for, feeding a placeholder the extractor doesn’t compute on its own):

Events

ReadiumSpeechPlaybackEvent

type ReadiumSpeechPlaybackEvent = {
  type: 
    | "start"           // Playback started
    | "pause"           // Playback paused
    | "resume"          // Playback resumed
    | "end"             // Playback ended naturally
    | "stop"            // Playback stopped manually
    | "skip"            // Skipped to another utterance
    | "error"           // An error occurred
    | "boundary"        // Reached a word/sentence boundary
    | "mark"            // Reached a named mark in SSML
    | "idle"            // No content loaded
    | "loading"         // Loading content
    | "ready"           // Ready to play
    | "voiceschanged"   // Available voices changed
    | "languagefallback"; // No voice matched an utterance's content language
  detail?: any;  // Event-specific data
};

Speaking in an utterance’s own content language

By default, playback always uses the selected/default voice. Call setSpeakInContentLanguage(true) to instead match each utterance’s own language field to the best available voice for that language, falling back to the selected/default voice when no match exists (which also fires a "languagefallback" event with detail: { language, reason: "no-matching-voice" }).

ReadiumSpeechPlaybackState

type ReadiumSpeechPlaybackState = "playing" | "paused" | "idle" | "loading" | "ready";

ReadiumSpeechUtterance

interface ReadiumSpeechUtterance {
  id?: string;          // Unique identifier for this content
  plain?: string;       // Plain-text rendering, when available
  ssml?: string;        // SSML rendering, when available
  language?: string;    // Language of this content (BCP 47)
  locate?: LocatorOptions; // Decoded from the source node's textref — spread into createLocator()/decorate()
  synthetic?: boolean;  // True when plain/ssml is a synthesized label/announcement, not text copied from the source
}

Represents a single piece of content to be spoken, as plain text and/or SSML.

synthetic is set on a contextualization catalog entry, or an alt/caption-derived description, rather than text found verbatim in the document (e.g. a table’s “Table. 3 lines. 2 columns.” or a pagebreak’s label) — locate is still safe to use for element-scoped highlighting, but a word-level substring/text-quote search against the DOM should be skipped, since the text isn’t actually there.