H3 Motion Editor (timeline, masks, automation) [alpha]
Paint where the de-rope should act
- images
- samples
- hold_map
- mask
- envelopes
- report
Alpha, and the most ambitious node in the pack: a DAW-style editor that lives right on the ComfyUI canvas. Where the classic pipeline trusts the oracle to decide where motion is too fast, H3 Motion Editor lets you decide - by dragging time blocks onto a timeline and painting the problem areas frame by frame. It compiles to the same hold_map and MASK wires everything downstream already eats, so it's a drop-in for the pipeline, not a fork of it.
The workflow
Queue once to load the filmstrip, then work on the node itself. With no blocks laid out yet and hold_until_edited on (default), the graph stops here after writing the filmstrip - nothing downstream runs - so you can't accidentally trigger the expensive regen before you've touched anything. Layout your blocks, then:
- Drag bracket blocks on the timeline - multiple blocks, snapped to the model's token grid, with the jerk profile drawn underneath so you see what the oracle sees.
- Click a block and paint the problem areas with brush and eraser, frame by frame, onion skin included.
- Set per-block dials - hold, feather size, feather profile and direction, edge grow, temporal fade.
- Toggle
Aon hold, feather, or strength to draw an automation envelope with draggable breakpoints, exactly like an automation lane in a DAW.
A block with no strokes regenerates its whole time span; strokes narrow it to the painted region. Queue again and only the regeneration side re-runs - the baseline stays cached, so edits are cheap to iterate.
Inputs that matter
images- the baseline frames on the world clock (required).editor_state- the serialized state the GUI widget maintains (required, but you don't touch it by hand unless you're an agent).samples- the baseline latent, which drives the jerk profile strip.oracle_hold_map- wire the oracle to gate it; blocks with hold=0 use oracle holds.outside_blocks- what the composite shows on frames no block covers:baselineorregenerated.paint_res(512) - the mask compile width; the composite rescales to full res.
Outputs are the drop-ins: hold_map → H3 Time Smear, mask → H3 Motion Composite (enable mask_is_soft there - the mask comes out already feathered and envelope-scaled), envelopes for inspection, and a report that prices the pass before you run it.
The agent angle
The editor state is plain JSON with a documented contract in the node's docstring ({"v": 1, "blocks": [...]}). Agents can author that JSON directly and skip the GUI entirely - the compile step is the same either way. If that matters to you, it's one of the nicer things about this node: the GUI is a convenience surface, not the interface.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/matlowai/ComfyUI-MAINodes
or ComfyUI Manager → ComfyUI-MAINodes, restart. Category latent/minimax/motion. It's an output-capable node (it can stop the graph after the filmstrip), and it's alpha - the interactive widget is young, so don't be shocked if the GUI evolves.
Common gotchas
Remember the grid: blocks snap to token boundaries, so a block you meant to start at frame 40 can land on 43. And invert_mask flips the final mask if you'd rather paint keep-baseline regions instead of regen regions. If your re-queues suddenly re-run the baseline, you edited something upstream of the cache - the "only regen re-runs" promise holds as long as the baseline branch is untouched.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | baseline frames (world clock) | |
| editor_state | STRING | serialized editor state; the GUI widget maintains this | |
| samplesopt | LATENT | baseline latent, for the jerk profile strip | |
| oracle_hold_mapopt | STRING | wire the oracle to gate it; blocks with hold=0 use oracle holds | |
| fpsopt | INT | 241–120 | — |
| rampopt | BOOLEAN | true | — |
| bridgeopt | INT | 80–20 | — |
| invert_maskopt | BOOLEAN | false | flip the final mask (paint keep-baseline regions instead) |
| outside_blocksopt | COMBO | baseline | what the composite shows on frames no block covers |
| paint_resopt | INT | 512128–1024 | mask compile width; the composite rescales to full res |
| hold_until_editedopt | BOOLEAN | true | with no blocks laid out yet, stop the graph here after the filmstrip is written (nothing downstream runs); lay out blocks and run again. Off = an empty editor passes the oracle's map through |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| hold_map | STRING | — |
| mask | MASK | — |
| envelopes | STRING | — |
| report | STRING | — |