MiniMax H3 Storyboard Generator ๐
Shot lists you can argue with, not just generate
- llm_service_connector
- storyboard_text
- shots_json
- shot_count
Every long AI video starts the same way: you queue eight clips, wait, and discover the story made no sense. MiniMaxH3StoryboardGenerator makes you look at the plan first. Give it a concept and a target shot count and one LLM call returns a structured storyboard - beats, shot sizes, camera moves, transitions, durations - as a table you can read and a JSON array your tooling can chew.
It's a planning artifact and stays one. This node doesn't write H3 prompts and doesn't touch the Production Plan; that's MiniMaxH3LoopPromptGenerator's job further down the graph.
What you set
concept- the whole story in a paragraph. Blank falls back to a built-in "short cinematic moment with a protagonist" default: useful for seeing the output shape before committing a real idea.shot_count- what you're asking for, 1 to 20. It's a request, not a contract: read the third output pin for the real number.style- how beats get arranged, and the dropdown that changes the board most:narrative_arc(three-act),parallel_montage,rhythmic_cuts,single_continuousfor the one-take look,character_study.genre- a 22-entry taxonomy shared with the pack's H3 prompt generator, so the advice here and downstream don't contradict each other.output_format- howstoryboard_textrenders:table(Markdown table),detailed(multi-field per shot),minimal(id plus description).
language picks the prose language (en / zh; English by default because H3 behaves better with it). Advanced knobs are temperature at 0.8 - a storyboard is the one place in this pipeline where you want creative layout, not obedient formatting - plus max_tokens and timeout.
What comes out
storyboard_text- the rendered board. This is the one humans read and edit.shots_json- the normalized array:shot_type,camera_movement,transition_in,duration_seconds,narrative_beat, pluscharacters,props,notes. Shot types come from a fixed whitelist (extreme_wide_shotthroughextreme_close_up,over_the_shoulder,point_of_view,two_shot,insert_shot, โฆ) with unknown values falling back tomedium_shot, durations clamped, ids uniqued. So the JSON is safe to key on, which is more than you can say for most model output.shot_count(INT) - what the board actually contains.
One wrinkle before you wire it: the docs describe feeding shots_json into the Loop Plan Generator, but the loop node's only free-text input is user_input - there's no shot-list socket on it. The handoff is text: read storyboard_text, edit what you disagree with, paste it into user_input (or the enhancer's draft). The board is your thinking space; the loop node turns prose into plan-shaped prompts.
H3 timing note: duration_seconds is the field to respect. H3 generates 4โ15s per call and the loop node caps every scene at 14s, so a board planning eight 20-second shots is a board you'll be re-cutting.
How it behaves when the model misbehaves
It asks for a JSON array in one call, tolerates a bare array, a ```json fence or prose around it, and strips a leading <think> block from a reasoning model. If the array still won't parse it does one corrective retry - a "your last reply was malformed" turn - then fails the node outright. No partial boards, which is the behaviour you want when a bad board would otherwise become twelve paid generations.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/MieMieeeee/ComfyUI-MieNodes
cd ComfyUI-MieNodes && pip install -r requirements.txt
Or find ComfyUI_MieNodes in ComfyUI Manager - it's on the Comfy Registry under publisher mie. No models, no heavy dependencies: just a Set*LLMServiceConnector with a working key (or a local Ollama endpoint, which costs nothing per call and handles this job fine).
Where people get burned
- A local 8B model that won't emit JSON. The contract is a JSON array, and the failure is a hard fail, not a shrug. Keep getting "unparseable after 2 attempts" on a small local model? Switch that one node to something bigger - it's the least frequent call in the pipeline, so it's the cheapest place to rent quality.
- Reasoning models and
max_tokens. The 8192 default already assumes some models burn budget thinking before they answer (the source of this repo notes exactly that failure: HTTP 200, empty content). If you drop it low "to save money", that's what you'll get. shot_countisn't honoured to the digit. Models round, merge and pad. Trust the output pin, not the number you typed.- It plans, it doesn't prompt. No dialogue is locked verbatim, no
<d>blocks are emitted, no continuation rules are written. If what you want is a shootable H3 plan, this is step one of two - the loop node is step two.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| llm_service_connector | LLMServiceConnector | โ | |
| concept | STRING | Overall creative concept / story summary for the whole video. Blank = the node synthesizes a default concept. | |
| shot_count | INT | 51โ20 | Expected number of storyboard shots. |
| style | COMBO | narrative_arc - ๅไบๅผงๅ /ไธๅน | Storyboard style: how beats are arranged and cut. |
| genre | COMBO | none - ไธๆๅฎ | Genre taxonomy shared with the H3 prompt generator; injects genre-specific guidance. |
| language | COMBO | en | 2 options: en, zh |
| output_format | COMBO | table - Markdown่กจๆ ผ | Rendered format of storyboard_text. |
| seed | INT | 00โ18446744073709550000 | โ |
| temperatureopt | FLOAT | 0.800โ2 | โ |
| max_tokensopt | INT | 819264โ32768 | โ |
| timeoutopt | COMBO | 120 | 4 options: 30, 60, 120, 300 |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| storyboard_text | STRING | โ |
| shots_json | STRING | โ |
| shot_count | INT | โ |