Nodes/ComfyUI-MMS-Aligner/MMS Audio-Text Aligner (SRT)
ComfyUI Node

MMS Audio-Text Aligner (SRT)

Karaoke-grade subtitles from a transcript you already have

By hnvcam·Created 4 months ago·Updated 4 months ago· 0
MMS Audio-Text Aligner (SRT)
  • audio
  • srt
  • output_path
text
languageauto
custom_language_code
romanizefalse
segmentation_modemax_chars+punctuation+newlines
max_chars_per_line42
remove_punctuationfalse
output_namesubtitles
gap_ms300
split_count1
precisionbf16
chunk_with_whisperfalse
whisper_model_sizebase
chunk_max_seconds360

The fastest way to turn "I have the transcript" into "I have the timestamps"

Most subtitle workflows in ComfyUI go one direction: Whisper hears audio, guesses the text, and timestamps its own guess. This node goes the other way. You already have the transcript - a script, translated lyrics, captions that drifted, a dubbed line - and you want to know exactly when each word is spoken. That's forced alignment, and this is the rare node that does it in the graph and hands you a ready-to-use .srt.

It's the difference between someone summarizing your audio and someone placing a ruler on it. If your text and audio say the same thing, you get word-level start/end times, and from those you build subtitles. Perfect for karaoke-style captions, translated subs, or re-timing a Whisper transcript that's close but off by half a second.

How it works

Under the hood it's Meta's facebook/mms-1b-fl102, a 1B-parameter speech model that covers 102 languages (trained on the cleaner FLEURS dataset). Each language gets its own adapter weights and native tokenizer - no romanization needed for most scripts.

The pipeline: your audio is resampled to 16 kHz mono in memory, the transcript's language is detected with lingua (when language=auto), the model runs one forward pass to get CTC emissions, and torchaudio.functional.forced_align does the actual alignment math. Token spans get merged into word boundaries, then grouped into SRT cues. All in RAM - no temp WAV files dumped on your disk.

The big catch is upfront, not in the pipeline: the ~3.2 GB model downloads to ComfyUI/models/mms/facebook__mms-1b-fl102/ on your first run, not at install. Plan for a slow first execution; every run after uses the cache.

The inputs that matter

The node has a lot of knobs, but a beginner really sets these:

  • audio - from any node that outputs ComfyUI's AUDIO type, normally LoadAudio.
  • text - the transcript, multiline. Punctuation and newlines here are usable as segmentation cues.
  • language - auto detects from the text. If detection fails, pick your language from the dropdown or enter an ISO 639-3 code via custom.
  • segmentation_mode - single_word gives one word per cue (karaoke), max_chars+punctuation+newlines is the sensible default for reading subs.
  • gap_ms - bridges sub-300 ms silences between cues so single-word subtitles don't flicker. Set 0 to disable.
  • output_name - base filename, no extension; .srt is appended automatically.

Everything else is optional tuning: max_chars_per_line, remove_punctuation (keeps apostrophes and hyphens, so "don't" survives), split_count to split into name_1.srt, name_2.srt…, romanize as a fallback, and precision (bf16 default - fp8 is experimental and wants PyTorch 2.1+).

Two outputs: srt (the full subtitle text, always populated, wire it to a Preview Text node to check without writing a file) and output_path (newline-separated list of files written to ComfyUI's output folder).

Installing it

ComfyUI Manager: search "MMS-Aligner". Or manually:

cd ComfyUI/custom_nodes
git clone https://github.com/hnvcam/ComfyUI-MMS-Aligner
cd ComfyUI-MMS-Aligner
pip install -r requirements.txt

Then restart and the node appears under audio/alignment as "MMS Audio-Text Aligner (SRT)". torch and torchaudio come from ComfyUI; transformers, huggingface_hub, uroman, and lingua-language-detector are pure Python - no compiler, no MSVC, which is exactly what the author promises. One genuine gotcha: the README's own install snippet still says idealweek/ComfyUI-MMS-Aligner (an earlier repo name - the live remote is hnvcam). If you copy-paste the stale URL, you'll be chasing a repo that moved. Clone the hnvcam one.

Also note faster-whisper in requirements.txt is commented as optional - you only need it for chunk_with_whisper=True, which splits long audio (roughly 15–20+ minutes on consumer GPUs) after MMS OOMs on it.

Troubleshooting

  • "Could not auto-detect language" - your text is too short or mixed. Just set language explicitly.
  • "Transcript produced no alignable tokens" - the text has characters outside the language's tokenizer vocab. Try romanize=True, or double-check your ISO 639-3 code.
  • Slow first run - it's the 3.2 GB download. Not a bug; it caches.
  • Your language isn't in FL102's 102 languages - the README is blunt that this node won't work for you. Check before you sink a download into it.
  • Out of memory on long clips - drop precision to fp16, or turn on chunk_with_whisper so a rough Whisper pass finds safe split points and each chunk aligns independently.

If you've got a clean transcript and you're tired of Whisper's timestamps drifting off the audio, this is the node you're actually looking for.

Categoryaudio/alignment

Inputs (15)

NameTypeDefaultDescription
audioAUDIOAudio to align. Connect any node that outputs the ComfyUI AUDIO type (e.g. LoadAudio). Will be resampled to 16 kHz mono in memory.
textSTRINGTranscript to align with the audio. May contain punctuation and newlines, both of which can be used as segmentation cues for the SRT output.
languageCOMBOautoLanguage of the transcript. `auto` detects from the text. Pick `custom` to enter any ISO 639-3 code in `custom_language_code`. The FL102 model supports 102 languages — the chosen language loads its specific adapter weights and tokenizer.
custom_language_codeSTRINGISO 639-3 code (e.g. `vie`, `eng`, `cmn`). Used only when `language` is set to `custom`.
romanizeBOOLEANfalseRomanize the transcript before alignment using uroman. Generally NOT needed — the FL102 tokenizer is trained on each language's native script. Useful as a fallback if you see 'no alignable tokens' errors with text that contains unusual characters.
segmentation_modeCOMBOmax_chars+punctuation+newlinesHow to split words into SRT subtitle lines: - single_word: one word per cue (karaoke-style) - max_chars: pack greedily up to `max_chars_per_line` - punctuation: break at . ! ? , ; : - newlines: break at line breaks in the input text - combinations apply all selected rules
max_chars_per_lineINT420–1000Maximum characters per SRT line. 0 disables the limit (relevant only when `segmentation_mode` includes `max_chars`).
remove_punctuationBOOLEANfalseStrip punctuation (. , ! ? ; : " ( ) [ ] { } — – … « » “ ” ‘ ’) from the SRT output text. Apostrophes and hyphens are kept (so "don't" and "well-known" remain intact). Punctuation still drives segmentation when `segmentation_mode` includes it; only the displayed text is cleaned.
output_nameSTRINGsubtitlesBase file name (no extension) written to ComfyUI's output directory. The `.srt` extension is added automatically. When `split_count` > 1, files are named `<output_name>_<index>.srt`.
gap_msINT3000–5000Bridge small gaps between consecutive cues. If the gap between two cues is smaller than this many milliseconds, the previous cue's end is snapped to the next cue's start (prevents subtitle flicker during fluent speech, especially in `single_word` mode). Larger gaps are preserved as natural pauses. Set to 0 to disable.
split_countINT11–5Number of .srt files to split the output across. 1 (default) writes a single file. Higher values divide cues into near-equal chunks named `<output_name>_1.srt`, `<output_name>_2.srt`, ...
precisionCOMBObf16Compute precision for the MMS model: - bf16 (default): half the VRAM of fp32, wide dynamic range, accurate on Ampere+ GPUs - fp16: half the VRAM of fp32, may underflow on very long audio - fp8: experimental — quantizes Linear weights to float8_e4m3fn, requires PyTorch 2.1+ - fp32: full precision, highest VRAM usage
chunk_with_whisperBOOLEANfalseSplit long audio into smaller chunks using faster-whisper word-level timestamps to find safe split points. Required if MMS OOMs even at fp16/bf16 (typically audio > 15-20 min on consumer GPUs). Adds a Whisper pass before alignment, then merges chunk SRTs.
whisper_model_sizeCOMBObaseFaster-whisper model size used for chunk-point detection (only when chunk_with_whisper=True). `base` is usually plenty — we only need rough word timings to find anchor points. Larger models give more reliable matches in noisy or tonal-language audio at the cost of VRAM and speed.
chunk_max_secondsINT36060–1800Maximum length per chunk in seconds (only when chunk_with_whisper=True). 360s (6 min) is conservative and fits comfortably on 16 GB GPUs at bf16. Increase if your GPU has more VRAM and you want fewer chunks.

Outputs (2)

NameTypeDescription
srtSTRING
output_pathSTRING