Expand description
Speech → text (whisper.cpp), the subtitle generator on top of it, and the double-take detector.
Nothing here ships in the exe: no model, no ML crate. The model is downloaded once into
Settings::cache_dir()\models (visible progress, size named before the click) and the inference is a
child process, exactly like ffmpeg (media/ffpipe.rs) and yt-dlp: locate the exe, run it, parse its
stdout, never block the UI. With neither installed the app is untouched — the pane just says what to
install and where it looked.
whisper.cpp prints one line per segment, [00:00:01.000 --> 00:00:02.400] text, so the transcript
streams in while it runs and the progress fraction is the last timestamp over the audio length.
-ml 1 -sow makes those lines one word each — that is where the word timings come from, regrouped
into sentences by group_words.
The subtitle conventions follow the usual auto-subs ones: ~42 characters a line, split on word boundaries, a minimum on-screen time that never eats the next cue.
Structs§
- Group
Opts - How one-word segments are regrouped into sentences — every knob the “Regenerate” pass turns.
- Job
- A running transcription.
segments()grows while it runs;progressdrives the UI and cancels it. - Options
- Segment
- One transcribed span.
wordsis filled only when the run asked for word timings.
Constants§
- HOST 🔒
- MERGE_
GAP 🔒 - Duplicate ranges closer than this are cut as one.
- MIN_
WORDS 🔒 - Fewer words than this and a repeat is just normal speech (“yeah”, “okay”), not a second take.
- MODELS
- Downloadable whisper.cpp models: (name, file, download size in MB).
Functions§
- default_
model - Index into
MODELSofSettings.transcribe_model(by name or file), else base.en. - download 🔒
- download_
model - Download a model into the cache.
curl.exeships with Windows 10 1803+; progress is the size of the.partfile against the published one, because curl’s own meter needs a console. - dup_
ranges - Timeline ranges of every take but the last of each group — what “cut the duplicates” removes. Sorted and merged so two duplicates in a row are one cut.
- duplicate_
takes - Groups of segments that say the same thing again — a flubbed line and its retakes. Each group is in
time order with at least two members and the LAST one is the keeper.
windowis how long a silence may sit between one take and the next. - exe
- A whisper.cpp binary, or None.
main.exeis only accepted from a directory we were pointed at — amain.exepicked up off PATH would be anything at all. - exe_dir
- Where the app looks for a whisper binary it did not find on PATH.
- extract_
wav 🔒 - 16 kHz mono wav of the clip’s range, through the ffmpeg we already ship next to.
- group_
words - One-word segments (
-ml 1 -sow) → sentences, keeping the word timings. A sentence ends perGroupOpts: on punctuation, on a long gap, atmax_chars, or atmax_words. - have_
model - Is the model there and not a truncated download?
- install_
hint - Exactly what to install and where it is expected (shown in the pane when
exe()is None). - model_
path - model_
url - models_
dir %LOCALAPPDATA%\SimpleEditor\cache\models— where downloaded models live.- normalize
- Lower-cased words with the punctuation stripped (“So, THAT one!” → [“so”, “that”, “one”]).
- parse_
line [00:00:01.000 --> 00:00:02.400] Hello there→ (1.0, 2.4, “Hello there”). Anything else (whisper’s banner, timings, blank-audio markers) is None.- retime
- Source seconds → timeline seconds: the clip’s speed is one linear map over its whole range.
- ripple_
time - Where
tends up after those ranges are rippled out — None whentwas inside one of them. Used to drag the cues and the transcript along with the cut. - run 🔒
- settings 🔒
- short_
label - Name for a marker on a duplicate take: the transcript, short enough to read on the timeline.
- similarity
- How alike two token lists are, 0..=1: twice their longest common subsequence over their combined length. Order-aware (unlike a bag overlap) and forgiving of the “um“s a retake adds.
- start
- to_cues
- Segments → subtitle cues: wrapped to
max_charsper line,lineslines to a cue (joined with \n), timed by the word timings when there are any and proportionally to the characters otherwise, each held for at leastmin_durunless the next cue needs the time. Where a sentence continues across the cue split,cont= (prefix, suffix) marks it: the suffix goes on the cut-off cue, the prefix on its continuation (e.g.("…", " —")). ponytail: the marks are added after the wrap, so a marked line can run a few chars pastmax_chars. - wrap_
words 🔒 - Greedy line wrap on word boundaries; a single word longer than
max_charsgets its own line.