✂️ Cutting Subtitles (OreX)
The garbage collector between your LLM and your dub
- subs_with_timestamps (batch)
- clean_text (batch)
Here's a sentence you'll recognize if you've ever piped an LLM into a media workflow: the model translated your subtitles, and the output is a mess. Wrapped in quotes it invented. Brackets it decided to keep or drop at random. \n as literal text. A Python list printed as a string. orex-Cutting-Subtitles exists to eat all of that and hand you two clean, parallel lists - one for your TTS, one for your aligner.
It sits in the middle of the OreX dubbing chain, right after the LLM translates your text_batch from the GigaAM transcription node. The LLM is told to keep the [00:00:28 - 00:02:12] timestamp prefixes, but LLMs are only sort of told things. This node is the part that trusts nothing.
How it works
Under the hood it's a parser, not magic. It handles the three most common ways an LLM mangles its own output: if the text arrived as a Python list literal ("[...]"), it safely evaluates it back to a real list; if the model escaped newlines as literal \n, it un-escapes them; then it runs each line through a single forgiving regex - ^.*?(\[[0-9:\s-]+\])[\s:]*(.*)$ - which ignores any leading garbage up to the first timestamp bracket, captures the timestamp, and grabs everything after as the subtitle text. Trailing quotes and stray brackets the model left on the end get stripped.
The clever part is that lines with no timestamp at all are passed through untouched rather than dropped. So if the LLM quietly emitted a line of commentary without a timestamp, you still see it - you just can't feed it to the aligner.
Inputs and outputs
One input, two outputs. subtitles_text is a multiline STRING with the raw LLM output (the default sample shows the expected format: [00:00:28 - 00:02:12]: Hello everyone). The two outputs are lists, and they're twins:
- subs_with_timestamps (batch) -
[timestamp]: textlines, index-aligned with the input. This is what you wire into the Audio Subtitle Aligner. - clean_text (batch) - just the text, no timestamps, in the same order. This is what you feed your TTS node so it doesn't try to read "00:00:28" aloud.
The alignment between the two is the whole point: the Nth element of one matches the Nth element of the other, so the TTS audio and the timestamps stay in lockstep downstream.
Install
Part of the ComfyUI-GigaAM pack: Manager → search "ComfyUI-GigaAM", or git clone https://github.com/orex2121/ComfyUI-GigaAM into ComfyUI/custom_nodes, then restart. Alone, this node needs nothing extra - it's pure Python stdlib - but the pack as a whole wants pip install gigaam pyannote.audio audiotsm soundfile, so if you're using the full pipeline, install those too.
Where people get burned
This node can only clean what's actually on the line. If your LLM dropped the timestamps entirely, the regex finds nothing to match and lines pass through unchanged - which then breaks the aligner downstream, because it expects [start - end] on every line. The fix is prompt-side: tell the translation model it must preserve the [mm:ss:cc - mm:ss:cc] prefix verbatim on every line, nothing added. The author's workflow keeps this tight by feeding the node a text_batch that already has the timestamps baked into the format the regex expects. Garbage in, cleaned-out-but-garbage out - but at least the garbage is now predictable.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| subtitles_text | STRING | [00:00:28 - 00:02:12]: Hello everyone | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| subs_with_timestamps (batch) | STRING | — |
| clean_text (batch) | STRING | — |