MiniMax-H3 Prompt Rewriter
The reference-quality MiniMax-H3 prompt rewriter, run fully local
- duration
- aspect_ratio
- options
- rewritten_prompt
- integrated_multimodal_description
- overall_soundscape
- non_diegetic_music
MiniMax-H3 is picky about its prompts. It wants a structured, shot-by-shot audio-video description - [Shot 1] markers, an overall_soundscape line, a non_diegetic_music line - because that's the shape it was trained on. Typing that by hand for every clip is misery. This node is the fix: you type "A red fox walks through a snowy forest at dawn," it returns the full structured description H3 expects, and it never touches the network after the weights are down. The "Rewriter" in the name means a short prompt goes in and a production-ready H3 prompt comes out - not a call to some hosted API.
It's the flagship of the pytraveler/MiniMax-H3-Prompt-Rewriter-ComfyUI pack (same person who writes the "ComfyUI update X.XX" posts on r/comfyui, by the way). What makes it the reference is what's inside: LightX2V's T2VA prompt-rewriter LoRA, trained on Qwen3.6-27B until H3-shaped output came out of it with just a seven-line system prompt. The format isn't instructions the model is trying to follow - it's in the weights.
How it works
Short version: pick a Qwen3.6-27B base, the node attaches the LoRA, generates, and hands you four text outputs. The base can be the official bf16 checkpoint, a bitsandbytes nf4 repack, or a GGUF. The model dropdown (the "model list") holds every option plus anything already on disk, and whatever's missing is downloaded on first use with a progress bar on the node itself.
One thing worth knowing before you go down this road: the MiniMax-H3 text encoder can't be reused for this. It's a different model (Qwen3-VL-32B, different vocab, truncated to 50 of 64 layers, no lm_head) that only produces hidden states for the DiT. This node runs a full 27B language model alongside H3. That's the cost of the quality, and there's no shortcut.
The inputs that matter
prompt- the short idea. Any language the base reads; the rewrite comes back in English, which is what H3 wants.model- your base-model choice.nf4on the official checkpoint is ~16 GB VRAM; a GGUFQ4_K_Mis ~19 GB and needs nothing installed (more below). Start there if you're tight on card.resolution/duration- keep these equal to what you feed MiniMax-H3, or the shot pacing won't match. Duration is capped at 4–15 s, the range the LoRA was trained on.greedy- on by default. It's deterministic and it's what makes the node cacheable. Leave it on.keep_model_loaded- off by default, on purpose: the moment the rewrite finishes you need that VRAM back for H3 video generation.
Outputs
Four strings, all wire into a text viewer or straight into H3's text input:
rewritten_prompt- the full thing, ready to paste.integrated_multimodal_description- just the shot-by-shot visual section.overall_soundscape- the diegetic audio section.non_diegetic_music- the score section.
Install
Clone into custom_nodes (or grab it from ComfyUI Manager - search "MiniMax-H3") and install requirements into ComfyUI's Python environment:
cd ComfyUI/custom_nodes
git clone https://github.com/pytraveler/MiniMax-H3-Prompt-Rewriter-ComfyUI
pip install -r MiniMax-H3-Prompt-Rewriter-ComfyUI/requirements.txt
The pip deps (transformers, peft, accelerate, bitsandbytes) are for the Transformers route. The GGUF route needs none of them: it uses llama-cpp-python if it's already in your environment, and otherwise fetches the official llama.cpp binaries (~34 MB) and runs them as a subprocess. That's the smallest path - about 10–16 GB total download against 52 GB for the official checkpoint.
Where people get burned
keep_model_loadedstays off. A 27B holds onto 16 GB the moment you turn it on. Leave it until you're iterating on prompts back-to-back.- The rewrite invents details. It's a trained distribution, not a transcript. Review it when identity, dialogue, timing or composition must be exact.
- "It produced a good rewrite but I'm on a 9B." If a Qwen3.5-9B GGUF is in your model list, it can't take this LoRA (wrong block count - the node flags it
(wrong size for the adapter)), so any plausible output is the plain model running the system prompt without the adapter. Not a bug, but it's not what you're paying for. - Quantized repacks are third-party. The node verifies the architecture from
config.jsonbefore downloading, which proves the shape - not the uploader's trustworthiness.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | The short prompt to expand into an H3 audio-video description. | |
| model | COMBO | Base model. Entries prefixed 'on disk:' are already downloaded; the rest are fetched on first use. GGUF entries need no extra install: without llama-cpp-python the node fetches the official llama.cpp binaries. Use the button to edit the list. | |
| resolution | COMBO | 16:9 | Target aspect ratio the rewrite is composed for. It has no socket on purpose: a ratio arriving from the graph belongs on 'aspect_ratio', which reads the spellings other nodes use and overrides this while it is connected. |
| duration | FLOAT,INT | 100.1–600 | Target clip length in seconds; drives shot count and pacing. Right-click the node for 'duration': the default value back, or a new upper end for the widget. It offers 30 seconds until you change it and the server takes up to 600, because a widget's range is fixed when the node is declared and one number cannot suit every graph -- MiniMax's own guide is written around clips of a few seconds, while the stretched pipelines the community has built run well past that. What you set is remembered with the workflow. |
| quantization | COMBO | nf4 | How to load an unquantized checkpoint: nf4 needs about 16 GB of VRAM, int8 about 28 GB, bfloat16 about 54 GB. Ignored for GGUF models and for checkpoints that are already quantized. |
| greedy | BOOLEAN | true | Deterministic decoding. Turn off to sample; see the options node. |
| seed | INT | 420–4294967295 | — |
| keep_model_loaded | BOOLEAN | false | Keep the 27B model in VRAM after the rewrite. Leave off when the same GPU has to run MiniMax-H3 video generation afterwards — or give the rewriter a card of its own with 'device' in the options node, and then there is nothing to compete with. |
| aspect_ratioopt | STRING,COMBO | Optional, and it overrides the picker while something is connected. Reads a ratio ('16:9'), a frame size ('3840x1080') or a bare number ('1.78'), and a label around the pair is fine -- '3:4 (Portrait Standard)' reads as 3:4. A size within 2% of a listed ratio is called by its name, so 1376x768 arrives as 16:9 rather than as 43:24. | |
| optionsopt | H3_REWRITER_OPTIONS | — | |
| bypassopt | BOOLEAN | false | Hand 'prompt' straight to the output and run no model at all: nothing is downloaded, nothing is loaded, no VRAM is touched. This is what ComfyUI's own bypass (Ctrl+B) cannot do here - it only forwards a connected link, and every input this node writes from is a widget, so bypassing the node the usual way leaves the nodes downstream with nothing. The section outputs come back empty. |
| repeat_lastopt | BOOLEAN | false | Hand back a prompt this node already has instead of running the model again. By default that is the node's own last answer: with nothing kept yet it runs once, keeps what it wrote and says so, and from then on returns that same text for as long as the switch is on, whatever else you change. Pick something in the library window and this switch hands that saved prompt on instead -- the window chooses which prompt, this switch is what makes it happen. Off is always a real run. The session store is in memory only, one answer per node: it is not saved with the workflow and does not survive a restart, while a saved prompt does both. 'bypass' still wins over all of it. |
| library_pickopt | STRING | Which saved prompt this node hands on instead of writing one, as JSON written by the library window. It is a widget so the choice is saved with the workflow and reaches an API run: a pick the graph does not carry is a graph that reproduces something else. It applies only while 'repeat_last' is on. That switch is what hands a kept prompt on at all; this says which one, and empty means the node's own last answer. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| rewritten_prompt | STRING | — |
| integrated_multimodal_description | STRING | — |
| overall_soundscape | STRING | — |
| non_diegetic_music | STRING | — |