MiniMax H3 Multi Keyframe [darkilNodes]
Pin keyframes anywhere on the timeline, not just the first and last frame
- model
- clip
- vae
- first_frame
- last_frame
- middle_frames
- positive
- latent
- model
The stock ComfyUI "MiniMax H3 Image to Video" node gives you exactly two anchors: frame 0 and the last frame. MiniMax H3 Multi Keyframe [darkilNodes] is a drop-in replacement that lets you pin extra images anywhere in the clip - think shot-board control, or holding a subject at the one-third mark instead of just the bookends. It returns the same positive conditioning and latent the core node does, plus a model output that carries the layout patch. This is the node you want if you've ever groaned at a generated video where the "middle" should have been an image you fed in.
Context first: MiniMax H3 is the open-source Hailuo 3 video model, released at the end of July 2026 with day-0 ComfyUI support. It's brand new territory, and so is this patch.
How it works
This is the rare node where the mechanism is worth understanding, because it explains both why it works and why it's a bit experimental. The core H3 pipeline is already written to carry a list of keyframes of any length - one condition segment and one condition latent per entry. The only thing refusing anchors in the middle is PackedLayout, which raises ValueError("only first/last keyframe anchors are supported") for anything else.
The trick: the temporal RoPE coordinate of a condition row is linear in the pixel frame index - origin + 5/3 * index, which is the 40 Hz RoPE over 24 fps video. That one formula reproduces both stock anchors exactly, which means frame 17, frame 50, whatever, is just… the same formula. So the node builds the keyframe list with real frame indices and hands back a patched MODEL: an OUTER_SAMPLE wrapper that installs a marker-gated PackedLayout patch for one sampling run and removes it in a finally block. Nothing is patched process-wide, and keyframes from other packs without the marker go through the stock code untouched.
The wiring - read this twice
model, clip, and vae come from the same places as for the core node. But that model output has to reach the sampler (the guider and scheduler). It's what carries the layout patch. If you wire it like the stock node and forget the model connection, the run stops with that exact stock error above instead of quietly stacking every anchor on frame 0. The README is blunt about it, and so am I: this is the one gotcha that will eat you.
Inputs and outputs that matter
middle_frames(IMAGE, optional) - a batch of images, one anchor per image.middle_positions(STRING) - one value per image, comma separated ("0.33, 0.66"). Leave it empty to spread the anchors evenly between first and last.position_units-ratio(0.0–1.0 of the clip) orframes(absolute index on the snapped timeline).middle_fit-cover(keep aspect, crop - like the stocklast_frame) orstretch.keyframe_noise_aug(FLOAT, default 0.999) - condition strength for every keyframe row. Lower values blend noise into the anchors and let the model deviate from them. This is the first knob to reach for when the model fights a middle anchor.length(INT, default 124 ≈ 5 s) - snapped up to the model's 17k+5 frame grid; the trained range is roughly 124–362 frames.
Plus the usual first_frame, last_frame, prompt, width (1344), height (768). Outputs: positive (CONDITIONING), latent (LATENT), model (MODEL).
Install
Pack install is the usual zero-dependency affair - no Python deps, no model files to download (the H3 checkpoint you already need for core MiniMax H3 is all you use):
- ComfyUI Manager: search "darkil" / "comfyui-darkil-nodes", or
cd ComfyUI/custom_nodes && git clone https://github.com/pytraveler/comfyui-darkil-nodes.git, then restart.
The real requirement is hidden: this node needs a ComfyUI build with MiniMax H3 support (comfy_extras/nodes_minimax_h3.py and comfy/ldm/minimax/model.py). If your ComfyUI is older than the H3 release, update ComfyUI itself first - the node will refuse with a clear "no MiniMax H3 support" error, not a crash.
Caveats worth knowing
H3 was trained with first and last anchors (the fl2va mode). A middle anchor is outside that training distribution. In practice it holds - a marker drawn on the middle image shows up in the middle of the clip with consistent motion around it - but the further past three anchors you go, the less trodden the ground. Each extra anchor also adds one condition segment to the packed sequence, roughly 1000 rows at 1344x768, so don't go overboard. Treat this as an experiment node with a really nice error message - and keep keyframe_noise_aug in your back pocket for when the model disagrees with you.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | H3 diffusion model. The returned model carries the layout patch and has to reach the sampler | |
| clip | CLIP | — | |
| vae | VAE | — | |
| prompt | STRING | — | |
| width | INT | 134432–16384 | — |
| height | INT | 76832–16384 | — |
| length | INT | 1245–3600 | Frame count at 24 fps, snapped up to the model's 17k+5 grid (124 = ~5s, trained range is ~124-362) |
| middle_positions | STRING | One position per image in middle_frames, comma separated. Empty spreads them evenly between the first and the last frame | |
| position_units | COMBO | ratio | ratio: 0.0-1.0 of the clip. frames: absolute frame index on the snapped timeline |
| middle_fit | COMBO | cover | How a middle frame is fitted to the canvas. cover keeps the aspect and crops, like the stock last_frame |
| keyframe_noise_aug | FLOAT | 0.9990–1 | Condition strength for every keyframe row. 0.999 is the stock value, lower values blend noise into the anchors and let the model deviate from them |
| first_frameopt | IMAGE | — | |
| last_frameopt | IMAGE | — | |
| middle_framesopt | IMAGE | Batch of images anchored between the first and the last frame, one anchor per image |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| positive | CONDITIONING | — |
| latent | LATENT | — |
| model | MODEL | — |