Nodes/toobusy/2BZ SeedVR2 Tile Restore
ComfyUI Node

2BZ SeedVR2 Tile Restore

SeedVR2 on an 18-Megapixel Sheet Without the Out-of-Memory

By nicekriss·Created about a year ago·Updated a day ago· 21
2BZ SeedVR2 Tile Restore
  • model
  • vae
  • image
  • restored
  • info
◄tile_megapixels2.00►
◄upscale_small_to3.0►
◄tile_overlap128►
◄seed42►
◄color_correctionlab►

What it's for

SeedVR2 is the incumbent for "more detail that was never there". The KB puts it at roughly one upscaling thread in three, holding steady through 2026, Apache 2.0, and it's stopped being a topic - people just run it at the end of the graph.

Its problem is size: feed it a whole sheet and you blow VRAM. And the obvious workaround, a tiled upscaler like Ultimate SD Upscale, cannot drive it - the core SeedVR2 nodes condition on the encoded input itself (SeedVR2Conditioning takes the latent as its condition), while generic tilers hand one shared conditioning to every tile. Fine for a ControlNet-Tile upscaler, wrong here.

So 2BZ SeedVR2 Tile Restore runs the whole core chain - preprocess, encode, condition, one-step sample, decode, post-process - once per tile, with that tile's own conditioning, feathers the overlaps and returns your input size. A photo or an 18 MP sheet, same node, no prompt.

How it works

Two things happen before any tiling.

Scale. An image smaller than upscale_small_to MP is lanczos-enlarged (capped at 4×) before restoring, then shrunk back with antialiased bicubic. That sounds backwards and isn't: face texture keeps improving to about 2–3 MP and flattens above (×1.52 of the original high-pass at 1 MP, ×1.97 at 3), which is why the knob defaults to 3. 0 disables it.

Tiles. The node picks the tile count from the megapixel budget, then the smallest tile that covers the image with at least tile_overlap shared pixels between neighbours, rounded to a multiple of 16. If the image already fits the budget, it's one tile.

Then per tile it calls the core chain - SeedVR2Preprocess → VAEEncodeTiled → SeedVR2Conditioning → a 1-step KSampler (cfg 1.0, euler/simple) → VAEDecodeTiled → SeedVR2PostProcessing - and feathers the result into an accumulator with linear ramps on any edge that has a neighbour, leaving image borders hard. Weights are normalised so overlaps don't darken or double.

Inputs and outputs that matter

  • model - SeedVR2 3B or 7B, loaded with Load Diffusion Model.
  • vae - the SeedVR2 VAE, not a normal one.
  • image - anything; the loop handles multiple frames.
  • tile_megapixels (default 2) - the VRAM knob. Author's guide for the 3B model: 8 GB → 1, 12 GB → 1.5–2, 16 GB → 2–3, 24 GB → 3–4. Lower it and you get more tiles: roughly the same quality, slightly slower.
  • upscale_small_to (default 3) - the quality knob above.
  • tile_overlap (default 128) - pixels shared between neighbours and feathered. Raise it if you can see a grid.
  • seed (default 42) - keep it fixed while tuning.
  • color_correction (default lab) - per-tile colour match back to the input, lab being the most faithful; wavelet, adain and none are the rest.

Outputs are restored and info. info names the input size, working size and tile grid - wire it to Preview Any and read it; it's the fastest check that your VRAM knob did what you thought.

The output is at the input size. This is a restore, not an upscale. The intended next step is 2BZ Retouch Blend (skin-aware) (or Frequency Detail Transfer), which keeps the original's shapes and uses only this image's fine texture.

Install

In the toobusy pack as of v0.5.4.

cd ComfyUI/custom_nodes
git clone https://github.com/nicekriss/toobusy.git toobusy

Manager works if you search the pack title, but the registry copy can lag the repo - a lagging install just looks like nodes that never appear. Use Install via Git URL with https://github.com/nicekriss/toobusy, or clone, then restart.

Two model files, both Comfy-Org on Hugging Face:

| file | goes in | | --- | --- | | seedvr2_3b_int8_convrot.safetensors | ComfyUI/models/diffusion_models/ | | seedvr2_ema_vae_fp16.safetensors | ComfyUI/models/vae/ |

SeedVR2's preprocess/condition/post-process nodes are ComfyUI core, so you need a reasonably current build. No extra pip packages.

Measured, and where people get tripped up

On an RTX 3090 with the 3B int8 model: a 2 MP photo takes about 24 seconds; an 18 MP sheet about 79 seconds across 15 tiles. Peak VRAM was around 7 GB regardless of image size - which is the whole point. Bigger input buys tiles, not memory.

Missing core nodes give you an explicit error naming the node (Required ComfyUI node 'SeedVR2Preprocess' is not available...). That's an update-ComfyUI problem, not a toobusy one.

The precision trap is real, and it isn't this node's. The corpus's most-quoted SeedVR2 warning is that the GGUF route messed with skin and one FP8 report added tiling grid artifacts, against a clean FP16 run. The pack's shipped path is Comfy-Org's int8-convrot model plus the FP16 VAE - stick to those, and if the 3B model errors on your build, switch to the 7B int8 version rather than a lower-precision quant.

A visible grid means tile_overlap is too small for your content, not that the node is broken - bump it and the edges go.

Categorytoobusy/retouch

Inputs (8)

NameTypeDefaultDescription
modelMODELSeedVR2 3B/7B (Load Diffusion Model).
vaeVAESeedVR2 VAE (seedvr2_ema_vae).
imageIMAGE—
tile_megapixelsFLOAT2.000.5–16VRAM knob: how much SeedVR2 processes at once. Bigger images are split into tiles of this size. Lower it if you run out of memory. Rough guide (3B int8): 8 GB -> 1, 12 GB -> 1.5-2, 16 GB -> 2-3, 24 GB -> 3-4.
upscale_small_toFLOAT3.00–16Quality knob (MP): images smaller than this are enlarged to it before restoring, then returned at their own size. Face texture saturates around 2-3 MP. 0 = never enlarge.
tile_overlapINT12832–512Pixels shared by neighbouring tiles and feathered together.
seedINT420–18446744073709550000—
color_correctionCOMBOlabMatch each tile's colours to the input (lab is the most faithful).

Outputs (2)

NameTypeDescription
restoredIMAGE—
infoSTRING—