Proper Pixel Art Video / GIF
Pixelate an animation without the flicker
- config
- output_path
Here's the thing about pixelating a video: if you run a per-frame pixel-art pass on every frame independently, the animation boils. The detected grid shifts a pixel one way, the palette shifts a shade the other way, and your character shimmers like a bad GIF from 1998. That's why the video half of this pack exists as its own node instead of "just loop the image node."
Why a separate node
Proper Pixel Art Video / GIF pixelates a whole animation with one shared grid and one shared palette. Upstream, the trick is that every frame of an animation sits on the same underlying mesh, so the expensive steps - Canny, morphological closing, Hough line detection, line clustering, width estimation, and palette quantization - are solved once over a sample of frames (num_sample_frames, default 8) and then applied to every frame. One grid, one palette, no frame-to-frame jitter. Same deterministic algorithm as the image node otherwise: no model, no checkpoint, no API key, CPU-friendly.
It's the same fix the community arrived at independently for AI pixel art in general: the model gives you the composition, a deterministic grid-detect-and-quantize pass gives you the pixels, and for animation the grid has to be solved globally or not at all.
Inputs that matter
input_path- a dropdown of video/GIF files from ComfyUI'sinputfolder, with upload enabled on the widget itself, so dragging a file in drops it intoinput/without any manual copying.num_colors(default 0) - 0 keeps the dominant colors, 1–256 quantizes to a palette. For a GIF, always quantize; an unquantized animation balloons.initial_upscale_factor(1–8, default 2) andpixel_width(0 = auto) - same meaning as on the image node. Raise the upscale factor or hard-code the width when detection misses.scale_result(1–20, default 1) - integer nearest-neighbor upscale of the whole animation.transparent_background- keys out the most common boundary color. Note the tooltip: GIF output supports binary transparency only, so you get hard-edged holes, not soft alpha.num_sample_frames(default 8) - how many frames are sampled to solve the mesh and the palette. This cost is paid once, so pushing it up is cheap insurance on a long clip.output_format-giformp4.config(from the Config node) andintermediate_dirare optional, andintermediate_diris again your best debugging lever.
Output
One output: output_path, a STRING holding the server-side path of the file written into ComfyUI's output directory. This node is flagged as an output node, so it runs and saves even if nothing is wired downstream - it's a terminal node, not something you chain into another image pipeline. The written file is named from the input plus the output dimensions, something like walkcycle_64x64.gif.
GIF or MP4?
MP4 is encoded near-losslessly - libx264 at CRF 1 - through PyAV, whose wheels bundle their own FFmpeg, so you don't need FFmpeg installed system-wide and quality doesn't depend on whatever your box happens to have. That's where the av dependency in the pack's requirements comes from. GIF output uses a single global palette for the whole animation.
Practical rule: MP4 if it's going anywhere near a video editor or a phone, GIF if it's a sprite-sheet preview or a forum post.
Install
ComfyUI Manager, search ComfyUI-ProperPixelArt, install, restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/unclepomedev/ComfyUI-ProperPixelArt
cd ComfyUI-ProperPixelArt
pip install -r requirements.txt
requirements.txt is just proper-pixel-art>=2.0.0,<3.0.0; the imaging stack (OpenCV headless, Pillow, NumPy, SciPy, PyAV) comes in transitively. The pack wants Python ≥3.12 and a reasonably new ComfyUI (it's built on the newer node API), and there are no model files to download.
Where people get burned
The dot in your output directory. The pack README flags this and it's real: upstream picks the container format from the suffix of the output path, and this node hands it ComfyUI's output directory. Point ComfyUI at a directory whose name contains a dot - output.v2, D:\comfy\output.old - and that dot gets read as a format name, which is one of the few ways this node fails outright.
input_path is empty. The combo only lists files in ComfyUI's input folder. Videos sitting in output/ won't show up; drag them into the node's upload widget or move them into input/.
Long clips feel slow. Detection samples frames, but every frame still gets snapped and quantized. Quantize down with num_colors, and keep scale_result at 1 until the look is right.
Nodes missing entirely. You're on a ComfyUI old enough that the pack's entry point never loads.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| input_path | COMBO | Source video or GIF from the ComfyUI input directory. | |
| num_colors | INT | 00–256 | Number of colors to quantize the frames to. 0 keeps dominant colors (preserves all colors), while 1 or more quantizes to that many colors using palette method. |
| initial_upscale_factor | INT | 21–8 | Initial image upscale factor before grid detection. Useful if detected spacing is too large. |
| pixel_width | INT | 00–256 | Width of pixels in the input frames. 0 auto-detects pixel width. |
| scale_result | INT | 11–20 | Width of pixels in the output animation. 1 means no scaling. |
| transparent_background | BOOLEAN | false | Makes pixels matching the most common boundary color transparent. GIF output supports only binary transparency. |
| num_sample_frames | INT | 8 | Number of frames to sample for mesh and palette detection across the video or GIF. |
| output_format | COMBO | gif | Output container format for the video/GIF pipeline. |
| configopt | COMFYUI_PROPERPIXELART_CONFIG | Optional advanced configuration overriding algorithm defaults. | |
| intermediate_diropt | STRING | Subfolder in the ComfyUI output directory to save intermediate algorithm visualization images. Empty disables saving. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| output_path | STRING | Server-side file path to the saved video or GIF in the ComfyUI output directory. |