分镜编辑器
The contact sheet you can edit by hand, living inside the graph
- images
A batch of nine comes back as nine stacked previews you scroll one at a time. If you want a board - panels side by side, comparable, reorderable - the historic answer was to save them all and do it in Photoshop.
StoryboardEditor (显示名 分镜编辑器) skips that step. Wire any IMAGE output in, hit Queue, and the node fills its own grid. Then click into a cell, swap it, delete it, insert one before or after it, and save. What comes out is one contact-sheet PNG with your border colour, cell size, and index labels.
What the node actually does under the hood
It's a preview node, not a data node. RETURN_TYPES is empty - there is no output port at all - and OUTPUT_NODE = True, which is how it gets executed. If you were hoping to feed the composed grid into another sampler, that's not this node. It's a terminal.
The mechanism is a scratch folder, not a tensor operation. Each incoming frame gets written by Pillow into ComfyUI/output/StoryboardEditor/tmp/ as cell_001_.png, cell_002_.png and so on, capped at 36 files. The node hands the frontend a fixed list of 36 slots pointing at those files, and js/storyboard_editor.js draws them as a grid overlay with hover buttons. Clicking 💾 保存分镜图 POSTs to the pack's /storyboard_editor/save_grid route, which pastes the cells onto one canvas and writes it through ComfyUI's standard get_save_image_path: you get output/{filename_prefix}_{cols}x{cols}_{timestamp}.png. A 3×3 board at the default 512 px cells with 8 px borders comes out 1568 × 1568.
Two engine details matter here. IS_CHANGED returns float("NaN") - the usual trick that forces a node to re-run on every queue instead of being cached, which is what you want from something that accumulates. And "new run" is detected by comparing PromptServer.instance.last_prompt_id against the last one it saw, so a fresh queue wipes the temp folder first.
The inputs worth touching
images is optional: leave it unwired and you can still fill cells from disk via the insert button's file picker. Wire it to get generation output there automatically.
grid_count is a dropdown of 1 / 4 / 9 / 16 / 25 / 36 - strings, not ints - and it's a maximum, extra images past that are ignored. cell_size (64–1024, step 64) and border_width (0–20) decide how big the saved sheet is. border_rgb is a plain "R,G,B" string, and a typo silently falls back to light grey 211,211,211. center_crop is the one to think about: true scales to fill and crops the overflow, keeping aspect ratios honest; false stretches everything to a square. For consistently-generated panels, cropped is fine; with mixed aspect ratios neither is great, but crop looks less wrong. show_label adds the little numbered badge in each cell's bottom-right corner.
Then auto_expand_grid, which isn't what the tooltip implies: the backend takes the value and ignores it, and the frontend merely rewrites your grid_count widget to the smallest tier that fits what it has. Handy - but the board comes out at whichever tier it climbed to that run.
Installing it
Manager first: search Joshua Storyboard Editor (or Storyboard Editor), install, restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/joshua1688/ComfyUI-StoryboardEditor.git
cd ComfyUI-StoryboardEditor
pip install -r requirements.txt
That last line installs nothing - the shipped requirements.txt just says the plugin has no extra dependencies. It wants Pillow ≥ 10.3 and numpy, which ComfyUI already ships, plus Python 3.10+. No models, no keys. One of the rare nodes whose install cannot break your environment.
Where people get burned
Your edits die on the next Queue. The temp folder gets cleared whenever a new prompt starts, so arrange panels, hit Queue on something else in the same browser session, and you may come back to an empty grid. Save first - saving doesn't clear the temp images, so you can keep tweaking and save again.
All your storyboard nodes share one folder. The temp path is fixed at output/StoryboardEditor/tmp, not per-node or per-workflow. Two 分镜编辑器 nodes in one graph append into the same pool and render the same board.
Over 36 and the extras just vanish. No warning, files past the cap get deleted wholesale. Judging a 64-image batch here means judging the first 36.
Grid not drawing at all? The JS isn't loading. Check js/storyboard_editor.js exists and hard-refresh with Ctrl+F5. A failed save is nearly always an invalid filename_prefix or no write permission on output/.
Last thing: this is a version-1.x, single-author pack with basically no community footprint yet, so you're the stress test. It's MIT, one Python file plus one JS file - skim it before installing.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| imagesopt | IMAGE | — | |
| filename_prefixopt | STRING | StoryboardEditor/grid | 保存路径前缀,支持子目录 |
| grid_countopt | COMBO | 9 | 最大网格数量,超出部分忽略 |
| border_widthopt | INT | 80–20 | 网格之间的边框像素宽度 |
| border_rgbopt | STRING | 211,211,211 | 边框RGB颜色 |
| cell_sizeopt | INT | 51264–1024 | 每个网格的边长 |
| center_cropopt | BOOLEAN | true | True=中心裁剪,False=拉伸填充 |
| show_labelopt | BOOLEAN | true | 是否显示序号标签 |
| auto_expand_gridopt | BOOLEAN | true | 图片数量超过当前宫格时,自动切换到更大的宫格 |
Outputs (0)
No outputs