case 04
Our own use case: learning a language from real shows, with training wheels that come off.
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.
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.
@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.
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.
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.