MiniMax-H3 Multi Reference Caption
Caption a whole shot's references in one box, not five chained nodes
- subjects
- pictures
- videos
- audios
- clip
- options
- reference_assets
- captions
The single Reference Caption node is exact, but it grows: five references means five nodes, five wires, and five chances to leave the wrong role on one of them. This is the whole-shot version - every asset you connect, described by one small multimodal model, written out as a finished reference_assets block for the Ref2VA writer. It takes the role out of your hands entirely: the group an asset is plugged into is its label.
That's the guide's vocabulary made structural. Ref2VA defines exactly four reference labels and forbids inventing more, so four input groups cover the format completely. Describing an image as audio stops being possible, rather than merely discouraged.
| Group | Label | What belongs here |
|---|---|---|
| subjects | <Subject N> | reusable visible content - a person, an animal, a place, a costume, a style |
| pictures | <Picture N> | an image used as an actual frame: first, last, key, composition anchor |
| videos | <Video N> | whole-video relationships - an edit source, a continuation point, camera work and pacing |
| audios | <Audio N> | a voice timbre, music, ambience, an effect |
Slots grow as you fill them, one spare always waiting. A videos slot takes a VIDEO or an IMAGE batch, whichever your loader hands out - VideoHelperSuite's Load Video (Upload) wires straight in. Frames are sampled evenly up to max_frames, so the cost of a clip stays independent of its length.
The checkbox is the feature
Every slot has a checkbox on its own row. Uncheck it and the asset stays wired but costs nothing - no model load, no description, no line in the block. That's the ordinary thing to want ("everything except this one"), and pulling the wire out to get it would throw away the wiring you meant to keep. The state is saved with the workflow and travels through the API like any other value. The block comes back with the switched-off asset simply absent, and numbering stays correct.
How it writes the block
In the guide's order - subjects, pictures, videos, audio - rather than wiring order, and each label is numbered within its own category, continuing from whatever arrives on previous. So this node still sits happily in a chain with single caption nodes on either side. Outputs are reference_assets (the finished block) and captions (the raw descriptions). Wire reference_assets into a writer's reference_assets input, or into another caption node's previous.
Inputs to know
model,length,seed- shared by every asset in the node.modelhas to cover every kind you connected: a vision-only captioner can't take theaudiosgroup.max_frames- 8 by default; how many frames from a batch or clip, spread evenly.context_size- 0 sizes it from the references and your card. Leave it unless you know why you're changing it.clip- the same power move as everywhere else in this pack: connect a multimodal text encoder fromCLIPLoader(Qwen3-VL or Gemma-4) and every asset is described by that model instead of the GGUF, which stays loaded. Only Gemma-4 E2B/E4B/12B can hear audio.enabled_mask- the JSON behind the checkboxes, hidden; it just travels with the workflow.bypass- passpreviousthrough unchanged and run nothing, dropping this asset from the chain without unwiring it. Numbering stays correct because each node numbers what it receives.
What's deliberately gone: role, description, instruction. The group is the role, and hand-written text belongs to one asset at a time - keep the single Reference Caption node for that.
Install and the one real gotcha
Same pack, same install (ComfyUI Manager → search "MiniMax-H3", or git clone into custom_nodes). First run fetches the model and its projector; the node runs the official llama.cpp binaries, so nothing extra to install.
The one gotcha is it needs a recent ComfyUI. The growing inputs are io.Autogrow from the v3 node API, so on an older install this is the only node in the pack that goes missing - the rest register exactly as before. If your Manager can't see it, update ComfyUI first.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| model | COMBO | A multimodal GGUF and its projector. Entries prefixed 'on disk:' are pairs already in your ComfyUI model folders. One model reads every asset here, so it has to cover every kind you connected -- a vision-only captioner cannot take the audio group. Ignored entirely while 'clip' is connected. | |
| length | COMBO | standard | How much the model is asked to write, for every asset in this node. |
| seed | INT | 420–4294967295 | — |
| subjectsopt | COMFY_AUTOGROW_V3 | Reusable visible content: a person, an animal, an object, a scene, a costume, a style. This is the right group for an image that defines what something looks like, which the guide keeps separate from an image used as an actual frame. | |
| picturesopt | COMFY_AUTOGROW_V3 | Images used as concrete frames: a first, last or key frame, a composition anchor, a storyboard panel. If the image only defines how a character or a place looks, it belongs in 'subjects' instead. | |
| videosopt | COMFY_AUTOGROW_V3 | Whole-video relationships: the source clip of an edit, the clip a continuation starts from, or a clip whose camera work, cuts and pacing are reused. | |
| audiosopt | COMFY_AUTOGROW_V3 | Standalone audio: a voice timbre to match, music to reference, an ambience or an effect to copy. | |
| previousopt | STRING | reference_assets from an earlier caption node, if this one is in a chain. | |
| clipopt | CLIP | A multimodal text encoder loaded by 'CLIPLoader' -- Qwen3-VL or Gemma-4. Connect it and every asset here is described by that model instead of by 'model': it stays loaded between assets and between runs, so a shot full of references costs one load rather than one per asset. Only Gemma-4 E2B, E4B and 12B can hear audio. Leave it unconnected and nothing changes. | |
| optionsopt | H3_REWRITER_OPTIONS | — | |
| enabled_maskopt | STRING | {} | Which slots are switched off, as JSON, written by the checkboxes on the input rows. It is kept as a widget so the state travels with the workflow and through the API; the interface hides it. A slot missing from the map is on. |
| max_framesopt | INT | 81–64 | How many frames to take from an IMAGE batch or a video, spread evenly. All of them would overflow the context and the wall clock. |
| context_sizeopt | INT | 00–131072 | 0 sizes the context from the references and the card: llama.cpp reserves the whole KV cache up front, and a model trained for 256k would ask for tens of GB of it before looking at anything. Set a number to say it yourself; too small a value fails the run outright rather than truncating. |
| bypassopt | BOOLEAN | false | Pass 'previous' through unchanged and run no model at all, which drops this asset from the chain without unwiring it. Numbering stays correct: each node numbers what it receives, so the assets after this one close the gap. 'caption' comes back empty. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| reference_assets | STRING | — |
| captions | STRING | — |