Model or dataset
rockbenben/subtitle-translator avatar
rockbenben/subtitle-translator

Subtitle Translator: keeping timecodes out of the model's reach

Translate a whole season of subtitles in one pass — .srt/.ass/.vtt/.lrc, 120+ languages, 27 LLM providers, timing untouched | 整季字幕一次译完,时轴不动,支持 120+ 语言

1,112 stars147 forksTypeScriptMIT

At a glance

What is it?
A browser-based batch translator for .srt, .ass, .vtt and .lrc files that parses timing locally and sends only dialogue to 8 machine-translation APIs or 27 LLM providers. The design bet is that the model should never see a timestamp.
Who is it for?
Adopt it if you already hold an API key for DeepL, DeepSeek, Gemini or a self-hosted Ollama endpoint and you need a whole season translated without touching cue timing. Skip it if your subtitles need human review of register, honourifics or song lyrics, because nothing in the pipeline checks translation quality, only structural integrity.
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 4 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 September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem is that general translators treat a subtitle file as prose

Paste an .srt into a chat interface and the model sees text where cue numbers, timecodes and dialogue are interleaved. It rewrites what it sees. The README states the failure plainly: "the model rewrites your timecodes." The second problem is volume. Subtitle work arrives as seasons, not files, and a one-file-at-a-time workflow does not scale to twenty-two episodes. Subtitle Translator targets both. It is built for people who already have subtitle files and already have an API key, and who want the translation step automated without a round trip through a desktop editor. Anime and drama fansub groups, media localisation freelancers, and developers wiring translation into a pipeline are the obvious audience. Someone translating a single short clip by hand is not.

Structure is parsed locally, so the timeline is physically out of reach

The mechanism is a split. Before anything is sent anywhere, the tool extracts timecodes, cue numbers, ASS headers and WebVTT cue IDs. What leaves the browser is dialogue text only. The README calls this "structural separation" and claims the timeline "physically cannot be touched" because the model never receives it. That is a stronger guarantee than prompt instructions, which a model can ignore. On the return path the translated strings are reinserted into the original skeleton, which is why bilingual output and format conversion can happen without realigning anything. The same parser handles the extraction feature: strip cues and timing, export clean text, auto-copied to clipboard, for summarisation or repurposing. WebVTT NOTE, STYLE and REGION blocks are skipped rather than translated as dialogue, which matters because those blocks often contain CSS and comments that a model would mangle into visible text.

Chunking, concurrency and the context window trade-off

Translation runs in batches with two knobs exposed for LLM modes. Concurrent Lines caps how many lines are translated in parallel and defaults to 20; the README warns that raising it triggers rate limits. Context Lines controls how many surrounding lines accompany each batch and defaults to 50, with the stated trade-off being coherence against token consumption. Higher context means the model sees more of the conversation and can keep character voice consistent; it also means every request carries more input tokens. The README adds a blunt caveat: models under 70B parameters may produce misaligned output, and it recommends mainstream hosted models for context mode. That is an admission that the structural guarantee protects the timeline but not the line-to-line mapping. If a small model returns the wrong number of segments, the reinsertion step has to cope, and the documentation does not describe what happens then. Treat that as the sharpest edge in the design.

Getting it running: the browser path and the CLI path

The hosted instance is at tools.newzone.top/en/subtitle-translator, and the README describes the whole tool as client-side, with subtitle content and API keys staying in the browser. GTX and Edge need no configuration and act as each other's fallback, so a first run requires nothing but a file. For anything else you open API Settings and enter a key. Providers blocked by CORS can be routed through a relay, and the README notes that the built-in relay works out of the box while "API Settings → Relay address" points every relayed provider at your own deployment of the relay Worker. The CLI is the other entry point: the README states that `yarn cli` runs the same engine, parsers and cache from a terminal. It does not document the CLI's flags or configuration file in the excerpt available here, so check the repository before scripting against it. Caching uses IndexedDB with no browser-storage size limit, and refreshing the page does not lose translated files.

Batch output, multi-language runs and what the summary actually tells you

Dropping a season at once is the headline behaviour. Each file translates and downloads independently under its original filename, and a run ends with an aggregated success and failure summary in the form "Exported (3/5)". That summary is the only quality signal the tool gives you. It reports that files completed, not that the translations are good. Multi-language output goes further: a single pass can produce several target languages, each written as its own file with the language code appended, so movie.zh.srt and movie.fr.srt come out of one run. Bilingual output inserts the translation above or below the original, and for SRT or VTT sources you can export ASS with separate styles for original and translation, described in the README as Default 70pt white plus Secondary 55pt cyan. Those style values are editable afterwards in any subtitle editor, which is the practical escape hatch when the defaults do not match your player setup.

Where the approach stops being the right tool

The structural guarantee is narrow. It protects timing and cue numbering; it says nothing about whether the dialogue reads well. Idiom, register, honourifics and songs are exactly where machine translation fails, and the tool has no review step. The README's own warning about sub-70B models producing misaligned output is the second limit: context mode assumes a capable model, so budget for a hosted API rather than a small local one. The third is CORS. Providers walled off from browsers need a relay, and the README points at a relay Worker you deploy yourself, which is infrastructure the tool does not remove. If you are offline, behind a restrictive network, or unwilling to send dialogue to a third party at all, the client-side claim does not help you, because the requests still leave your machine for whichever endpoint you configured. The privacy property is about where keys and files are stored, not about whether content is transmitted.

How it differs from a subtitle editor with a translation plugin

Subtitle Edit and similar desktop editors treat translation as one operation inside a larger editing workflow. They open a file, show you a timeline, and let you translate selected cues through a configured engine. Subtitle Translator inverts the priority. There is no timeline editing surface in the material here; the file goes in, the file comes out, and the batch is the unit of work rather than the cue. That makes it faster for volume and worse for judgement. If your job is to fix a mistranslated line at 00:14:22, an editor is the correct instrument. If your job is to produce a first-pass translation of twelve episodes into two languages before a human revisits them, the batch model wins. The CLI narrows the gap slightly by making the engine scriptable, but the README presents it as the same engine, not as an editing environment.

Licence, maintenance and what the release cadence implies

The project is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is the standard permissive arrangement and it imposes no copyleft obligation on your own code. It also means the maintainers offer no warranty, and nothing in the licence obliges them to fix a broken provider. Maintenance signals are visible in the release list: v3.1.0, v3.1.1 and v3.2.0 landed within roughly three weeks of each other in August and September 2026, with the last push on the same day as v3.2.0. Frequent patch releases are consistent with a project tracking provider API changes, which is the real ongoing cost here. The 27 LLM providers and 8 machine-translation APIs are integrations that break when vendors change endpoints or authentication. Adopting this means accepting that the integration surface is the maintenance burden, and that a provider you depend on can stop working between releases. The repository is not archived, and the README is bilingual, which suggests an active user base in both English and Chinese. None of this is a quality claim; it is a description of what the release history shows.

Editorial conclusion

Adopt it if you already hold an API key for DeepL, DeepSeek, Gemini or a self-hosted Ollama endpoint and you need a whole season translated without touching cue timing. Skip it if your subtitles need human review of register, honourifics or song lyrics, because nothing in the pipeline checks translation quality, only structural integrity. Before committing, verify two things: that your target provider is reachable from a browser without CORS trouble, and that the Context Lines default of 50 does not push you past your provider's per-request token limit.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. rockbenben/subtitle-translator on GitHub
Community notes

Community notes