Nodes/ComfyUi-MpiNodes/Mpi H3 References
ComfyUI Node

Mpi H3 References

Every MiniMax H3 reference slot, on one node

By MadPonyInteractive·Created 11 months ago·Updated 6 days ago· 3
Mpi H3 References
  • clip
  • vae
  • audio_vae
  • ref_image_1
  • ref_image_2
  • ref_image_3
  • ref_image_4
  • ref_image_5
  • ref_image_6
  • ref_image_7
  • ref_image_8
  • ref_image_9
  • ref_video_1
  • ref_video_audio_1
  • ref_video_2
  • ref_video_audio_2
  • ref_video_3
  • ref_video_audio_3
  • ref_audio_1
  • ref_audio_2
  • ref_audio_3
  • positive
  • latent
  • ref_tags
prompt
width1344
height768
length124
ref_image_sizematch

MiniMax H3 is an omni-modal video model: it takes text, images, video and audio as one input context, and the prompt can point at references by tag - <Picture 1>, <Video 1>, <Audio 2> - to say "make this look like this." ComfyUI's core node grows those reference slots one at a time as you connect them, which is fine for a human clicking in the UI but a nightmare for anything that compiles a saved workflow: covering every combination of "which slots are filled" would need 2^18 pre-authored branches. MpiH3References is the fix - all 18 slots exposed flat, always present. Fill what you have, leave the rest empty, and the node drops the empties itself and renumbers the survivors so the tags in your prompt still point at the right thing.

How it works

The inputs: clip, vae and audio_vae (the three models H3 needs), a multiline prompt, width/height/length (feed length from MpiH3Length), and ref_image_size. Then the 18 optional slots:

  • ref_image_1 through ref_image_9 - reference images.
  • ref_video_1 through ref_video_3 - reference video frames (24fps, 2–15s).
  • ref_video_audio_1 through ref_video_audio_3 - each reference video's paired soundtrack.
  • ref_audio_1 through ref_audio_3 - standalone reference audio.

Two design choices make this workable. First, the heavy lifting is delegated to core's own MiniMaxH3ReferenceToVideo, not reimplemented - the conditioning maths can't drift from ComfyUI. Second, "empty" is detected reliably: an unconnected slot, or an Mpi loader run with block_if_empty off (which emits a 1×1 image / 1-sample waveform sentinel). A genuinely black image or genuinely silent clip still reports its real size/sample count, so real content is never mistaken for absent.

The tag system - read this twice

Write your prompt against slot numbers: <Picture 1> means whatever is wired into ref_image_1, <Audio 2> into ref_audio_2. The node rewrites those tags to the ordinals core actually presents - because core renumbers references as empty ones are dropped - and drops any tag whose slot is empty. That's what keeps a tag pointing at the same input no matter which slots ahead of it are empty.

And it's the only way to be right about audio. H3 shares one audio sequence between reference videos and standalone clips, and a reference video's soundtrack consumes an <Audio j> slot before its own <Video k> tag - whether a file even has a soundtrack is only known once it's decoded. So the node renumbers at runtime rather than trusting a static mapping, and the ref_tags output reports the final map. If audio pairing is going wrong, that string is the first place to look.

The inputs that matter

  • prompt - your text, with <Picture i> / <Video k> / <Audio j> tags written against the slots.
  • length - frame count at 24fps (124 ≈ 5s, trained range ~124–362). Feed it from MpiH3Length.
  • ref_image_size - how each reference is scaled: match fits it to the output's pixel area; max uses a 2048 short edge and is best for identity - use it for character sheets, where match squashes individual views past readability. max is several times slower, because reference tokens ride through every sampling step. That's the trade, and it's real.

Outputs: positive CONDITIONING, latent, and the ref_tags string - that last one being the resolved tag map for debugging.

Where people get burned

The two classic mistakes: writing <Picture 1> to mean "the first image I have" instead of "the slot named ref_image_1" (slot order is whatever you wired, not importance), and setting ref_image_size to max on a big multi-reference batch without realising each step pays for it - that can turn a fast clip into a very long wait. And remember the audio truthiness rule: an unconnected audio slot is dropped, but a connected audio wire that turns out to be silent passes through as real content. That's correct - H3 can legitimately want silence as a reference - but "my reference is silent" is a real possibility, and it's on you to notice.

Install

From the MadPonyInteractive/ComfyUi-MpiNodes pack. ComfyUI Manager → search ComfyUi-MpiNodes (publisher mad-pony-interactive), install, restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/MadPonyInteractive/ComfyUi-MpiNodes

then restart. No extra dependencies beyond H3 itself - the model is a large download from HuggingFace (MiniMaxAI/MiniMax-H3), and its community licence geofences the weights out of the US, EU, UK and South Korea. The pack is AGPL-3.0 (≤ 1.2.6 MIT) and is the node library behind the author's Cubric Vision app.

The verdict

For a one-off manual H3 job in the web UI, core's growable node is fine. The moment you're compiling workflows or running the same graph with different references, the flat 18-slot surface is the difference between "impossible" and "one node." It's the most complicated node in this pack, and the one that most clearly exists to solve a problem the core UI pretends doesn't exist.

CategoryMpiNodes/Utils

Inputs (26)

NameTypeDefaultDescription
clipCLIP
vaeVAE
audio_vaeVAE
promptSTRINGAddress references by their SLOT number here: <Picture 1> is whatever is wired into ref_image_1, <Audio 2> into ref_audio_2. The node rewrites them to the ordinals core presents (see ref_tags) - so a tag keeps meaning the same input no matter which other slots are empty. A tag naming an empty slot is removed.
widthINT134432–16384
heightINT76832–16384
lengthINT1245–3600Frame count at 24 fps (124 = ~5 s, trained range ~124-362). Feed it from MpiH3Length.
ref_image_sizeCOMBOmatchHow each reference is scaled (aspect kept, never upscaled, no crop). 'match' fits it to the OUTPUT's pixel area. 'max' uses a 2048 short edge and is best for identity - use it for character sheets, where 'match' squashes the individual views past readability. 'max' is several times slower: reference tokens ride through every sampling step.
ref_image_1optIMAGEReference image. Leave unconnected, or feed a loader with block_if_empty OFF, to skip it.
ref_image_2optIMAGEReference image. Leave unconnected, or feed a loader with block_if_empty OFF, to skip it.
ref_image_3optIMAGEReference image. Leave unconnected, or feed a loader with block_if_empty OFF, to skip it.
ref_image_4optIMAGEReference image. Leave unconnected, or feed a loader with block_if_empty OFF, to skip it.
ref_image_5optIMAGEReference image. Leave unconnected, or feed a loader with block_if_empty OFF, to skip it.
ref_image_6optIMAGEReference image. Leave unconnected, or feed a loader with block_if_empty OFF, to skip it.
ref_image_7optIMAGEReference image. Leave unconnected, or feed a loader with block_if_empty OFF, to skip it.
ref_image_8optIMAGEReference image. Leave unconnected, or feed a loader with block_if_empty OFF, to skip it.
ref_image_9optIMAGEReference image. Leave unconnected, or feed a loader with block_if_empty OFF, to skip it.
ref_video_1optIMAGEReference video frames at 24 fps (2-15 s).
ref_video_audio_1optAUDIOSoundtrack for ref_video_1. Pairing is by this number, so wire it from the same loader.
ref_video_2optIMAGEReference video frames at 24 fps (2-15 s).
ref_video_audio_2optAUDIOSoundtrack for ref_video_2. Pairing is by this number, so wire it from the same loader.
ref_video_3optIMAGEReference video frames at 24 fps (2-15 s).
ref_video_audio_3optAUDIOSoundtrack for ref_video_3. Pairing is by this number, so wire it from the same loader.
ref_audio_1optAUDIOStandalone reference audio.
ref_audio_2optAUDIOStandalone reference audio.
ref_audio_3optAUDIOStandalone reference audio.

Outputs (3)

NameTypeDescription
positiveCONDITIONING
latentLATENT
ref_tagsSTRING