lektor_ai_comfy — Polish AI Dubbing Tool ========================================= FULL DOCUMENTATION: see docs/ docs/README.md start here — overview and quick start docs/requirements.md hardware, software, dependencies docs/installation.md installing ComfyUI + the TTS engine docs/usage.md every CLI flag, working modes, recipes docs/architecture.md how the pipeline works internally docs/troubleshooting.md diagnosed failure modes and their fixes Installer: ./install_backend.sh (see docs/installation.md) This file remains as a condensed quick reference. Converts SRT subtitles to AI voiceover (lektor style) using ComfyUI + Higgs Audio V3 TTS, then mixes the result with the original video audio into a two-track MKV. All subtitle tracks in the source video are carried over to the output. Requirements ------------ - ComfyUI running at http://127.0.0.1:8189 with TTS-Audio-Suite custom node - Model: higgs-audio-v3-tts-4b (bosonai/higgs-audio-v3) - ffmpeg and ffprobe available on PATH - Voice reference: a WAV file + matching .txt transcript in the voice directory (default: voices/gudowski_short.wav + voices/gudowski_short.txt) Settings -------- Defaults live in settings.ini next to the script: voice, speed, temperature, max_tokens, strip_leading_ms, trailing_fade_ms, orig_volume, tts_volume, output_dir, dictionary, numbers, comfy_url Precedence: command-line flag > settings.ini > built-in default. Use --settings FILE to select a different profile. See docs/usage.md for the full description. Basic Usage ----------- Full run with an external SRT file: python3 lektor_ai_comfy.py input/film.srt input/film.mkv Use subtitles embedded in the video (lists tracks, prompts for a choice): python3 lektor_ai_comfy.py input/film.mkv --embedded-subs Process only a time range (extracts a video fragment automatically): python3 lektor_ai_comfy.py input/film.srt input/film.mkv --start 01:20 --end 05:40 Subtitle Handling ----------------- Both external SRT files and embedded subtitle tracks go through the same cleaning: - HTML tags stripped: , , , , etc. - ASS override codes stripped: {\an8}, {\pos(x,y)}, {\c&H…&}, etc. - ALL-CAPS blocks converted to Title Case (keeps proper nouns readable) - Sentence fragments starting with a lowercase letter are capitalised - Missing terminal punctuation added (… or . depending on context) - Dictionary replacements applied (see below) - Dialogue lines (prefixed with -) are split into separate clips with proportional timing - Numbers spelled out as Polish words, in the right case (see below) With --embedded-subs the extracted subtitles are saved to the job folder as embedded_sub.srt so you can inspect them before or after the run. The final MKV preserves all subtitle tracks from the source video — text-based (SRT, ASS, SSA, WebVTT) and image-based (PGS Blu-ray, VOBSUB) alike — using stream copy with no conversion. Replacement Dictionary ---------------------- dictionary.txt next to the script rewrites words and phrases before they reach the TTS engine — abbreviations, units, symbols, names the model mispronounces. One rule per line: km/h = kilometrów na godzinę np. = na przykład /(\d+)\s*%/ = \1 procent Matching is case-sensitive and whole-word only, so "np." leaves "znp." alone and "Joshua" leaves "joshua" alone. The replacement is inserted exactly as written. The first letter of each block is capitalised before these rules run, so add a capitalised variant for words that can start a subtitle. Longer patterns win over shorter ones regardless of the order they are written in, and replacement text is never rescanned, so rules cannot feed each other. A pattern wrapped in slashes is a regular expression, with \1 \2 … referring to its groups. Lines starting with # or ; are comments. The result is visible in the job folder's tts_input.srt — check there if a rule is not doing what you expect. --regen and --rebuild work from that file, so they do not re-apply the dictionary; edit tts_input.srt directly, or rerun. Use another list with --dictionary FILE (a relative name is looked for in the current directory first, then next to the script) or turn it off with --dictionary "". A missing file is not an error. A second list can be merged in with --dictionary-extra FILE. The GUI writes one per queue — the "Queue dictionary" button — into the first queued video's job folder, for rules that belong to one batch rather than to Polish in general. Number Normalization -------------------- The TTS misreads long digit strings and sometimes turns them into non-words, so after the dictionary every block containing a number is rewritten with the numbers spelled out in Polish — in the correct grammatical case, which is why this is a small neural model and not a lookup table: Wygrał 1247 złotych. -> Wygrał tysiąc dwieście czterdzieści siedem złotych. Mówimy o 25 psach. -> Mówimy o dwudziestu pięciu psach. Mam 3 koty. -> Mam 3 koty. (single digits are read fine) It runs in its own environment (transformers>=5, which must not be installed next to ComfyUI's pinned versions). One-time install: normalizer/setup.sh # venv + dependencies HF_TOKEN=hf_... normalizer/setup.sh --model # gated weights, accept terms first Terms: https://huggingface.co/Folx/qwen3-0.6b-pl-text-normalization Everything after that runs offline. See normalizer/README.md. Turn it off with numbers = no under [normalize] in settings.ini, or with --no-normalize-numbers for one run. If the environment or the model is missing the run continues with the digits untouched — it is never fatal. Output Files ------------ Everything belonging to one video is kept together in a job folder named after the video file. Only the finished video is written to the top level. output/ clips/