arkennemasis Scene List (the loop — one chain, N scenes)
Render 50 scenes from one chain
- image_prompt
- video_prompt
- voice_text
- scene_number
- length
- scenes_json
ComfyUI has no for loop. There's no "repeat this subgraph N times" primitive - which is why most multi-shot workflows are just the same branch copy-pasted across the canvas until it stops fitting. ArkSceneList is the arkennemasis pack's answer: it turns a JSON scene plan into per-scene lists, and ComfyUI's own executor does the iterating for you. One chain of nodes, one save node, and it renders 5 scenes or 50 off the same canvas. The scene count comes from the plan at run time, so you don't rebuild anything when the brief changes.
How the "loop" actually works
This is the neat trick. A node declaring OUTPUT_IS_LIST makes every downstream node run once per item in that output - ComfyUI's executor already slices list outputs and re-runs the chain per element, reusing any scalar inputs alongside. So ArkSceneList just needs to emit lists. It parses scenes_json (an array of scene objects, each carrying image_prompt, video_prompt and voiceText), sorts by the scene number, and fans those out as six outputs where the first five are lists: image_prompt, video_prompt, voice_text, scene_number, and length.
The length output is worth understanding, because it's the thing that keeps clips from silently being the wrong duration. Each scene's seconds field is clamped between min_seconds (default 10) and max_seconds (default 15), then snapped onto MiniMax H3's 17-frame-plus-5 frame grid at 24 fps. If the plan has no seconds field, the node infers a duration from the voice line's word count at about 2 words per second - a fallback the author measured on real TTS output rather than guessed. The 15-second ceiling isn't arbitrary: H3 is trained to roughly that length, and quality falls off beyond it.
The sixth output, scenes_json, is the odd one out - it's a plain string, not a list. That's deliberate: it hands the downstream assembler the full plan (minus any that got truncated by limit) so it can read subtitles and music cues without needing the original node.
Wiring it up
The intended shape is: Story agent → scenes_json into this node → the fan-out drives one scene-rendering chain (e.g. the pack's Hailuo Scene node) → every finished clip lands on one Video Assemble node, which declares INPUT_IS_LIST and receives the whole collection in a single call. limit is the handy one - render only the first N scenes when you're iterating, without deleting branches.
Install and gotchas
It ships in the arkennemasis pack, so install once and you get all 61 nodes:
cd ComfyUI/custom_nodes
git clone https://github.com/Hishamahmer/comfyui-arkennemasis
# then install deps and restart:
pip install -r comfyui-arkennemasis/requirements.txt
Or use ComfyUI Manager → Install via Git URL and paste the repo URL. Requirements are just replicate and httpx, and each module loads independently, so nothing else in the pack breaks if one part fails.
Two things bite people. First, scenes_json must be a valid JSON array - the node raises with the first 200 characters of your input if it isn't, and it accepts a {"scenes": [...]} wrapper if your agent wraps things. Second, the voice key in the plan is voiceText (camelCase) while its neighbours are image_prompt and video_prompt - the node accepts both spellings, but if you're writing a story-agent brief yourself, get the casing right the first time. A wrong key means an empty line, which surfaces much later as a "text is empty" TTS error instead of the naming mismatch it really is.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| scenes_json | STRING | [] | The JSON array from the story agent. |
| min_seconds | FLOAT | 10.01–15 | Floor for every clip. A scene asking for less is raised to this; a scene asking for more keeps its own length. |
| max_seconds | FLOAT | 15.01–15 | Ceiling. MiniMax H3 is trained to about 15s (362 frames); beyond that quality falls off. |
| limit | INT | 00–200 | Render only the first N scenes. 0 = all of them. This replaces the old per-branch gate — a shorter list simply means fewer iterations, and nothing downstream is blocked. |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| image_prompt | STRING | — |
| video_prompt | STRING | — |
| voice_text | STRING | — |
| scene_number | INT | — |
| length | INT | — |
| scenes_json | STRING | — |