← All projects

Contribute

Presto

Playback speed control for every video on the web, not just YouTube.

  • JavaScript
  • WebExtensions
  • Manifest V3

No tagged issues yet. Open one!

Presto is one dependency-free content script with no build step and no package.json, so you can understand the whole extension in an afternoon. Issues and pull requests are welcome.

The three hard problems

Most of Presto's code exists because naive speed controllers break in three ways:

  • Players reset the speed. Adaptive players reassign playbackRate on quality switches, ads and source changes, so every media element gets a guarded ratechange listener that puts your speed back.
  • Every frame is isolated. Each iframe runs its own copy of the script. Speed changes are relayed to the top frame, which owns the state and broadcasts it down the frame tree.
  • Sites bind the same keys. The key listener runs on window in the capture phase so it wins against player shortcuts, and it stays out of the way while you type in a field.

The control is drawn over each video instead of inside the player's markup, so it survives sites that rebuild their controls.

Set up

git clone https://github.com/SUD747/presto && cd presto
node test/unit.js
python3 -m http.server -d test 8000   # test page at http://localhost:8000/page.html

Then run the extension in a throwaway browser profile that reloads whenever a file changes:

npx web-ext run                                     # Firefox
npx web-ext run -t chromium                         # Chrome
npx web-ext run -u http://localhost:8000/page.html  # and open the test page

If you load it by hand instead, refreshing the page won't pick up edits to src/content.js. Reload the extension first.

Where things live

  • src/content.js: everything that happens on the page. Keep it a single file with no dependencies.
  • src/popup.*: the toolbar panel. src/steps.js holds the step sizes both of them share.
  • test/unit.js: speed and step arithmetic, extracted from content.js itself so the test can't drift from the code.
  • test/page.html: a manual harness with a plain video, one in a shadow root, one in an iframe, a text field, and a video added after load.

Before you open a PR

  • Add a case to test/unit.js if the change can be tested without a browser, or to test/page.html if it can't.
  • Keep Mozilla's linter clean: npx web-ext lint --self-hosted should report zero errors and zero warnings.
  • Say which real sites you tested on. Ad breaks and quality switches only show up there.

Found a security issue? Report it privately as described in SECURITY.md, not in a public issue.

Want every detail? Read the full CONTRIBUTING.md on GitHub

Not a coder, or short on time? You can support Presto another way: Buy me a coffee