text_clip_Generate
An LTX-2 prompt writer that costs you zero extra VRAM
- clip
- image1
- image2
- image3
- image4
- image5
- video
- audio
- generated_text
What it's for
LTX punishes short prompts. Everyone who runs it learns this the same way: you type a decent one-liner, you get a static shot or chaos, and you end up writing a paragraph about lighting and sound. The community's answer has been to bolt an LLM into the graph and have it write the prompt for you - which means downloading a second model, running Ollama alongside ComfyUI, and budgeting VRAM for two networks that both want the card.
text_clip_Generate does the same job with no second model, because it uses a model you've already loaded: the CLIP. If that CLIP is LTX-2's Gemma text encoder, it can generate text, not just encode it, and this node is a prompt-writing front end for exactly that.
How it works
Underneath, this wraps ComfyUI core's Generate Text node (comfy_extras/nodes_textgen.py), whose mechanism is clip.generate(...) - the text encoder running autoregressively as a small LLM. The pack's contribution is the chat template and the input plumbing.
You feed it a rough idea in prompt. The node assembles a chat prompt by hand - a system turn with LTX's own instruction text (expand the idea into a video prompt with visuals and audio, keep the user's specifics, invent lighting and texture where vague, write speech in quoted dialogue) plus a user turn saying User Raw Input Prompt: … - then hands it to core with the default template off, length capped at 4096, thinking off, and sampling off. Sampling off matters: decoding is deterministic and greedy, so there's no temperature or seed to twiddle.
It also knows two template generations. If the loaded tokenizer reports a gemma4 name it uses the newer <|turn>system … <|turn>model format and matching system prompt; otherwise the <start_of_turn> variant. And if generation returns empty, it silently gives you back your original prompt - a failure degrades to "no enhancement" rather than an empty conditioning string.
The inputs and outputs that matter
clip- required. This is the writer. It has to be a text encoder that supports generation; on a plain SDXL CLIP or a T5 you're asking for something the tokenizer can't do.prompt- multiline, required. Your raw idea, not a polished prompt.system_prompt- optional STRING, and it's a forced input, so it must be wired from a string node rather than typed. It replaces LTX's built-in instruction entirely. Use it to constrain the writer (dialogue-only, camera-move-free, your style bible) or to write a system prompt of your own.image1…image5- optional IMAGE inputs, up to five, so the writer can see reference stills. Each is resized to the first image's dimensions and only the first frame of a batch is used.video- optional IMAGE batch; the tooltip is literal: video frames as an image batch. Core subsamples them internally (assumes 24 fps, steps down to about 1 fps) before they reach the encoder.audio- optional AUDIO.- Output:
generated_text(STRING). Wire it into your LTX text encode or aCLIPTextEncode.
Important distinction, because it's easy to get backwards: the images, video and audio here condition the writer, not the video model. They're context for the description ("write a prompt about this"), and they don't get passed downstream as conditioning by this node.
Install
It's part of ComfyUI-Apt_Preset:
cd ComfyUI/custom_nodes
git clone https://github.com/cardenluo/ComfyUI-Apt_Preset
cd ComfyUI-Apt_Preset
python -m pip install -r requirements.txt # your ComfyUI's python
Restart, or install via ComfyUI Manager by pack title. No model downloads - it reuses whatever CLIP you load for LTX.
Common issues
Update ComfyUI first. This node imports comfy_extras.nodes_textgen at module load, and core's text-generation support (TextGenerate, clip.generate) is recent. On an older build that import fails, and because Apt_Preset's __init__.py imports every module unguarded, you don't lose one node - you lose the whole pack to a single "IMPORT FAILED" line. Users report that failure for this pack often enough that it's worth checking the startup log before anything else.
Nothing is generated, or it errors on the generate call. Your clip isn't a generative text encoder. The node is written for the Gemma-family encoder that ships with LTX-2 (and LTX-2.4's gemma4 variant). Loaded with anything else, there's no generate on the tokenizer to call.
It "doesn't help". Sometimes it doesn't, honestly. Enhancement is good at the parts people skip - soundscape, materials, lighting, chronological flow - and it writes prose. Prose is what you want for scene and audio detail and not what you want for camera control; short bossy instructions beat a paragraph when you're telling the model to dolly in, and plenty of LTX users deliberately bypass Gemma-generated prose for exactly that reason. Treat it as a writer for the descriptive layer, keep your camera moves explicit in the system or the text, and don't be surprised if you edit what it hands back.
It feels slow and heavy for "free". Free means no extra model - the Gemma encoder is large and it's yours already, but running it autoregressively for up to 4096 tokens is real work on a real card. And any LLM wrapping a prompt can leak preamble or role delimiters into the output; core handles the thinking/reasoning split and this node falls back to your raw prompt on an empty result, but read the returned text once before trusting it blind.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| clip | CLIP | — | |
| prompt | STRING | — | |
| image1opt | IMAGE | — | |
| image2opt | IMAGE | — | |
| image3opt | IMAGE | — | |
| image4opt | IMAGE | — | |
| image5opt | IMAGE | — | |
| videoopt | IMAGE | Video frames as image batch. | |
| audioopt | AUDIO | — | |
| system_promptopt | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| generated_text | STRING | — |