Profile
Back to NewsBack
GitHub Trending 5 min
Reader Mode
open-subs/opensubs: Subtitle any video without uploading it. Whisper, translation, styling and burn-in — all local, in the browser, on the desktop, or from the command line.

open-subs/opensubs: Subtitle any video without uploading it. Whisper, translation, styling and burn-in — all local, in the browser, on the desktop, or from the command line.

16 hours ago

OpenSubs

The open-source alternative to VEED and Kapwing auto-subtitles — your video never leaves your machine. opensubs.app

Subtitle any video without uploading it anywhere. OpenSubs transcribes the speech, translates it, styles it and burns it into the picture — and the video file never leaves your machine, because there is nowhere for it to go.

opensubs.app runs the whole thing in a browser tab with nothing to install. If you would rather have it installed, or want subtitles over a video already playing in another tab, there are three more ways to run it — see docs/install.md.

ci</a> licence: AGPL-3.0-or-later</a>

Four places, one engine

| | What it adds | Install | |---|---|---| | Web app | Nothing to install, nothing to trust — open the page | opensubs.app | | Browser extension | Live subtitles over whatever is playing in a tab. Chrome, Edge, Firefox | Chrome · Edge · Firefox | | Desktop app | Long files, without a browser in the way. One video at a time. macOS, Windows, Linux | guide | | Command line | Scripting and CI | guide |

Line breaking, reading-speed limits, the style presets and the ASS writer are one Rust crate compiled two ways — to WebAssembly for the browser and to a native binary for everything else — so all four produce the same subtitles from the same input rather than four dialects of nearly-the-same.

What actually happens to your video

Nothing leaves the machine unless you ask it to.

  • The video is read through an object URL and decoded locally. There is
no upload endpoint in this product, so a footage leak is not something to promise against — it is not possible.
  • The speech model is downloaded once (from Hugging Face in the browser,
from Hugging Face into ~/.cache/opensubs-models on the desktop) and cached. Only the model is fetched; the audio stays put.
  • Subtitle text is the only thing that can ever be sent anywhere, and
only if you pick a cloud translator instead of the on-device one.

The full statement is at opensubs.app/privacy.html, and it is written to match what this repository does rather than the other way round.

Layout

crates/            the engine, shared by every front end
  subs-media         probing and container facts
  subs-asr           speech recognition
  subs-subtitle      cue model, SRT/VTT/ASS
  subs-style         the presets and the style template
  subs-pipeline      the burn job, and where ffmpeg is found
  subs-qa            reading-speed and overlap checks
  subs-tier          what is free and what is paid
  subs-translate     the translation providers
  subs-credits       billing, linked by a separate gateway
  subs-wasm          the browser build of the above

apps/ web the site and the web app (Svelte 5 + Vite) extension Chrome, Edge and Firefox (MV3) desktop Tauri 2 mobile iOS, iPadOS and Android (Capacitor) cli the opensubs binary

The clean-up rules that decide which lines are hallucinated music rather than speech live in apps/web/src/lib/cleanup.ts, and the extension imports them rather than copying them. They took two rounds of field reports to get right; a fork of them would be wrong within a month.

Building it

Rust 1.97.1 and Node 22. The toolchain file pins the version and the wasm32-unknown-unknown target, so rustup sorts itself out on first build.

cargo test -p subs-media -p subs-subtitle -p subs-style -p subs-pipeline

cd apps/web && npm ci && npm run build # dist/ cd apps/extension && npm ci && npm run build:all cd apps/desktop && npm install && npx tauri build cargo build --release -p opensubs # the CLI

The desktop app and the CLI shell out to ffmpeg to burn, and need one built with the ass and whisper filters — Homebrew's plain ffmpeg formula has neither. docs/install.md covers it per platform.

apps/web/vendor/openapps/ holds two built packages the accounts and paid-translation UI depends on. They are checked in so a clone builds offline. They are provided in compiled form; their source is not published, and scripts/vendor-openapps.sh regenerates them from it.

Testing

cd apps/web
npm run test:cleanup     # the hallucination rules
npm run test:context     # sentence grouping and re-spreading
npm test                 # 109 checks in a real browser against dist/
npm run test:languages   # six language fixtures, end to end

cd apps/extension npm test # the window-stitching logic npm run test:pipeline -- /path/to/video.mp4 --engine firefox

test:pipeline is the one that matters: it captures audio from a real video element in a real browser, runs the real model, and asserts a real transcript comes back. Fixtures pass in this repository while real files fail, so a green synthetic test is not evidence.

Maintainers

OpenSubs is maintained by the OpenSubs team, who publish this repository from the open-subs account. Report a problem or ask a question in Issues, or write to [email protected].

Licence

AGPL-3.0-or-later. See LICENSE. Everything in this repository is under it except the parts below, which say so in their own manifests.

  • crates/subs-credits and crates/subs-translate are
MIT OR Apache-2.0, at your option. They are linked by a separate gateway binary, and each Cargo.toml says why they opt out.
  • apps/web/vendor/openapps/ holds two prebuilt packages for
accounts and credits, which keep their own licence: MIT OR Apache-2.0 (their package.json).

Both are permissive and combine with the AGPL in the rest of the app.

Chat with me