Nodes/PixRestore for ComfyUI/PixRestore Loader
ComfyUI Node

PixRestore Loader

It refuses to guess, and that's the point

By hiroki-abe-58·Created 27 days ago·Updated 27 days ago· 9
PixRestore Loader
    • model
    • report
    ◄model▾►
    ◄verify_hashestrue►

    If you've loaded a checkpoint before, this node will feel slightly wrong. There's no CheckpointLoaderSimple dropdown full of .safetensors files, no "download the model for me" button, and the output isn't a MODEL you can plug into a KSampler. PixRestore Loader loads one very specific thing - the released PixRestore-S one-step restoration model plus its DINOv2 ViT-S/14 feature encoder - and it checks the files against published SHA-256 hashes before it does. It is the front half of a three-node pack for repairing degraded 512×512 images.

    What it actually loads

    PixRestore-S is a pixel-diffusion transformer: it denoises directly in pixel space with no VAE, conditioned on DINOv2 features, in a single denoiser call. That's a different job from the two large upscaling categories you normally meet - the ESRGAN-style interpolators that add pixels and invent nothing, and the generative detail-adders like SeedVR2. This is the small research-model corner of the second category: it doesn't make the image bigger, it tries to un-break it.

    The loader's job is unglamorous and deliberate: get the model, the config and the encoder into VRAM, from files it can prove are the released ones.

    The two inputs, and the two outputs

    model is a combo, and the list is built by scanning <ComfyUI>/models/pixrestore for sub-folders that contain both config.json and clean_weights/ema_model.safetensors. The author's own tooltip says exactly that: "a folder in models/pixrestore with config.json and clean_weights/". A folder missing either file silently doesn't appear - this is the number one "why is my dropdown empty" cause. The folder is registered through ComfyUI's model-path system, so an extra_model_paths.yaml entry for pixrestore can point at a second drive.

    verify_hashes (default on) hashes config.json, ema_model.safetensors and dinov2_vits14_pretrain.pth and compares them to the digests baked into the pack's pins.py. Leave it on. You're hashing 0.22 GB once per load - nothing next to the load itself - and the failure it catches is "your file is truncated or someone re-saved it", which otherwise surfaces as a much stupider error later.

    Outputs are model (PIXRESTORE_MODEL) and report (STRING). The model output only goes into PixRestore Restore - it is not a MODEL, so no KSampler will take it. The report is a JSON blob and it's genuinely useful: the pinned commit hashes, load and import timings, parameter counts for both networks, the SHA-256s it just verified, and a torch_compile_removed flag that should read true. Wire it into a PreviewAny and you have a receipt for what you're running.

    Under the hood

    The pack ships no upstream code. tools/setup_pixrestore.py downloads the PixRestore repo at commit 909ca06, DINOv2 at 7764ea0 and the PixRestore-S weights from Hugging Face at revision a5fe719 into models/pixrestore/upstream, checking every digest. At load time the loader verifies all of those files again and imports them as top-level modules named pixrestore and dinov2. That's the sharp edge: if any other custom node in your install already imported a different module with one of those names, this pack refuses to load rather than mix code.

    Two details worth knowing because they're the sort of thing that makes a pack mysteriously broken on Windows. Upstream decorates several DiT functions with @torch.compile, which wants Triton; the pack swaps those wrappers for the undecorated functions, i.e. the equivalent of running the official script with TORCHDYNAMO_DISABLE=1. And it clears DINOv2's xFormers flag so the attention path matches a reference environment without xFormers. Both are why the pipeline runs on a stock Windows box instead of complaining about a missing compiler.

    It also needs a CUDA GPU - the loader raises immediately on a machine without CUDA, and there's no CPU or Apple MPS path in this version. Peak VRAM the node allocates during a restore is about 342 MiB, so "GPU required" here is about capability, not size. One model stays resident at a time; loading a different folder frees the previous one.

    Note for the curious: this pack is written against ComfyUI's newer io.ComfyNode authoring API, so there's no NODE_CLASS_MAPPINGS in it. That reads as "new", not "broken".

    Install

    cd ComfyUI/custom_nodes
    git clone https://github.com/hiroki-abe-58/ComfyUI-PixRestore
    python -m pip install -r ComfyUI-PixRestore/requirements.txt   # timm>=0.9,<1.1
    python ComfyUI-PixRestore/tools/setup_pixrestore.py --models-dir ../models
    

    Then restart ComfyUI. timm is the only Python dependency, which is refreshing. ComfyUI Manager can install the pack itself, but Manager will not download the weights - that second and third command is the whole model install, and it lands you models/pixrestore/pixrestore-s/ plus the DINOv2 checkpoint and the pinned upstream source. About 0.22 GB total. The nodes never fetch anything at runtime, which is why it works offline afterwards.

    When it goes wrong

    • Empty model dropdown. A folder in models/pixrestore exists but lacks one of the two required files. ls models/pixrestore/*/config.json will tell you in one line.
    • not the released files: [...] - a digest mismatched. Re-run setup_pixrestore.py; it re-downloads only what fails. Don't just switch verify_hashes off to get past this.
    • another Python module named 'pixrestore' is already loaded (...) - two packs are fighting over the same module name. Restart ComfyUI; if it comes back, disable the other pack.
    • config.json differs from the released PixRestore-S config - you pointed it at a B / L / XL config. Only S is supported here.
    • ComfyUI's "Unload Models" / free-memory button doesn't touch it. The model isn't in ComfyUI's model manager at all. That's what PixRestore Unload exists for.
    Categoryloaders/pixrestore

    Inputs (2)

    NameTypeDefaultDescription
    modelCOMBOA folder in models/pixrestore with config.json and clean_weights/
    verify_hashesBOOLEANtrueSHA-256 of config.json, the weights and the DINOv2 checkpoint, compared with the released files

    Outputs (2)

    NameTypeDescription
    modelPIXRESTORE_MODEL—
    reportSTRING—