ComfyUI Extension: ComfyUI-ForcedAlignTimings

Authored by veoreg

Created

Updated

0 stars

Run ComfyUI workflows without the setup

No installs, no CUDA version roulette, no GPU sitting idle on your bill. Bring a workflow and run it in the browser.

Word-level forced alignment for the Synthy/iRead custom TTS provider that aligns generated speech against known input text and returns per-word timings.

Looking for a different extension?

Custom Nodes (1)

README

ComfyUI-ForcedAlignTimings 🎯⏱️

Word-level forced alignment for the Synthy/iRead custom TTS provider (boris_tts_*). Aligns generated speech against the known input text and returns per-word timings — the raw material for the X-Voice-Markup word_timestamps array (see SY-A-39.md).

Why forced-align (not ASR)

The text is known — we synthesized the audio from it. So we align audio to that exact text instead of transcribing with Whisper and fuzzy-matching its guesses. This is robust on the SY-A-39 stress cases (repeats test test test, numbers в 2026 году).

Pipeline

CosyVoice (text -> audio)
  -> ForcedAlignTimings (audio + text -> raw word timings)     ← this node (GPU)
    -> n8n Code node (raw timings + ORIGINAL text -> markup)   ← UTF-16 / mapping

The node does not do UTF-16 offsets or normalization mapping — that is pure string logic owned by the n8n Code node (1/tts-poc/map_timings.mjs).

Node: Forced Align Timings

| | | |---|---| | Inputs | audio (AUDIO), text (STRING), device (auto/cuda/cpu) | | Outputs | timings_json (STRING), audio_ms (INT), word_count (INT) |

timings_json:

{
  "sample_rate": 16000,
  "audio_ms": 1234,
  "align_text": "Hello, world!",
  "words": [
    {"value":"Hello","char_start":0,"char_end":5,"time":120,"end":480,"score":0.91},
    {"value":"world","char_start":7,"char_end":12,"time":640,"end":980,"score":0.88}
  ]
}

char_start/char_end are Python codepoint offsets into align_text. The n8n node converts them to UTF-16 offsets against the original request text.

Dependencies

  • torch + torchaudio — already in comfy_v5.15c.
  • uroman (pip install uroman) — multilingual romanization for RU. Falls back to a builtin Cyrillic→Latin table if absent.
  • MMS_FA downloads a ~1 GB wav2vec2 aligner on first use — bake it into the image or mount a cache so the GPU box has no cold-start network dependency.

Smoke test on the 5090 box (BEFORE docker commit)

python nodes.py sample_ru.wav "Привет, мир"
# expect JSON with two words and increasing time values

Docker patch (comfy_v5.15c → next)

Follow the SmartGridCutter procedure in .agent/skills/docker-comfyui/SKILL.md: docker cp this folder into /app/ComfyUI/custom_nodes/, pip install uroman, verify curl .../object_info/ForcedAlignTimings, docker commit, docker save → tar → deploy on Hostkey/RunPod.

Run ComfyUI workflows without the setup

No installs, no CUDA version roulette, no GPU sitting idle on your bill. Bring a workflow and run it in the browser.

Learn more