Open-source project
ken107/read-aloud avatar
ken107/read-aloud

read-aloud zips a hand written file list, so the code that runs inside the page comes from an object store instead

An awesome browser extension that reads aloud webpage content with one click

1,756 stars305 forksJavaScriptMIT

At a glance

What is it?
ken107/read-aloud is a Chrome and Firefox text to speech extension that still has no test directory and no build step, where the packaged archive omits the page-scripts directory entirely, the build script ends in a construct that swallows its own failure, and the three version numbers in the project disagree with each other.
Who is it for?
read-aloud is worth installing if you want a page read aloud with the voices your browser already has, and the paid cloud voices are a separate decision from the extension itself. Two things to know before you rely on it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The package script zips a fixed list, and page-scripts is not on it

There is no build step. The whole packaging pipeline is one npm script that calls `zip` on a literal list of paths:

json
"package": "zip -r build/package.zip _locales css img js sound *.html manifest.json background.js -x \\*.map || true",
"sync-page-scripts": "rsync -avz js/messaging.js page-scripts/ && aws s3 sync --delete --metadata-directive REPLACE --cache-control max-age=14400,public page-scripts s3://lsdsoftware-assets/read-aloud/page-scripts"

Compare that list with the top level of the repository. `page-scripts/`, `tools/`, `docs/`, `introduction.md` and `package.json` itself are all absent from the archive, while `_locales`, `css`, `img`, `js`, `sound`, every top level HTML file, the manifest and the background script are all in it.

The page scripts are the interesting omission, because a second script explains where they go instead. It copies one file out of `js/` into `page-scripts/`, then syncs that directory to an object storage bucket with `--delete`, so removing a file locally removes it from the bucket too, and with a cache lifetime of 14400 seconds, four hours, marked public. The consequence is that the code injected into the page is not part of the archive the store reviewed, and what your browser runs can be up to four hours behind what was published.

The build script ends in a construct that swallows its own failure

The end of the package command is `-x \\.map || true`, and the second half matters more than the map exclusion. The `|| true` means the shell returns success no matter what the `zip` did, so a packaging run that failed still reports itself as done.

The first half excludes source maps from the archive, which is sensible for a shipped extension. What the combination adds up to is a build that cannot fail loudly, which is a poor fit for the one operation in this project that other people depend on. Anyone producing a Firefox build from source follows seven manual steps, and step two is:

bash
mkdir build
npm run-script package

Then the resulting zip is extracted by hand and its `manifest.json` is selected through the `about:debugging` page. If the zip step quietly did nothing, the next step fails on a missing file rather than on a clear build error.

There is nothing to lean on instead. The manifest declares no dependencies and no development dependencies, there is no test directory in the tree, and the two scripts are the entire tool surface, so the project's correctness rests on the archives being built and inspected by whoever is releasing them.

The manifest says 1.0.1 and the newest tag says v1.54.1

Three version numbers exist in this project and no two agree.

json
"name": "read-aloud",
"version": "1.0.1",
"description": "A Chrome extension that reads aloud the webpage's content with just one click. Support 40+ languages."

The newest release tag is v1.54.1, from 2022. Before it sit v1.54.0 from the same day, and before that a tag named `ff-1.45.1` from 2021, which uses a different prefix entirely. So the tags are not even on one naming scheme, and the manifest version of 1.0.1 sits well below every one of them.

That gap is not cosmetic, because for a browser extension the manifest is the authority on what version is installed. Whatever number the web store shows, the file the browser reads is the one in `manifest.json`, and the repository copy says 1.0.1.

The description in the manifest also names one browser where the page names two. The manifest calls it a Chrome extension, while the installation section covers Chrome and Chromium based browsers and Firefox separately, and the Firefox instructions are the only place a source install is documented at all.

The newest release undid the one before it fifty-four minutes later

Two releases carry messages rather than version names, and they are worth reading together. v1.54.0, published at 16:40 on 2022-03-09, is titled Make Google Docs work better. v1.54.1, published at 17:34 the same afternoon, is titled Undo previous release.

So the most recent thing this project published was a rollback of the change before it, fifty-four minutes after shipping it, in the same version line, with the patch number incremented rather than the release being withdrawn. Anything that pins v1.54.1 as a good state is pinning the state after the revert, not the improved Google Docs handling. The third recent tag, `ff-1.45.1` from 2021, is titled only Bug fix.

That pattern is the reason the release history is the most useful page in the project. The store listings are the current versions, the branch is ahead of all of them, and the one message that explains a behaviour change is a message about undoing something.

The last release is from 2022 and the default branch has moved every year since

The releases stop in March 2022. The repository is not archived, and its most recent push is dated 2026-09-24, so the default branch, `master`, has been receiving work for more than four years after the last tag. Nothing on the page says whether those commits are published anywhere else, and the installation section points only at the Chrome Web Store and the Mozilla Add-ons site, both of which serve the released version.

The gap is visible in the manifest in a second way. It describes support for 40 or more languages, and the repository carries a `_locales/` directory for them, but the number that ships is the one in the released archive, and the branch's `manifest.json` carries a different version string from the tags anyway.

The public surface has also widened since those releases. The top level of the tree holds a page for the offscreen document, one for the PDF viewer, one for connecting a phone, and separate pages for options, advanced options, custom voices, languages, the player, shortcuts and error reports. Which of those correspond to a shipped feature and which are branch-only work is not something the page answers.

Basic Usage has two headings and nothing under either of them

The usage section is a pair of empty headings. `Extension Button` is followed immediately by `Right Click Menu`, which is followed immediately by `Advanced Usage`. So the two things a new user does first, clicking the toolbar button and using the context menu, are named as sections and then left empty.

The rest of the usage material picks up at the advanced level. The shortcut set is the only block given as a listing:

yaml
ALT/Option + P           : Play/Pause
ALT/Option + O           : Stop
ALT/Option + Comma       : Rewind
ALT/Option + Period      : Forward

And customization is described as a three step route that crosses two different menus. You click the Read Aloud icon on the browser's extensions menu, stop whatever is currently playing, and then open the gear icon in the Read Aloud context menu, with a note that the settings may take a second or two to appear. That path is why an extension that claims one click to read a page needs a paragraph to change the voice, and it is also why the two empty headings are a real gap rather than a formatting artefact.

The Firefox source install ends at a hand extracted manifest.json

Installing from a store is two sentences, one per browser. Installing in Firefox from source is seven steps, and none of them is automated beyond the packaging script.

You create a build directory, run the package script, and extract the resulting zip by hand, which is where the `manifest.json` used later comes from. Then you remove any existing copy of the add-on from the browser, because Firefox will not load a second version alongside the installed one. From there the instructions go through the browser's own debugging page: type `about:debugging` in the address bar, click This Firefox, click Load Unpackaged Extension, and select the `manifest.json` produced in the earlier step.

There is no mention of what a rebuild does to that state, or of how to reload the unpacked copy after changing a script, which is the operation anyone working on the extension will want most often. It is also the only route that gets the branch code rather than the released code, so it is the path that goes with the four year gap between the last tag and the last push.

Editorial conclusion

read-aloud is worth installing if you want a page read aloud with the voices your browser already has, and the paid cloud voices are a separate decision from the extension itself. Two things to know before you rely on it. The releases stopped in 2022 while the branch has taken commits every year since, so what the stores serve and what is on the default branch are different things. And the scripts injected into the page are not in the package at all, they are published to an object store with a four hour cache, which means the code running in your browser can be up to that old regardless of the installed version. The customization path through two different menus is the other small cost of the setup.

Frequently asked questions

Which voices can read-aloud use?

Voices the browser provides natively, plus cloud text to speech services including Google Wavenet, Amazon Polly, IBM Watson and Microsoft. Some of the cloud based voices are described as needing an additional in-app purchase to enable.

What keyboard shortcuts does read-aloud have?

Four, all built on ALT or Option. P plays and pauses, O stops, Comma rewinds, and Period forwards.

How do I install read-aloud in Firefox from source?

Create a build directory with mkdir build, run npm run-script package, and extract the resulting zip. Then in Firefox remove any existing copy of the add-on, open about:debugging, choose This Firefox and Load Unpackaged Extension, and select the manifest.json from the extracted folder.

Does the read-aloud package include everything in the repository?

No. The package script zips a fixed list of directories and files, and page-scripts is not in it. Those scripts are published to an object storage bucket by a separate sync script instead, with a four hour cache lifetime.

How do I change the voice in read-aloud?

Stop whatever is playing, open the Read Aloud icon from the browser extensions menu, and click the gear icon in the Read Aloud context menu, allowing a second or two for the settings to appear. The settings cover voice, reading speed, pitch and text highlighting.

Official sources

  1. ken107/read-aloud on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ken107-read-aloud.svg)](https://hysenlabs.com/projects/ken107-read-aloud)