Open Editor
← all case studies

case 04

Dual-Language Subtitles

Our own use case: learning a language from real shows, with training wheels that come off.

// the problem

This one is personal — it exists because the founder is learning Spanish from a real series. The method language learners converge on is watching native media with both subtitle tracks visible: the target language to read along, the native language as a safety net. And the tooling fight starts immediately. Players show one track at a time. The disc’s subtitles turn out to be bitmap images you can’t restyle. The fan-made subtitle file is full of markup that burns in literally. And there’s no way to make the native track less prominent — which is the entire point once you start improving.

// how everyone solves it

The standard advice is to burn both tracks with two chained subtitles filters:

ffmpeg -i episode.mkv \
  -vf "subtitles=episode.mkv:si=2,subtitles=spanish.srt:force_style='...'" \
  -c:a copy out.mp4

Which works — once, roughly. Both tracks fight for the bottom of the frame. Styling one relative to the other means hand-editing ASS style blocks. Delaying the native line so you try the target line first isn’t a flag that exists. And the moment your source subtitles carry markup or the timings need an offset, you’re maintaining a conversion pipeline before the learning even starts.

// the m0saic program

@m0saic-dev/language/dual-sub/v1 treats the two tracks as what they are: a fixed hierarchy. Target language on top, dominant; native beneath, subordinate — and a support dial underneath it. At full support the native line is right there. Dial it down and the native line dims, arrives a beat later (a cut, a fade, or an unblur — your pick), and eventually stops coming. Level presets turn that dial into a course: training wheels to cold turkey, one prop.

The practical mess is handled where it belongs, in the template: it reads embedded MKV tracks or external .srt/.ass files, strips the markup that would burn in literally, applies per-track timing offsets, and classifies subtitle tracks by their cue statistics — so the karaoke-spam track that calls itself the default doesn’t win just for being first.

dual-track burn — target language dominant, native subordinate, support dial engaged

// run it yourself

One command, straight from a terminal. The CLI carries the template, the engine, and the validator — if the layout can’t render correctly, it fails before a single frame is written.

npx m0saic make @m0saic-dev/language/dual-sub/v1 -w 1920 -h 1080 --inputs episode.mkv -o learn.mp4

// read the source

The template behind this study is @m0saic-dev/language/dual-sub/v1 — a typed, unit-tested program, not a script. The template library is headed for open release; the m0saic source lives on GitHub.

This template lives in the @m0saic-dev community library — the founder’s own published templates, separate from the core @m0saic set. Same engine, same discipline, personal itch.