CCSR_Upscale
The no-prompt diffusion upscaler that's lighter than SUPIR
- ccsr_model
- image
- upscaled_image
If you've ever followed a 2024 upscaling tutorial, this is the node that was doing the actual lifting. CCSR_Upscale is the workhorse of Kijai's ComfyUI-CCSR pack: a diffusion-based upscaler that takes a photo and a model and hands back a bigger, sharper, rebuilt image. It belongs to the pre-SeedVR2 generation, the same family as SUPIR but on a much lighter SD-1.5-scale backbone - and it's still the cheapest way to get the "diffusion actually invented detail" effect on a mid-range card.
Upscaling is really three jobs (more pixels, more detail, more frames). CCSR is firmly the second one. Feed it a soft, low-res portrait and it doesn't interpolate - it re-renders. If all you need is pixels, skip this and grab Lanczos or a 4x ESRGAN model: instant and free. But when you want a generative rebuild and can't afford SUPIR's 12GB+ footprint, this is the 2024 answer that still works today. Just know it's dated; by 2026 SeedVR2 is what everyone actually runs, and CCSR has quietly become the retro pick or the one you reach for on a modest card.
How it works
CCSR stands for Content-Consistent Super-Resolution, and the "consistent" is doing real work. Under the hood it's a latent diffusion model (a ControlLDM) whose conditioning is your image itself, injected through a ControlNet-style stage at all 13 scales. There's no prompt anywhere - the node uses a fixed empty text embedding at cfg_scale 1.0, so the image alone decides the output.
The flow: your input gets resized by scale_by, encoded to latents at 8x downsample, run through ~45 denoising steps between t_min and t_max, then decoded and re-scaled to exact dimensions. Because diffusion loves to drift colors, an adain color-fix pass (the default) pins the output to the source. Set keep_model_loaded off (the default) and the model unloads when it's done, which keeps your VRAM from staying hostage between runs.
The inputs that matter
- ccsr_model - the CCSRMODEL output from a loader node (see below).
- image - the IMAGE you're upscaling.
- scale_by - the real upscale factor. Default 1.0 means "same size, just diffuse"; set 2–4 for an actual upscale. This is the knob people most often forget.
- sampling_method -
ccsr(no tiling, OOM risk on big images),ccsr_tiled_mixdiff(the default; tiles the diffusion), orccsr_tiled_vae_gaussian_weights(tiles the VAE too - lowest memory, slightly softer seams). - steps / t_min / t_max - how hard it re-imagines. Lowering
t_minbuys more detail and more hallucination in equal measure.
The single output, upscaled_image, wires straight into a SaveImage node.
Installing and getting a model
Install the pack the normal way - ComfyUI Manager, searching for "ComfyUI-CCSR", or:
cd ComfyUI/custom_nodes
git clone https://github.com/kijai/ComfyUI-CCSR
Restart ComfyUI and let Manager install the requirements: taming-transformers, omegaconf, einops, pytorch-lightning>=2.2.1, and open-clip-torch>=2.23.0. That's a heavier dependency set than most packs, and the pytorch-lightning pin has been known to fight other custom nodes, so let Manager sort it rather than pip-ing blind.
Then you need the model. The recommended path is DownloadAndLoadCCSRModel, which auto-fetches the fp16 safetensors into ComfyUI/models/CCSR. The older CCSR_Model_Select node picks the original full-precision checkpoint from models/checkpoints - that's the backwards-compatibility route Kijai kept around.
Common issues
The README is refreshingly honest: this is a wrapper around the original PyTorch implementation, "not a proper native ComfyUI implementation, so not very efficient and there might be memory issues." The community hit exactly that - first runs are heavy on both RAM and VRAM, especially before the model is cached. Mitigate with the default tiled sampling, don't crank tile_size past 512 without a reason, and stick to the fp16 model.
Also temper expectations on speed. Forty-five diffusion steps per image is minutes, not seconds, on a consumer card - if the source is already clean, you're using the wrong tool entirely. And like every generative upscaler (SUPIR included), it can drift faces toward a plausible-but-not-yours version; give portraits their own pass if identity matters.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| ccsr_model | CCSRMODEL | — | |
| image | IMAGE | — | |
| resize_method | COMBO | lanczos | 5 options: nearest-exact, bilinear, area, bicubic, lanczos |
| scale_by | FLOAT | 1.000.01–20 | — |
| steps | INT | 453–4096 | — |
| t_max | FLOAT | 0.670–1 | — |
| t_min | FLOAT | 0.330–1 | — |
| sampling_method | COMBO | ccsr_tiled_mixdiff | 3 options: ccsr, ccsr_tiled_mixdiff, ccsr_tiled_vae_gaussian_weights |
| tile_size | INT | 5121–4096 | — |
| tile_stride | INT | 2561–4096 | — |
| vae_tile_size_encode | INT | 10242–4096 | — |
| vae_tile_size_decode | INT | 10242–4096 | — |
| color_fix_type | COMBO | adain | 3 options: none, adain, wavelet |
| keep_model_loaded | BOOLEAN | false | — |
| seed | INT | 1230–18446744073709550000 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| upscaled_image | IMAGE | — |