H3 Shot Dispatcher
One segment per queue run — and why queueing forty is completely safe
- project
- timeline
- cast
- shot
- prompt
- length
- width
- height
- fps
- seed
- refine_seed
- first_frame
- info
ComfyUI runs a graph once. That's the whole problem with long video: a twelve-segment piece means twelve runs, and something has to remember which segments are already done - across interruptions, restarts, and you editing two prompts halfway through. H3 Shot Dispatcher is that something. It claims one outstanding segment per queue run and emits the plain primitives your sampler already wants.
It's the node that turns a single-clip H3 graph into a render farm of one.
The cursor is a state machine, not a counter
A segment is outstanding for a pass when it isn't locked, isn't currently running, and has no stored clip for that pass. The dispatcher claims the first outstanding segment, marks it running, and H3 Vault Write is what completes it. Claiming is idempotent, so:
- queue forty runs against twelve segments → twelve render, twenty-eight no-op
- interrupt, edit two prompts, resume → only those two re-render
- kill ComfyUI mid-render → the next run picks up exactly where it stopped
- a run that dies leaves its segment
running; afterstale_minuteson H3 Project it returns topendingon its own
When nothing is outstanding it execution-blocks the sampler branch instead of erroring, so a run with nothing to do finishes clean and tells you why.
Inputs you actually touch
project and timeline are the wires. Then:
mode-next_pending(the normal one),manual_index(reshoot a specific card),range,failed_only(retry after a crash).force_rerender- discard the stored clip for this pass and shoot another take.reset_stuck- force every segment stuck onrunningback to pending. A cancelled or crashed run leaves one behind, and enough of those stall the queue.prompt_format-full_reference_6(the default),video_3field, orflat. It decides how the six authored sections get flattened into the one string the sampler takes, and it matches how ComfyUI-H3-Prompt-Creator renders, so prompts from either path come out byte-identical.
Optional cast in, and ten outputs out. prompt, length, width, height, fps, seed, refine_seed, first_frame, info all wire into your existing sampling graph - length replaces the Float (Duration) node, and the dispatcher does the % 17 snapping for you.
The one wire that matters
shot. It carries segment id, pass, take and seed around the sampler - shot goes straight into H3 Track Slice and H3 Vault Write while the sampler never learns timelines exist. That's what lets the vault know what it's receiving without your sampling subgraph being cluttered with bookkeeping.
seed and refine_seed are worth a mention: both are derived deterministically from the H3 Project base_seed, and they stay fixed across re-plans. That's why a promoted segment matches the draft you approved instead of quietly becoming a different video.
Concretely: ask for 6.000s at 24fps and length comes out 158 frames = 6.583s, because 144 frames isn't on the ladder. The stitcher trims the extra 0.583s back off. You never do that arithmetic again.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/AIJigyasa/ComfyUI-H3-Planner
Then restart. Or search MiniMax H3 Planner in ComfyUI Manager. You need ffmpeg on PATH (or pip install imageio-ffmpeg into the ComfyUI environment) because every stored clip gets encoded, and a ComfyUI with the MiniMax H3 nodes, since the pack drives MiniMaxH3ReferenceToVideo rather than sampling itself.
Where people get burned
"Nothing to render" while segments sit on running looks exactly like "all done" from the outside - that's what a stalled queue feels like. The node now prints the state counts and the fix (tick reset_stuck), but if you're on an older copy, that's your answer.
An upstream planner inside the render graph will fight the vault. If a node rewrites your prompts on every queue while reuse_existing is off, the timeline discards the clips that no longer match and your segments go outstanding again seconds after they rendered. Keep planning and rendering in separate workflows - the examples are built that way for a reason.
Don't wire length into the sampler and leave your old Math Expression in the graph too. Remove the Float (Duration) and the % 17 expression node; the dispatcher is doing that job now, and it records what it did in info.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| project | H3_PROJECT | — | |
| timeline | H3_TIMELINE | — | |
| mode | COMBO | next_pending | 4 options: next_pending, manual_index, range, failed_only |
| manual_index | INT | 11–9999 | — |
| range_start | INT | 11–9999 | — |
| range_end | INT | 00–9999 | 0 = to the end |
| force_rerender | BOOLEAN | false | discard the stored clip for this pass and shoot another take |
| prompt_format | COMBO | full_reference_6 | 3 options: full_reference_6, video_3field, flat |
| reset_stuck | BOOLEAN | false | force every segment stuck on 'running' back to pending. A cancelled or crashed run leaves one behind, and enough of those stall the queue. |
| castopt | H3_CAST | — |
Outputs (10)
| Name | Type | Description |
|---|---|---|
| shot | H3_SHOT | — |
| prompt | STRING | — |
| length | INT | — |
| width | INT | — |
| height | INT | — |
| fps | FLOAT | — |
| seed | INT | — |
| refine_seed | INT | — |
| first_frame | IMAGE | — |
| info | STRING | — |