Global Speed's version numbers disagree with each other, and its build chain assumes a Mac shell
Web extension to set a default speed for video and audio
At a glance
- What is it?
- A TypeScript browser extension that forces one playback speed onto every video and audio element on a page. The feature set is clear, but the version identifiers, the build scripts and the documentation each tell a slightly different story.
- Who is it for?
- The extension does one thing that most players do not, which is apply a speed you already chose to every video and audio element without asking again, and it does that across sites the README names, YouTube, Netflix, Spotify and podcast pages among them.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 10, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The manifest says 1.0.0 and the published build is 3.4.124
Four identifiers describe the same extension and they do not agree with each other.
The package manifest opens with `"name": "globalspeed"` and `"version": "1.0.0"`, and declares `"type": "module"`. The release tags tell a different story: v3.4.117 on 2026-08-25, v3.4.120 on 2026-09-21, v3.4.124 on 2026-09-28, each published under the name Global Speed. The build scripts name a third thing, `global-speed-chromium.zip`, and the Chrome Web Store listing the README links to carries a fourth, `global-speed-youtube-netf`.
None of that breaks anything at runtime, because an extension's identity comes from the manifest inside the packed directory rather than from the npm version string. It does mean the version field is not a usable handle. If you are pinning this project in a build, tracking a changelog, or matching a source checkout against a store listing, the only numbers that move are the tags, and the manifest stays at 1.0.0 while they climb past it. The three tags above also show a cadence worth noticing: the patch number rises in gaps of three or four across five weeks, with no major or minor tag in that window.
The practical result is that nothing in the tree ties a source commit to a store version, so the checkout on your disk and the extension in your browser can differ without anything in the project saying so.
The dev script assumes a POSIX shell and sweeps a macOS file
The scripts that do the real work are written for a shell with `export` and `find` in it.
"common": "node tools/viteBuild.js && node tools/localeTools/index.cjs build && find build -name '.DS_Store' -type f -delete",
"dev": " export NODE_ENV=development && npm run common",
"commonFf": "FIREFOX=true node tools/viteBuild.js && FIREFOX=true node tools/localeTools/index.cjs build && find buildFf -name '.DS_Store' -type f -delete",
"prod": " export NODE_ENV=production && npm run common && cd build/unpacked && zip -r '../global-speed-chromium.zip' .",The `.DS_Store` deletion in both chains is the clearest sign of where this is worked on: the build removes a macOS Finder artefact out of its own output directory before packaging. That is a no-op on macOS and Linux, and on any host whose shell is not POSIX the chain stops at the first command it cannot run rather than skipping past it. Two smaller details sit in the same block. `dev` and `prod` set NODE_ENV and hand it to nothing explicitly, relying on the child processes to read it from the environment. And `prod` uses `cd` in the middle of the script, so the directory change holds for the rest of that chain and no longer, which is why the zip lands one level up from the directory it was told to pack.
Neither detail is something you will notice locally. Both turn into one on a build machine that runs the scripts as written, from a directory that is not the repository root.
Firefox has its own chain, its own assets, and no loading instructions
The Firefox target is a parallel build rather than a configuration flag, and the written instructions stop before reaching it.
`commonFf`, `devFf` and `prodFf` prefix every step with `FIREFOX=true`, write to `buildFf` instead of `build`, and produce `global-speed-firefox.zip` next to the Chromium archive. A fourth script, `prodFff`, goes further and builds a source package, copying `src`, `static`, `staticCh`, `staticFf`, `tools`, `package-lock.json`, `package.json`, `tsconfig.json` and `vite.config.js` into a staging directory before zipping it to `buildFf/source.zip`. The tree carries `firefox-build.md` as its own file, and the manifest sets a browserslist of `chrome >= 116` and `firefox >= 128`, so the two targets are not even on the same floor.
The loading instructions do not follow. The build chapter has three numbered steps, and the third one, load the unpacked folder, has exactly two sub items: Chrome, where you open the extensions page, enable dev mode and load unpacked, and Edge, where you open the extensions page and load unpacked. Firefox appears in the install links at the top of the README and nowhere in the build chapter, even though it is the target with the most separate machinery behind it.
One substitution is worth knowing about before you read any of those build notes: `prodFff` copies `firefox-build.md` to `zed/unpacked/README.md`. The README that ships inside the Firefox source package is not the one at the root of the tree.
Three static asset trees and a locale tool that also emits types
Translations are produced during the build, by a tool that lives outside the source directory and has three entry points.
`node tools/localeTools/index.cjs build` runs at the end of both the Chromium and the Firefox chain, which means no string in the built extension is hand edited. Two other scripts drive the same tool: `gsm` passes `types`, and `locale` passes nothing at all. That asymmetry is the small puzzle here, since every other use of the tool names its subcommand explicitly and the bare form is left for the tool itself to interpret.
Assets are split three ways to match. The tree holds `static/`, `staticCh/` and `staticFf/`, so the shared assets and the two per browser sets sit side by side and the build decides which to copy. Related to that, the manifest's sideEffects list ends with `notFirefox/background/capture`, a path named for the case where the browser is not Firefox, which is how a module meant to be excluded from one target keeps a name that says so.
Around those sit the housekeeping scripts. `lint` runs `tsc --noEmit` and does nothing else, `format` runs `prettier --check` across `**/*.{js,ts,tsx,json,css}` with a dedicated `format:fix`, and a `.prettierignore` sits next to `prettier.config.js` and `components.json` at the top level. `release` runs `node tools/release.js`, and the only description of what that script does is its filename.
sideEffects pins four paths so the bundler cannot drop them
The manifest keeps a short list of modules alive on purpose, and it is the only place in the tree where that intent is written down.
The `sideEffects` array has five entries: `./src/background/utils/*.ts`, `./src/background/badge.ts`, `./src/background/rules.ts`, `./src/background/capture.ts`, and `notFirefox/background/capture`. Declaring these as side effectful tells the bundler to keep the code even when nothing imports an export from it, which is the mechanism that stops tree shaking from deleting a background module whose real job is to run. The first entry is the only glob in the list, so anything added under `src/background/utils/` is covered by one pattern rather than by name.
Two observations follow from the shape of the list. The last entry is written without the leading `./` and without a file extension, unlike the four above it, so it is the one path whose resolution depends on how the bundler normalises a bare path. And the list is a closed set: a new module outside these five paths has to be added here or it can be removed from a release without any check failing. For an extension whose features are hotkeys, URL rules, badge state and media capture, that is a quiet failure mode, because a missing module usually looks like a feature that stopped responding rather than like a build error.
The names in the array also map onto the feature list: rules for the per site speeds, badge for toolbar state, capture for the media the extension reaches.
A shortcut here can change audio in a window you are not looking at
The hotkey layer is the part of this extension that reaches outside the page you are reading.
The README advertises customizable shortcuts for changing speed, plus rewind and forward, frame by frame analysis, and volume up and down, and then adds the sentence that matters for scope: support for multiple trigger modes, including context menu and global shortcuts, so you can control background music or picture in picture videos while using another app. A global shortcut is not scoped to the focused element, and picture in picture is by definition a surface you are not typing into. Combined with the URL rule feature, which applies a speed automatically on specific sites, the extension has three independent ways to act on media you did not select: a remembered per site rule, a key pressed while another window has focus, and a filter toggled from a menu.
The filters are the loudest of those. Alongside brightness and contrast for a dark Netflix movie, the list includes a volume boost of up to 600 percent and a pitch shift, with the audio effects group marked Chromium only. Those act on whatever is playing rather than on anything the extension created, which is exactly the case where a wrong setting is audible everywhere at once.
What the documentation does not settle is which trigger modes are active out of the box, or how to tell after the fact which one changed a setting. Worth settling in your own configuration before you rely on it.
URL rules are a named feature with no pattern syntax anywhere
One of the two headline features is described in a single line and never specified.
The line is that you can define URL rules to auto apply your favorite speeds on specific sites. What follows it is a compatibility claim, listing YouTube, Netflix, Spotify and podcast sites, and more. The more is not enumerated. No pattern syntax is given, no example rule is written out, no precedence is stated for the case where two rules match the same page, and no way is described for seeing which rule fired or for listing the rules you already have. So the feature is present, the mechanism is named, and the part you would need in order to write a rule is missing.
What the tree does show is where the behaviour lives. Rules are one of the modules pinned in the manifest's sideEffects list, `src/background/rules.ts`, which means rule evaluation is a background side effect rather than something injected into the page. That is consistent with an extension that applies a speed to any media element it finds, but it also means the rule language is only discoverable by reading that file.
One more document sits at the top level without being mentioned anywhere in the README: `PRIVACY_POLICY.md`. The README names no permissions and points at no policy, while the feature set implies reaching media on arbitrary pages and continuing to act on background tabs. The tree also carries no licence file.
Editorial conclusion
The extension does one thing that most players do not, which is apply a speed you already chose to every video and audio element without asking again, and it does that across sites the README names, YouTube, Netflix, Spotify and podcast pages among them. Take it if you want a global default rather than a per player setting, and read the filters section first, since a 600 percent volume boost and a pitch shift applied to media you did not create is the part that reaches beyond your own playback. Before you pin anything, check that the tag you track is the version your users run, because the manifest sits at 1.0.0 while the tags move through 3.4.x, and check that your build shell understands export and find, because the dev and prod scripts assume it does. If you write URL rules, expect to work that out from the code in src/background/rules.ts, since the pattern syntax appears nowhere in the written documentation.
Frequently asked questions
What is the Global Speed extension for Chrome used for?
It sets a default speed for video and audio so the choice applies to all media on a page, and it also offers per site URL rules, media hotkeys, and filters for brightness, contrast, volume and pitch.
How do I use the Global Speed extension?
The README has no usage section. It links the Edge, Firefox and Chrome add-on listings and describes three feature groups: a speed applied to all video and audio, URL rules for specific sites, and media hotkeys with multiple trigger modes including a context menu and global shortcuts.
How much can Global Speed boost the volume?
Up to 600 percent, alongside brightness, contrast and a pitch shift, with hotkeys assignable to toggle filters on the fly. The audio effects group is marked Chromium only.
Which browsers and versions does Global Speed target?
The install links cover Edge, Firefox and Chrome, and the manifest sets a browserslist of chrome >= 116 and firefox >= 128. Firefox also has separate build scripts, a buildFf output directory and its own static asset tree.
How do I build Global Speed from source for a Chromium browser?
Run npm install, then npm run dev to build an unpacked version. On Chrome, open the extensions page, enable dev mode and load unpacked. On Edge, open the extensions page and load unpacked. The lint script runs tsc --noEmit and the prod script zips the result to global-speed-chromium.zip.
Can Global Speed speed up YouTube and Netflix videos automatically?
The compatibility list names YouTube, Netflix, Spotify and podcast sites, and URL rules can auto apply a favorite speed on specific sites. The pattern syntax for those rules is not given, and the rule logic sits in src/background/rules.ts.
Official sources
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.
[](https://hysenlabs.com/projects/polywock-globalspeed)