Flipbook GIF
The fast, ugly, shareable render preview
- images
- passthrough
- status
A GIF has 256 colours, a palette, and no metadata worth mentioning. It is a terrible delivery format for AI output and a wonderful format for showing someone what your render does. That's the entire pitch, and Flipbook GIF doesn't pretend otherwise - its own docstring says it's "purely for review and communication, not colour grading".
What it does
Takes an IMAGE batch, writes an animated GIF to save_path (default preview/flipbook.gif), and passes the frames through unchanged so you can keep using the batch downstream. Relative paths land under ComfyUI's output/ folder; absolute paths are used as given; the directory gets created if it doesn't exist.
Four things you set:
fps(12) - playback speed, as1000/fpsms per frame.max_width(480) - resizes to that width, aspect preserved. This is your file-size dial: halving the width cuts the frames to a quarter of the pixels, and it's usually the difference between a 20 MB GIF and a 3 MB one.loop(on) - play forever, or once.dither(on) - Floyd-Steinberg, which smooths gradients at the cost of a slightly noisier look. Turn it off for flat-shaded or graphic content and the file will be cleaner and smaller.
Outputs are passthrough (IMAGE) and status (STRING, with the path it wrote). It's an output node.
What it's for
Dailies review, and it's genuinely good at it. Burn-In stamps the frames with timecode and shot metadata, Flipbook GIF animates them, and you've got a reviewable clip in seconds without touching ffmpeg. The passthrough matters here: you can branch one batch into a GIF for the client and a Write node for the master, from the same run.
The other use is debugging motion. If you're rendering a video model or an upscale pass over frames and something's drifting - flicker, colour breathing, a stabilizer that's making it worse - a 12fps GIF at 480 wide makes the problem jump out. Frame-by-frame clicking doesn't.
What it is not
It's not an export. The tooltip says the frames are clamped to [0, 1] and quantised to a 256-colour palette, so display-encoded input is expected and HDR values go in the bin. And the metadata point from image-io-metadata.md applies with interest here: ComfyUI's PNG output carries the whole node graph inside the file, which is why dragging a render back onto the canvas rebuilds your workflow. Re-encode as GIF and that's gone - no graph, no seed, no parameters. The GIF is a dead end for reproducibility, by design.
If you're delivering motion, use a video write node. This is the preview.
Install
Part of Radiance (147 nodes). Manager → search Radiance → install, restart ComfyUI, hard-refresh the browser. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/fxtd-studios/radiance.git
cd radiance
python -m pip install -r requirements.txt
Windows portable: pip with python_embeded\python.exe. GIF writing needs Pillow, which is in requirements.txt; no model downloads.
Where people get burned
Wiring a linear float batch straight in. You'll get a clamped, oddly-contrasted GIF and wonder why. Decode to display first - OCIO ColorSpace, GPU Tensor Ops, Float32 Convert with source_gamma set, any of them.
Assuming a big batch is cheap. Each frame becomes a PIL image and gets quantised - 300 frames at 1080p is a real amount of RAM and a slow node. Drop max_width before you blame the pack.
Reading a colour judgement off the GIF. Dithering plus 256 colours plus 8-bit clamping means gradients band and saturated colours shift. Someone will look at the GIF and tell you the grade is off. It usually isn't.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | Frames to animate, returned unchanged on passthrough. Clamped to [0, 1] and quantised to a 256-colour palette, so display-encoded input is expected. | |
| save_path | STRING | preview/flipbook.gif | Output .gif path. A relative path is written under ComfyUI's output/ folder; absolute paths are used as given. The directory is created automatically. |
| fps | FLOAT | 12.01–60 | Playback speed. GIF frame delay = 1000/fps ms. |
| max_width | INT | 48064–1920 | Resize frames to this width (preserves aspect ratio). Smaller = smaller file. |
| loopopt | BOOLEAN | true | Loop the animation indefinitely. |
| ditheropt | BOOLEAN | true | Enable Floyd-Steinberg dithering for smoother gradients. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| passthrough | IMAGE | — |
| status | STRING | — |