Sub-align
Align .srt / .lrc / .txt subtitles (or generate them) to audio/video with WhisperX forced alignment — so each cue can move independently instead of only applying one global timeline shift.
Why not only a global offset?
Tools like ffsubsync typically find a constant offset (or stretch) between speech activity and subtitle “on” times. That works well for whole-track drift, but leading/trailing silence or local timing errors can still leave lines early or late.
sub-align picks a strategy from the input type, then runs WhisperX phoneme / word-level forced alignment so each line is refined against the audio:
| Input | Strategy |
|---|---|
| Media only | Whisper ASR → word-align → split into timed cues |
.txt script |
ASR only for search windows → forced-align original lines |
.srt / .lrc |
Optional global offset → expand windows by --margin → forced-align |
Limitation: subtitle text must roughly match spoken content. Alignment does not translate or correct wrong words.
More detail: docs/pipeline.md · scenarios & flags: docs/usage.md
Install
Requires Python 3.10+ and ffmpeg on PATH. First run downloads WhisperX alignment models (disk/RAM).
1 | pip install 'sub-align[align]' |
Extras [align], [cpu], and [gpu] all install WhisperX. Install a matching PyTorch build first when you need a specific CPU/CUDA wheel:
1 | # CPU |
Development
1 | uv venv |
Usage
1 | # Timed subtitles: auto global offset + per-cue refine |
Always pass --language (e.g. en, zh) or --detect-language.
See docs/usage.md for when to use --model, --margin, --offset, --fill-gaps, --trim-*, audio-only line limits, and a Whisper model size / VRAM cheat sheet.
Python API
1 | from sub_align import align_file |
How it works (short)
- Load media as 16 kHz mono audio (via WhisperX / ffmpeg); optional
--trim-start/--trim-end. - Resolve language (
--languageor tiny-model detection). - Build search windows by input type (ASR token match for
.txt; offset + margin refine for.srt/.lrc; full ASR for media-only). - Run WhisperX forced alignment; remap word times onto original cues; trim overlaps; optional
--fill-gaps; write.srtor.lrc.
Full diagram and tech notes: docs/pipeline.md.
License
MIT