智能循环 · 一键分镜视频
One button, five videos, and your browser does the looping
- image_prompt
- video_prompt
- filename_prefix
What this actually solves
You already have a working image→video pipeline. What you don't have is a way to feed it five different prompt pairs and come back in an hour to five clips. ComfyUI's Queue runs your graph once; the usual hack is to click Run and edit the text boxes between runs, which is how people end up with a folder of files named shot_final_v2_3.mp4.
SmartShotLoop is a single node that does the clicking for you. You paste in a JSON array of shots, wire its two prompt outputs into your existing graph, point it at your Save Video node, and press one button. It runs your whole chain N times, changing the prompts each time, and collects the videos in a gallery inside the node.
That matters more than it sounds: the real bottleneck in AI video isn't clip length, it's assembling coherent sequences. This node doesn't fix consistency - it removes the babysitting so you can iterate on it. It also explicitly does not stitch anything into one video. You get N separate files.
How it works (the loop is JavaScript, not Python)
The Python side is tiny. SmartShotLoop subclasses the pack's prompt-source node, parses your shots_json, validates it, and returns the prompts for whichever shot index it was asked for. That's it. All the orchestration lives in the pack's frontend extension, which attaches a DOM panel with the two buttons and the gallery.
Pressing 一键生成全部分镜 / "generate all shots" does roughly this:
- it snapshots your graph, checks both prompt outputs are wired upstream of the chosen save node, and refuses to start if ComfyUI's queue isn't empty;
- it trims the snapshot to your save node and its ancestors, so unrelated output branches don't fire;
- for each shot it injects
shot_indexand a randomrun_token, submits through ComfyUI's ownapp.queuePrompt(your normal login/auth path, no keys, no separate API), then polls/history/<prompt_id>until the run completes; - it pulls exactly one video descriptor out of the save node's outputs and drops a
<video>element into the gallery.
If any shot errors, is cancelled, disconnects, or times out, it stops submitting further shots. If all of them succeed you get one short 880 Hz beep - once, not per clip.
The caught exception to ComfyUI's caching is worth knowing: the prompt node overrides IS_CHANGED to return float("NaN"), the standard idiom for "never reuse my cached output," because the loop re-submits identical-looking text. It's also why this node is a cache defeat for anything behind it.
Inputs you'll actually set
shots_json is the whole interface. A JSON array, 1–100 items, each needing a non-empty image and video string, with an optional title that just labels the clip in the gallery:
[
{"title": "beach open", "image": "wide shot, girl on the shore at dawn", "video": "slow push in, waves rolling"},
{"title": "close-up", "image": "side profile, wind in her hair", "video": "slight orbit, hair moving"}
]
Wire image_prompt and video_prompt into your two text encodes, and filename_prefix into your save node's prefix field - that's what stops each shot overwriting the last, and the runner aborts on a duplicated output path if you skip it. If a prompt still lives in a widget, right-click it and pick Convert widget to input first.
The rest: video_output_node_id (the save node - the dropdown auto-selects if your graph has exactly one SaveVideo / SaveWEBM / VHS VideoCombine), timeout_minutes per shot (default 120), delay_seconds between shots, and sound_enabled / sound_volume for the finishing beep. shot_index and run_token are internal scheduling fields the batch sets; don't touch them.
Install
Search comfyui-smart-shot-loop in ComfyUI-Manager's node marketplace and check the publisher is playboy-dongan; the display name is ComfyUI Smart Shot Loop · 智能分镜循环. If Manager's registry index hasn't refreshed yet, clone it instead:
cd ComfyUI/custom_nodes
git clone https://github.com/playboy-dongan/ComfyUI-Smart-Shot-Loop.git
No pip install, no model downloads - pyproject.toml lists zero dependencies. Restart ComfyUI and hard-refresh the browser tab: the buttons and gallery are frontend code, so a restart alone won't show them. To find the node in the menu, search SmartShotLoop - the display name is Chinese, so searching English won't match it.
Where people get burned
Run does not do the batch. ComfyUI's normal Queue executes the graph once, at whatever shot_index is in the box. The batch only starts from the in-node button. That's deliberate, and it's the number one "it doesn't work" moment.
The tab must stay open and awake. Closing or refreshing stops submissions for later shots; the shot already queued may still finish and still cost you money. Turn off auto-queue. The runner re-checks the queue before every submission and stops rather than interleave, and the cross-tab duplicate lock needs HTTPS or localhost.
Exactly one video per shot. For VHS Video Combine that means saved-output enabled; for a cloud API video node that returns a URL, put the matching download/save node in between. Nested-subgraph node IDs aren't handled well either - keep the loop on the top-level canvas.
Seeds and settings are frozen at click time. The whole batch uses the snapshot taken when you hit the button, so editing a seed mid-run changes nothing (and the visible seed box may drift from what actually ran, thanks to native before/afterQueued callbacks). Fine, usually what you want for consistency - but you can't ask for a fresh seed per shot.
Set expectations on maturity. This is 0.2.0, published in early October 2026, with essentially no community footprint yet and an author who states openly that the tests run against a mocked Comfy API/DOM rather than a real GPU. Third-party node compatibility is the part that stays unproven, so validate before you build a paid-API batch on it.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| shots_json | STRING | [ { "image": "分镜1的图像提示词", "video": "分镜1的动作和运镜提示词" }, { "image": "分镜2的图像提示词", "video": "分镜2的动作和运镜提示词" }, { "image": "分镜3的图像提示词", "video": "分镜3的动作和运镜提示词" }, { "image": "分镜4的图像提示词", "video": "分镜4的动作和运镜提示词" }, { "image": "分镜5的图像提示词", "video": "分镜5的动作和运镜提示词" } ] | — |
| video_output_node_id | STRING | — | |
| timeout_minutes | INT | 1201–1440 | — |
| delay_seconds | FLOAT | 0.00–3600 | — |
| sound_enabled | BOOLEAN | true | — |
| sound_volume | FLOAT | 0.120–1 | — |
| shot_index | INT | 00–99 | — |
| run_token | STRING | manual | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image_prompt | STRING | — |
| video_prompt | STRING | — |
| filename_prefix | STRING | — |