H3 Extension Plan (alpha)
Do the grid math for chaining H3 clips so you don't have to
- plan
- length
- handle_frames
- new_frames
- report
- expand_to_end
Extending a MiniMax H3 clip into a longer one is a game of grid arithmetic wearing a video-production costume. Every segment length has to land on the model's legal frame count (the 17k+5 grid), the audio has to stay on the 40 Hz tick clock, the handle frames have to come from somewhere in the previous segment and land somewhere in the next, and the anchor mechanism that carries the seam depends on which ComfyUI core features you happen to have. Get any of it wrong and you get a broken render whose damage sits at the old boundary - which is exactly the failure signature the pack's window-mode docs warn about.
H3 ExtensionPlan is the node that does that arithmetic for you, in one step. It takes plain-language answers ("I want a seamless join with a 39-frame handle" or "this is a scene cut") and emits the numbers everything downstream needs: how many frames to generate, where the handle comes from, where it lands, and which anchor mechanism your running core actually supports.
The inputs that matter
segment_frames(default 141 - "the atom": 102 new + 39 handle) - frames to generate per segment, handle included. Rounds up to 17k+5 like core.transition- the join style:seamless (39-frame handle),cheap seamless (5-frame handle, unmeasured),frame continuity (last frame only),scene cut (no handle, global refs only), orcustom.new_frames(0) - how many frames of new material you want; 0 = everything after the handle (102 on the atom). Ask for more than fits and the generation length grows.visual_anchor/audio_anchor-autois the smart default: it picks per-token masks if your core has PR #15375, falls back to the AddGuide mechanism if not, and says which it chose. That's the kind of capability-awareness that makes this node quietly valuable.previous_length- frames in the finished previous segment (after its own trim), so the handle's source span lands correctly.final_segment(off) - critical for de-roped chains: the end of a non-final segment isn't the end of the shot, so H3 Time Smear'sexpand_to_end(end-jump protection) must be off there or a gesture ending the segment comes back accelerated after recovery. The node'sexpand_to_endoutput wires straight to Time Smear.
The outputs
plan (JSON for H3 Tail Context, H3 Protect Prefix and H3 Trim), length (frames to generate), handle_frames, new_frames, report, and expand_to_end. The report also flags when a length isn't on the audio tick clock, and warns when the handle source starts off a 17-multiple (legal, but unmeasured - token phase differs).
What "auto" is doing for you
The anchor logic is the sleight of hand. On cores with per-token masks, the tail written under the per-token freeze made a join that measured like an ordinary frame transition. On cores without them, it falls back to a guide. Same graph, different mechanism underneath, and you'd never know which one ran without the report. That's the whole value proposition: this node's job is to make "just extend it" survivable across ComfyUI versions.
Installing it
Pure Python:
cd ComfyUI/custom_nodes
git clone https://github.com/matlowai/ComfyUI-MAINodes
Restart, look under MAINodes/alpha. Example graphs want ComfyUI-KJNodes; the nodes don't. H3 underneath is community-licensed - US, EU, UK, South Korea excluded. If you're chaining clips, this is the node that turns the grid law into a set of numbers you can wire instead of a prayer.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| segment_frames | INT | 1415–3600 | frames to GENERATE per segment, handle included; rounds UP to 17k+5 like core. 141 = the atom |
| transition | COMBO | seamless (39-frame handle) | 5 options: seamless (39-frame handle), cheap seamless (5-frame handle, unmeasured), frame continuity (last frame only), scene cut (no handle, global refs only), custom (use handle_frames) |
| handle_frames | INT | 390–600 | only read for transition = custom; clip guides round DOWN to 17k+5, below 5 becomes one frame |
| new_frames | INT | 00–3600 | frames of NEW material wanted from this segment; 0 = everything after the handle (102 on the atom). More than fits raises the generation length |
| visual_anchor | COMBO | auto | 4 options: auto, guide, per_token_mask, none |
| audio_anchor | COMBO | auto | 4 options: auto, guide, regenerated, none |
| fps_num | INT | 241–240 | — |
| fps_den | INT | 11–1001 | — |
| previous_length | INT | 1410–3600 | frames in the FINISHED previous segment (after its own trim, or the first segment's full length); places the handle's source span |
| final_segmentopt | BOOLEAN | false | off for every segment another one will continue: the end of this segment is not the end of the shot, so H3 Time Smear's expand_to_end (end-jump protection, which lifts the LAST frames to the highest hold) must be off there or a gesture ending the segment comes back accelerated after recovery. Wire `expand_to_end` to H3 Time Smear |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| plan | STRING | — |
| length | INT | — |
| handle_frames | INT | — |
| new_frames | INT | — |
| report | STRING | — |
| expand_to_end | BOOLEAN | — |