Nodes/Mickmumpitz-Nodes/Make Storyboard Grid
ComfyUI Node

Make Storyboard Grid

A real storyboard sheet out of a batch of stills

By mickmumpitz·Created 10 months ago·Updated 25 days ago· 55
Make Storyboard Grid
  • images
  • storyboard
◄project_nameMyStoryboard►
◄shot_count8►
◄columns4►
◄cell_width512►
◄cell_height288►
◄cell_padding24►
◄frame_lengths24,24,24,24,24,24,24,24►
◄shot_namesShot 1,Shot 2,Shot 3,Shot 4,Shot 5,Shot 6,Shot 7,Shot 8►
◄auto_scale_texttrue►
◄text_scale_multiplier1.00►
◄timeline_start_frame0►

Most "image grid" nodes give you a contact sheet. Make Storyboard Grid gives you a storyboard - a project header, a title above every cell, a white frame around each shot, and a Timeline: Frame 0-23 caption underneath that actually advances shot to shot. It's the review artifact: the thing you look at before committing an hour of GPU time, or send to whoever you're making the video for.

It reads a batch of images, one per shot, and writes one IMAGE out. So it wires into Preview Image or Save Image like any other picture.

How it works

It's PIL all the way down - the node builds the sheet on CPU with ImageDraw, then converts the result back to a ComfyUI IMAGE tensor. No model, no GPU work, no surprises about your VRAM.

The layout math is fixed by the code, and it's worth knowing because it explains what you get:

  • It uses shot_count images from the batch, capped by however many you actually fed it (min(shot_count, batch size)). Extra images in the batch are ignored silently - so if your last cell is missing, that's the thing to check.
  • Each image is cover-fitted into the cell: scaled to fill, then centre-cropped. It crops to fit, it doesn't letterbox. A 16:9 still in a square cell loses its edges.
  • Timeline captions are computed cumulatively from your frame lengths: shot 1's caption runs from timeline_start_frame to that plus its length, and the next shot starts where the previous ended. So the captions describe a real edit timeline, not just "24 frames each".
  • Text sizes scale off min(cell_width, cell_height), with clamps so you can't end up with 4px or 200px type.

Those comma-separated STRING fields - shot_names and frame_lengths - are the reason this pairs with Make Storyboard Data, whose shot_names_joined and frame_lengths_joined outputs are shaped exactly for these two widgets. Names get padded with blanks if you supply fewer than there are cells, and a blank name falls back to "Shot N". Blank or non-numeric frame lengths don't crash anything: they're read as zero, which advances the timeline by exactly one frame. So a typo in the middle of your lengths list shows up as a one-frame shot in the captions rather than an error.

Inputs you'll actually touch

images is the batch - one image per shot, in shot order, and order is entirely on you. project_name is the header text (MyStoryboard by default) and takes the whole top strip, so it's worth using something meaningful.

Then the layout: shot_count (1–100), columns (default 4), cell_width and cell_height (512×288 by default, both 64–4096 in steps of 8), and cell_padding (24). Default 8 shots in 4 columns gives you a two-row sheet. Change columns to 8 and you get one long strip.

The optional trio is where the polish lives. auto_scale_text (on by default) sizes the header, titles and captions relative to the cell. text_scale_multiplier (0.3–3.0) exists to nudge that - but note a quirk in the shipped code: when auto_scale_text is off, the multiplier is skipped entirely and the node falls back to fixed sizes, so turning auto-scaling off makes that slider do nothing. And timeline_start_frame (default 0) is how you make the captions match reality - if shot 1 lands at frame 121 in your edit, set it to 121 and the whole sheet re-bases.

The single output is storyboard, an IMAGE. Preview it, save it, or feed it into a note/documentation step. Don't route a big sheet back into a video model; a 4-column 512-wide grid is already around 2,200px across.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/mickmumpitz/ComfyUI-Mickmumpitz-Nodes.git

Restart ComfyUI. Manager route: search "Mickmumpitz", Install, restart. MIT-licensed, published as "Mickmumpitz-Nodes" under publisher id mickmumpitz, currently v1.5.9.

The pack's requirements.txt covers this node's real needs - Pillow for the drawing and numpy for the tensor/pixel conversion - plus opencv-python and ultralytics>=8.0.0, which the README says are only genuinely needed by the Consistent Character Creator's detector path. No model files to download.

Troubleshooting

The text is tiny and blocky, or the same size no matter what. The node looks for a real TTF in the usual OS places - Arial/Segoe UI on Windows, Arial on macOS, DejaVu or Liberation on Linux - and only then falls back to matplotlib's font finder, and finally to Pillow's built-in bitmap font, which won't scale. On a bare Linux container, apt install fonts-dejavu (or fonts-liberation) is the fix; pip install matplotlib also gives the node a second chance to find something. Either way it's a missing-system-font problem, not a node bug.

Cells are cropped. That's cover-fit doing its job. If losing the edges matters, either match cell_width/cell_height to your images' aspect ratio, or accept it - a storyboard is for reading the shot, not preserving it.

Row of cells missing. shot_count is lower than the number of images in the batch; the extra ones are dropped.

Captions don't match what you generated. They come purely from the frame_lengths string. If you hand-typed it rather than wiring Make Storyboard Data's joined output, a mismatch is almost certainly a comma-count problem - one entry missing shifts every length after it by one shot.

CategoryMickmumpitz/Storyboard

Inputs (12)

NameTypeDefaultDescription
project_nameSTRINGMyStoryboard—
shot_countINT81–100—
columnsINT41–20—
cell_widthINT51264–4096—
cell_heightINT28864–4096—
cell_paddingINT240–200—
imagesIMAGE—
frame_lengthsSTRING24,24,24,24,24,24,24,24—
shot_namesSTRINGShot 1,Shot 2,Shot 3,Shot 4,Shot 5,Shot 6,Shot 7,Shot 8—
auto_scale_textoptBOOLEANtrue—
text_scale_multiplieroptFLOAT1.000.3–3—
timeline_start_frameoptINT00–100000—

Outputs (1)

NameTypeDescription
storyboardIMAGE—