⬡ Polyhedron Fast Upscale
The no-diffusion upscaler that keeps its mask in step
- image
- video
- upscale_model
- mask
- image
- video
- width
- height
- mask
There are three different jobs people call "upscaling", and the community's standing advice is to decide which one you have before you pick a tool. Fast Upscale is unambiguously the first job: more pixels, no new detail. Optional ESRGAN model in front, then a resize, then done. No diffusion refine, which is exactly why a 65-frame clip goes through it in seconds instead of minutes. It's the sibling of this pack's Power Upscale - if Power is the hi-res-fix-plus-tiles heavy lifter, Fast is the everyday path you reach for when you want size and clean edges, not invented texture.
The thing that sets it apart from a plain ImageScale is that it handles IMAGE, VIDEO and MASK together, and the mask follows the image instead of drifting out of register. That "mask follows image" bit is the one that most often goes wrong when you upscale an image and its mask with separate nodes - the mask comes back scaled by a slightly different rule and your inpainting target silently shifts. Here one geometry applies to both, crop and pad included, and a padded border is 0 because it was never part of the source.
The inputs that matter
size_mode-factorscales both sides byupscale_by(the Power Upscale way);exacthits a width × height, where a zero side keeps the aspect ratio.resize_method- the usual filters, plus two specials.lanczos (cpu)is a PIL path and only runs on CPU; ask it for a GPU device and it fails loudly instead of quietly ignoring you.nvidia_rtx_vsris NVIDIA's Maxine VideoSuperRes, which needs thenvvfxlibrary and an RTX card - when it's missing, the node says so plainly.divisible_by- snaps the result down to the divisor your samplers expect downstream. The Wan-friendly default is 16.per_batch- frames per sub-batch for the ESRGAN + resize step, so a long clip doesn't have to live in VRAM all at once.0means whole batch, which is how you find out what OOM stands for.keep_proportion- what to do when the aspect ratios don't match:stretch(distort),crop(cover the target, cut the overhang), orpad(fit inside, fill withpad_color).
Outputs are image, video, width, height, and mask. Note the video input/output: a wired VIDEO carries its audio and frame rate through into the VIDEO output, so this slots straight into a Wan frame pipeline without extra plumbing.
Installing it
It's part of the Polyhedron Suite pack - Manager search "Polyhedron Suite", or clone:
cd ComfyUI/custom_nodes
git clone https://github.com/PolyhedronAI/ComfyUI-PolyhedronLoRAStack.git
# restart ComfyUI
The nodes themselves have no hard dependencies. Video handling leans on PyAV (which recent ComfyUI builds ship) and OpenCV for thumbnails; if you're missing video features you can install them explicitly with pip install "polyhedron-lora-stack[media]".
Where people get burned
The most common trap is expecting Fast Upscale to add detail it was never designed to add - if your source is genuinely soft, ESRGAN + a resize will give you bigger soft. That's the "more detail" job, and it belongs to a diffusion refine or a model like SeedVR2. Also remember per_batch: a 129-frame clip through a 4× ESRGAN model in one batch is a multi-gigabyte tensor on a good day, and the OOM guard exists precisely because people kept hitting that.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| size_mode | COMBO | factor | factor: scale both sides by upscale_by (the Power Upscale way). exact: hit width x height (the Resize-v2 way; a zero side keeps the aspect). |
| upscale_by | FLOAT | 2.000.05–8 | factor mode: scale for both sides. |
| width | INT | 10240–8192 | exact mode: target width (0 = derive from height). |
| height | INT | 10240–8192 | exact mode: target height (0 = derive from width). |
| resize_method | COMBO | bicubic | bicubic/bilinear/area/nearest run on gpu OR cpu. lanczos is PIL = cpu-only. nvidia_rtx_vsr = Maxine VideoSuperRes (needs nvvfx + RTX; target snaps to /8). |
| device | COMBO | gpu | Where the torch resize runs. lanczos refuses gpu (fail loud); nvidia_rtx_vsr always runs on the GPU regardless. |
| divisible_by | INT | 161–64 | Snap the target DOWN to a multiple (Wan-friendly default 16). |
| per_batch | INT | 320–512 | Frames per sub-batch for ESRGAN + resize (VRAM guard). 0 = whole batch. nvidia_rtx_vsr is per-frame by SDK design. |
| mute_staging_logs | BOOLEAN | true | Silence ComfyUI's model staging INFO lines while this node runs (restored byte-exactly after). |
| keep_proportion | COMBO | stretch | What to do when the aspect ratios differ. stretch = distort to the target (the stretch behaviour). crop = cover the target and cut the overhang. pad = fit inside and fill the rest with pad_color. |
| crop_position | COMBO | center | Where the image sits - used for BOTH the crop cut and the pad placement. |
| pad_color | STRING | 0, 0, 0 | Fill colour for pad, as R, G, B (0-255). Unparseable = black (fail soft). |
| imageopt | IMAGE | Frame input [N,H,W,C]. Wire EXACTLY one of image/video. | |
| videoopt | VIDEO | Native VIDEO input; audio + frame rate ride through into the VIDEO output. Wire EXACTLY one of image/video. | |
| upscale_modelopt | UPSCALE_MODEL | Optional ESRGAN pass BEFORE the resize (core spandrel path, sub-batched). | |
| maskopt | MASK | Optional mask - resized with the SAME geometry (crop/pad included). A padded border is 0: it was never part of the source. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| video | VIDEO | — |
| width | INT | — |
| height | INT | — |
| mask | MASK | — |