H3 Drawn Plan (alpha)
Draw the timing envelope in the web editor, wire it into the graph
- ranges
- length
- fps
- window_start
- window_len
- report
- hold_map
- dilated_frames
- guide_frame
- splice_map
The pack's timeline surface has a philosophy: you author a shot as a plan document - what it should do, in seconds and densities - and the motion nodes turn that into concrete retiming instructions. H3 Drawn Plan is the bridge node that loads such a plan and hands you back the compiled geometry as wireable outputs. Draw the envelope in the web editor, export the plan, point this node at the file, and the drawing arrives in the graph without anybody retyping frame numbers.
The key thing to internalize, because it explains every other decision in this node: the ranges come from the compiler, not from this node. H3 Drawn Plan is a deliberately thin loader - its docstring says it contains no grid law, and if it ever needed to know about 17-frame groups or token indices to do its job, "the answer has been forked." That's a design principle, not a limitation. The plan's compiler produces the map; this node just parses and exposes it.
Two doors, one answer
The node gives you the same compiled map in two languages:
hold_map- the compiler's map verbatim, for wiring straight into H3 Temporal Insert. This is the exact map, no reshaping.ranges- the same map in H3 Manual Hold Map's language, for when you want to read or edit it by hand. That route re-shapes through the node's own token snapping, so the README is emphatic: wire ranges with ramp OFF and bridge 0 to reproduce the compiler's map exactly. Leave ramp on and you reshape the shoulders a second time.
Plus the useful integers: length, fps, window_start, window_len, dilated_frames, guide_frame, and splice_map (which drives H3 Segment Splice at feather 0 to put the recovered window back into the untouched clip). There's also a report that prices the plan before you run anything.
Inputs and the practical bits
plan_path (a plan.json from the editor, the oracle node, or the CLI) and optional plan_json (the plan pasted directly - wins over plan_path when both are filled, so a plan pasted from a chat works with no file on disk). ignore_uncompiled_lanes (false) controls what happens when a plan carries lanes this backend can't compile yet (pins, regions): off refuses the plan so nothing is dropped silently; on compiles the density lane anyway and names every skipped lane in the report.
If you're not using the web editor at all, this node can still serve you: the CLI and the oracle node also emit plans, and the JSON contract means agents can author them directly. It's the "typed, auditable handoff" node for the timeline surface - the thing that makes a drawn plan a graph citizen instead of a screenshot.
Installing it
Pure-Python pack:
cd ComfyUI/custom_nodes
git clone https://github.com/matlowai/ComfyUI-MAINodes
Restart, look under latent/minimax/timeline. It's alpha - the timeline surface is new and its interfaces may still move. Example graphs want ComfyUI-KJNodes; the nodes don't. H3 underneath is community-licensed (US, EU, UK, South Korea excluded). If you author plans in the web editor, this is the only way they get into the graph cleanly.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| plan_path | STRING | path to a plan.json written by the editor, the oracle node or the CLI | |
| plan_jsonopt | STRING | the plan document itself, pasted; wins over plan_path | |
| ignore_uncompiled_lanesopt | BOOLEAN | false | a plan may carry lanes this backend cannot compile yet (pins, regions). OFF: refuse, so nothing is silently dropped. ON: compile the density lane anyway and name every lane that was skipped |
Outputs (10)
| Name | Type | Description |
|---|---|---|
| ranges | STRING | — |
| length | INT | — |
| fps | INT | — |
| window_start | INT | — |
| window_len | INT | — |
| report | STRING | — |
| hold_map | STRING | — |
| dilated_frames | INT | — |
| guide_frame | INT | — |
| splice_map | STRING | — |