Subtitle Study Tool

Browser extension · Chromium · plain JavaScript, no build step · MIT

Two languages, on the film's own clock.

Find a subtitle for whatever is playing in the tab, draw it over the video in step with the player, and put the language you are learning beside the one you already know. With study mode on, the words that are rare in film dialogue are underlined and their meanings appear at the side as the film runs.

2subtitles at once, on one clock
30,000words per language, ranked for film dialogue
623tests and checks that need no browser
A night scene with an English and a Turkish subtitle along the bottom; the rare word "ephemeral" is underlined in the English line, and a study box at the top left gives its pronunciation, the Turkish "geçici" and two senses

Syncing a subtitle file to a video usually means estimating the offset between them. In a browser tab there is nothing to estimate: the <video> element reports where it is, so the overlay reads currentTime 20 times a second, and seeking, pausing and buffering stay in step on their own. The offset left is the one baked into a file timed against another release, and the second subtitle measures that against the first.

On the player's clock

Positions come from the page's own video element, 20 times a second. Nudge keys correct a file timed against a different release; ad breaks are shared between both subtitles, offsets are not.

Two subtitles at once

Side by side or stacked, each box dragged and resized on its own. Dragging one card onto the other swaps them, with their offsets and languages.

Rare words, marked

Each word is ranked against a frequency list counted over film subtitles, because a word can be common in print and rare in speech. The threshold is a slider.

Kept with the sentence

One key saves a word with the line it was said in, the same moment in the other subtitle, the film and the timestamp. The deck exports as TSV for Anki, or JSON.

An optional local daemon

A small Python service on 127.0.0.1 that keeps a download cache on disk, signs in to OpenSubtitles for a larger daily allowance, and serves word meanings.

A viewer, a translator, a transcriber

The same study surface for a subtitle file without a video, a batch .srt translator, and Whisper transcription for a film nobody has subtitled.

How a subtitle gets onto the video

Four steps, all in the extension; when the daemon is running, it answers the search and the download instead.

  1. What is playing

    The title, season and episode are read from the page: its title and metadata with the site's branding stripped from either end.

  2. Search

    OpenSubtitles is asked, and each result is scored against what the page said. A result that matches badly scores below the line where it would be attached without asking.

  3. Attach

    The overlay is drawn in the page, in a shadow root so the site's styles cannot reach it, and follows the video's position from then on.

  4. Line up the second

    The gap between two subtitles of the same film is the number that recurs in the differences between their cue times. It is applied alone only when the two look like the same film; otherwise it is offered.

Install

Not in a store: load it unpacked. No build step.

Load the extension

git clone \
  https://github.com/mmdemirbas/subtitle-study-tool

chrome://extensions   (or brave://, edge://)
  Developer mode: on
  Load unpacked: subtitle-study-tool/browser-extension

Then open the extension's options and paste an OpenSubtitles API key: opensubtitles.com, your account, Consumers, new consumer. It is free.

Optional: the daemon

cd subtitle-study-tool/subtitle-daemon
cp config.example.json config.local.json
# put your OpenSubtitles API key in it
./run.sh

Needs uv. uv run pytest runs the tests.

What it looks like

Taken from the extension itself over an original scene and a sample pair written for the repository; node browser-extension/tools/screenshots.mjs takes them again.

What leaves the browser

  • Search and download go to OpenSubtitles, with your API key, or through the daemon on 127.0.0.1 when it is running.
  • Word meanings come from the daemon; without it, from dictionaryapi.dev and MyMemory only after you allow them on the options page. Marking rare words needs no network.
  • The deck stays in the browser until you export it. The extension has no analytics and no account of its own.
  • With a Google API key in the daemon's config, looked-up words and the lines of any subtitle it is asked to make go to Google.