Nodes//Whisker: Sprite Sheet Generator
ComfyUI Node

Whisker: Sprite Sheet Generator

Turn a frame batch into a sprite sheet in one pass — background removal included

By nerdywhiskers·Created 5 months ago·Updated 22 days ago· 2
Whisker: Sprite Sheet Generator
  • frames
  • image
  • mask
◄target_frame_count16►
◄start_index0►
◄end_index-1►
◄grid_cols4►
◄grid_rows4►
◄target_resolution0►
◄bg_removalnone►
◄modelBiRefNet►
◄padding_top0►
◄padding_bottom0►
◄padding_left0►
◄padding_right0►
◄positionmiddle-center►
◄crop_padding0►
◄fit_to_canvasfalse►
◄original_image_scale1.00►
◄batch_size4►

You generated a short clip, and now the frames are a batch tensor and you need them as one sheet - for a game sprite, an animation contact sheet, or just to eyeball a whole video at a glance. That's this node's entire job: sprite_sheet takes an IMAGE batch (think VideoHelperSuite's Load Video, or an animated-WebP loader) and tiles the frames into a single grid_cols × grid_rows sheet. It's the "contact sheet" step that video workflows always seem to need and never want to wire by hand.

The optional extra is where it gets interesting. Because it lives in the same pack as the background-removal utilities, it can strip backgrounds while it assembles - handy when your animation frames have a solid backdrop you want gone before they become sprites.

How it works

Four stages, in order: prune, resize, remove background (optional), tile.

  • Prune - target_frame_count reduces the batch by step-skipping (every total // target frames). This happens first, so a 120-frame clip becomes 16 frames before anything expensive runs.
  • start_index / end_index then slice the pruned set - -1 for end_index means "last frame", so start_index=4, end_index=-1 means "from the 5th kept frame onward."
  • Resize - target_resolution caps the sheet's longest side; frames are resized first, so memory tracks the final output size instead of the raw clip resolution. Leave it at 0 to keep native frames.
  • Background removal - three modes: none (all alpha opaque), per-frame (run BiRefNet or RMBG-2.0 on each kept frame), or whole-sheet (assemble first, then one removal pass on the whole sheet).

The decision that matters: per-frame vs whole-sheet

This is the one choice that meaningfully changes the result. per-frame runs the model on each frame, which is slow but gives each sprite a clean, tight mask - and it's the only mode where padding_top/bottom/left/right do anything (each frame's subject is bbox-cropped, scaled to fit inside the cell minus padding, and centered). whole-sheet is one model pass, fast, but the model downsamples the assembled sheet to 1024 internally, so masks on a large sheet come out noticeably rougher. Rule of thumb: small sheets, whole-sheet; big sheets with detailed subjects, per-frame and eat the time.

Inputs and outputs

The schema is mostly obvious: frames in, grid_cols/grid_rows out. model (BiRefNet vs RMBG-2.0) matters only if you turn background removal on - and remember RMBG-2.0 is non-commercial without a paid license, so for shipping sprites stick with BiRefNet. Outputs are image (always 4-channel RGBA - the alpha is opaque in none mode) and mask (mirrors the sheet's alpha).

Two layout gotchas: if grid_cols × grid_rows exceeds the frame count, trailing cells are blank; if it's smaller, extra frames get dropped. Neither crashes, both surprise you the first time. And if a big sheet OOMs, target_resolution is the lever - it keeps the whole pipeline bounded.

Installing it

Shared pack install:

cd ComfyUI/custom_nodes
git clone https://github.com/nerdywhiskers/ComfyUI-Whisker-Nodes.git
pip install -r ComfyUI-Whisker-Nodes/requirements.txt

or search "ComfyUI-Whisker-Nodes" in ComfyUI Manager and restart. Under Add Node → whisker-nodes. First background-removal run downloads the model (~880MB) to your HuggingFace cache; if you never touch bg_removal, none of that ever happens.

Categorywhisker-nodes

Inputs (18)

NameTypeDefaultDescription
framesIMAGE—
target_frame_countINT161–1024—
start_indexINT00–1024—
end_indexINT-1-1–1024—
grid_colsINT41–64—
grid_rowsINT41–64—
target_resolutionINT00–16384—
bg_removalCOMBOnone3 options: none, per-frame, whole-sheet
modelCOMBOBiRefNet2 options: BiRefNet, RMBG-2.0
padding_topINT00–4096—
padding_bottomINT00–4096—
padding_leftINT00–4096—
padding_rightINT00–4096—
positionCOMBOmiddle-center9 options: top-left, top-center, top-right, middle-left, middle-center, middle-right, +3
crop_paddingINT00–4096Extra pixels kept around each frame's mask bbox before cropping, for breathing room. Same as BG Remove + Compose.
fit_to_canvasBOOLEANfalseFit each cropped asset into the cell proportionally (allows upscaling). When off, the asset keeps its scale and is only reduced to fit. Same as BG Remove + Compose.
original_image_scaleFLOAT1.000.1–2Scale factor applied to each cropped asset. Ignored while fit to canvas is enabled. Same as BG Remove + Compose.
batch_sizeINT41–128Frames per bg-removal forward pass. Only one chunk is on GPU at a time, so lower to 1-2 on small GPUs if per-frame bg removal runs out of memory.

Outputs (2)

NameTypeDescription
imageIMAGE—
maskMASK—