H3 Window Loop (rolling regen, one node) [alpha]
The whole de-rope chain, inside one node, on a VRAM leash
- model
- positive
- vae
- audio_vae
- sampler
- sigmas
- images
- guider
- baseline_audio
- images
- audio
- plan
- report
MiniMax H3 smears fast motion, and the fix that makes sense of it - the de-rope - is expensive. The whole Motion Lab pipeline slows a clip down on its own time axis, regenerates it video-to-video at partial denoise, then drops the held frames to recover the original frame rate. That's roughly eight nodes wired in a chain. On a clip with a lot of fast action, the dilated clip (the slowed one) can be several times longer than the original, and holding that whole thing in VRAM at once is exactly what blows up a mid-size card.
H3 Window Loop is the one-node answer: it plans the dilated clip into rolling windows that each fit a budget you set, runs the entire per-window chain internally, and splices the world back together. One node replaces the whole graph for people who don't want to build it, or for cards that can't hold it.
What the node actually runs
Internally it does time smear → VAE encode → V2V init → sample → decode → exact recover → audio recover → splice, per window, then hands you the assembled clip. Because that chain runs inside, the node needs the sampler's ingredients as inputs rather than a pile of images. The ones that matter:
model,positive,vae(video VAE) andaudio_vae(for the jointly generated foley)samplerandsigmas- the tooltip says it plainly: these should be the injected sigmas from H3 Inject Schedule, that's the whole pointimages- the baseline frames on the world clockhold_map- from the jerk oracle, H3 Manual Hold Map, or H3 Motion Editorbudget_dilated- the knob. It's counted in dilated frames, not world frames, because dilated length is what sets both the bill and the VRAM peak. Default 124.
Run it once with plan_only on and the report output prices every window before you pay for any of them. This is the step people skip and then regret.
Cold seams and hot seams
The planner's seam policy is the same one the whole window family shares. A boundary between bursts is a cold cut - both handles sit at hold 1, so the splice crossfades real-time baseline context, the shipped single-window behaviour repeated N times. A boundary forced inside a burst is a hot cut and gets pin-and-trim instead: the next window regenerates an overlap seeded from the already-recovered world, uses it as context, then throws it away, leaving a hard cut at a pinned frame. Hot audio is a hard cut at the local RMS minimum, never a crossfade - two independent foley takes of one moment can't be dissolved, and the node knows it.
What rides along, and what doesn't
MODEL-domain patches - LoRAs, attention patches, chunked feed-forward - apply, because you wire them upstream into model. SAMPLER wrappers too. IMAGE-domain nodes inside a loop body can't, by construction. The common one people want, an ImageScale between smear and encode, is replicated by the draft_width/draft_height widgets. Anything else you wanted in the loop just isn't reachable from here.
Installing and other notes
This ships in ComfyUI-MAINodes (GPL-3.0, MiniMax-H3 nodes by matlowai). No Python deps of its own:
cd ComfyUI/custom_nodes
git clone https://github.com/matlowai/ComfyUI-MAINodes
Restart ComfyUI. Alpha nodes like this load behind a guarded loader so a broken one can't take the pack down - check the README for the "alpha, expect interfaces to move" caveats. It's deliberately one of three rolling-window implementations shipped side by side (the requeue pair in motion.py and this one), and the pack says to expect at most one to survive. Don't build a house on it. Interrupt lands at the next sampler step, not the next window; set on_interrupt to return partial world if you'd rather keep the windows that already landed than lose the run.
Inputs (24)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | patched however you like: LoRAs, attention patches and chunked feed-forward all ride along | |
| positive | CONDITIONING | — | |
| vae | VAE | video VAE | |
| audio_vae | VAE | audio VAE, for the jointly generated foley | |
| sampler | SAMPLER | — | |
| sigmas | SIGMAS | from H3 Inject Schedule; the whole point is that these are the INJECTED sigmas | |
| noise_seed | INT | 00–18446744073709550000 | — |
| images | IMAGE | baseline frames, world clock | |
| hold_map | STRING | from the oracle, H3 Manual Hold Map or H3 Motion Editor | |
| budget_dilated | INT | 12439–3600 | max DILATED frames per window; the VRAM and cost dial |
| guideropt | GUIDER | overrides model+positive; wire your own guider to keep control of conditioning | |
| baseline_audioopt | AUDIO | the baseline clip's track; unwired, the world starts as silence | |
| handle_framesopt | INT | 122–48 | real-time context frames on each COLD edge |
| pin_framesopt | INT | 62–48 | overlap regenerated then discarded at each HOT edge (pin-and-trim) |
| feather_framesopt | INT | 60–24 | crossfade width inside a COLD handle; hot edges ignore it by policy |
| fpsopt | INT | 241–120 | — |
| seed_strideopt | INT | 10–1000 | seed offset per window; 0 = every window on the same seed |
| draft_widthopt | INT | 00–4096 | 0 = off. Replicates the ImageScale that community loop bodies put between smear and encode |
| draft_heightopt | INT | 00–4096 | — |
| upscale_methodopt | COMBO | lanczos | 5 options: lanczos, bicubic, bilinear, area, nearest-exact |
| on_interruptopt | COMBO | raise (stock behaviour) | 2 options: raise (stock behaviour), return partial world |
| plan_onlyopt | BOOLEAN | false | price the plan and stop; images pass through untouched |
| audio_rms_search_msopt | FLOAT | 120–200 | how far a hot audio cut may slide to land on a local RMS minimum |
| s_per_stepopt | FLOAT | 0.000–120 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| audio | AUDIO | — |
| plan | STRING | — |
| report | STRING | — |