Read Aloud 0.2.1 · Chrome Manifest V3 · plain JavaScript

Read Aloud

Read Aloud is a Chrome extension that reads web pages aloud through a speech endpoint you configure: Azure Speech directly, with SSML, or any OpenAI-compatible speech API. Select a paragraph or let it find the article; it highlights the text as it reads, starts speaking after the first few sentences, and keeps going when you close the popup.

Load it unpacked from chrome/extensions/read-aloud (chrome://extensions → Developer mode → Load unpacked); there is no build step and no store listing.

Permissions

The extension asks for nothing ambient: no access to any site until you act, then only to the tab you acted on, and network access only to the one endpoint origin you approve when you save its settings. Text extraction is injected on demand; the reading itself happens in the extension's own worker and an offscreen audio document.

How the extension is built Read Aloud's Manifest V3 architecture. The popup, the right-click menu and a keyboard shortcut all ask the service worker to read. The worker injects an extraction script into the page only when you act (activeTab and scripting permissions), which finds the selection, the article or the whole page, highlights exactly those text ranges with CSS Custom Highlights and returns the text. The worker splits it into chunks, sends each to the configured endpoint (Azure Speech with SSML, or an OpenAI-compatible speech API) and hands the audio to an offscreen document, which plays it and keeps playing when the popup closes. Settings and keys live in local, trusted-context-only extension storage, and diagnostics keep the last 200 allowlisted events. popup context menu shortcutread-default service workerchunking · requests200-event diagnostics the pageextraction on demandCSS Highlights speech endpointAzure SSMLor OpenAI-compatible offscreen documentplays · survives the popup local storagekeys · presets inject on demandtext + ranges one fetch at a time audio
Three entry points, one pipeline. The popup, the right-click menu and the shortcut all read through the same worker, with the default preset.

Choosing the text

Selection reads the browser's own selected ranges, never the element around them. Article prefers article, main and ARIA landmarks; Whole page takes visible body text outside them. Both skip navigation, forms, hidden ancestors, page chrome and anything you are editing. Preview scope → Highlight shows exactly what would be read, its character count and the first 600 characters, without sending anything.

Highlights are CSS Custom Highlights on the exact text ranges, so they never alter the page, and Clear or Stop removes only the extension's own, leaving your selection intact. A reading is limited to 100,000 characters.

The Read Aloud settings page: voice presets with save, use as default and delete; a connection section with the provider set to Azure Speech direct, the speech endpoint and an empty API key field; and the SSML voice section with model MAI-Voice-2.1-Flash, a voice field, language en-GB, speaker profile and an embedding ID field.
Settings: presets, the connection, and the SSML voice. Presets never include endpoints or keys.

Streaming

A page is too long to synthesise at once, and waiting for all of it would mean silence. Read Aloud splits the text at paragraph, sentence and word boundaries, synthesises a short first chunk so the voice starts quickly, and stays exactly one chunk ahead from then on.

Reading a long page How Read Aloud reads a long page. The first chunk is short, 400 characters by default, so the first audio arrives quickly; later chunks are 1200. Chunks split at paragraph, then sentence, then word boundaries. While one chunk plays, exactly one next chunk is synthesised, never more, so there is no unbounded queue and no full-page cache. Transitions add no delay, a slow endpoint can still leave a gap, and an error in the lookahead surfaces only after the current audio finishes. Stop aborts the pending request and disposes the audio. 0s 10s 20s 30s 40s 50s 60s synthesis playback 1 · 400 chars 2 · 1200 3 · 1200 4 · 1200 chunk 1 chunk 2 chunk 3 illustrative timing; at most one chunk is ever prefetched
One playing, one ready. Never an unbounded queue, never a full-page audio cache; pause survives chunk boundaries.

Both chunk sizes are configurable, 100–1200 characters for the first and 200–3000 for the rest, and splitting is lossless: the chunks concatenate back to the original text. Requests time out after 30 seconds, audio is capped at 8 MiB per chunk, results that arrive after a Stop are never played, and nothing is retried automatically, because every request may be billed.

Endpoints and voices

Azure Speech, direct

The text is escaped into SSML by the extension's own builder, the same kind of document the ssml CLI writes, with model, voice or speaker embedding, language, speed, pitch, volume, emotion, degree and role. The voice name is used exactly as given.

OpenAI-compatible

Plain text, a speed and, if you want, natural-language instructions such as "warm, calm and a little excited" to an origin, a /v1 URL or a full speech URL, with an optional Bearer key. Switching provider clears the unsaved key and endpoint rather than reusing credentials with another service.

Presets and a shortcut

Up to 30 named presets hold a voice and its delivery, never an endpoint or a key. One is the default, used by the popup, the menu and a keyboard shortcut you map yourself, which reads the selection or falls back to the article, the page or nothing.

Diagnostics without your text

Settings keep the latest 200 events across restarts: HTTP status, provider, chunk index, sizes, timings, playback gaps, failure categories and recognised request IDs, copyable as JSON for correlating a 502 with a gateway's logs. Keys, page text, titles, URLs and response bodies are never recorded.