Nodes/ComfyUI-SpotEdit-Dev/SpotEdit Apply (Static)
ComfyUI Node

SpotEdit Apply (Static)

Make Qwen Image Edit keep its hands off the background

By llldmxy99·Created 6 months ago·Updated 6 months ago· 4
SpotEdit Apply (Static)
  • model
  • reference_latents
  • spotedit_mask
  • vae
  • MODEL

This is the node that does the actual SpotEdit trick. The SpotEdit Mask Generator figures out what changed; SpotEdit Apply (Static) takes your Qwen Image Edit model, the original image's latent, and that mask, and hands back a patched model that only computes the edit region. Two things follow: the background stops drifting between edits, and the sampling steps get cheaper the smaller your edit is.

It comes from llldmxy99/ComfyUI-SpotEdit-Dev, a small two-node pack that implements the SpotEdit paper (arXiv:2512.22323) - a training-free, region-aware editing framework for diffusion transformers - adapted hard to Qwen Image Edit. It's an obscure "Dev" snapshot: one commit, README in Chinese, no community footprint to speak of. If you've been fighting the drift that's baked into every whole-frame edit model, it's still worth a look.

How it works

Under the hood it uses ComfyUI's Model Patcher to swap in its own forward pass for Qwen's transformer, and it does two things:

  1. Token pruning. Qwen Image Edit is a 20B DiT; normally every image token runs through every transformer block even when you're changing 5% of the frame. SpotEdit prunes the background tokens before the blocks compute, so only the edit region actually pays for attention.
  2. KV cache injection. On the first step of the final pass it runs one full forward to build a Key/Value cache. From then on, the skipped background tokens get their cached K/V injected back into self-attention instead of being recomputed - with a cosine-schedule blend across the timestep. The background pixels effectively come from the source image, not from regeneration, which is why they hold still.

The "(Static)" in the name is the design story: the mask is computed once, outside the sampling loop. The older dynamic version recomputed the mask every step and kept hitting tensor-shape mismatches; moving it out of the loop is what made the pack usable and is what lets you actually preview and hand-tune the mask between the two passes.

Inputs and output

Three required inputs, all obvious once you see them:

  • model - your Qwen Image Edit checkpoint. No other model family works; the pack hooks comfy.ldm.qwen_image.model specifically.
  • reference_latents - VAE Encode of the original image. This is the KV source for the background.
  • spotedit_mask - the SPOTEDIT_MASK from SpotEdit Mask Generator.

There's also an optional vae input, but read the source and you'll find it's accepted and ignored - a leftover from the old API so your older graphs don't hard-fail. Don't wire it; it does nothing here.

The single output is a MODEL, and it goes into the second KSampler. That's it.

The two-pass workflow

SpotEdit only shines in the two-pass setup its README prescribes:

  • Pass 1: a normal KSampler, steps 0–4 of 20, return_with_leftover_noise on → coarse latent. This "pre-run" shows where the edit is heading.
  • Mask: SpotEdit Mask Generator compares that coarse latent to the original, you preview and tune the threshold.
  • Pass 2: wire this node's model and the coarse latent into the second KSampler, start_at_step 4, end_at_step 20, return_with_leftover_noise off, denoise 1.0.

Install and gotchas

cd ComfyUI/custom_nodes
git clone https://github.com/llldmxy99/ComfyUI-SpotEdit-Dev
cd ComfyUI-SpotEdit-Dev
pip install -r requirements.txt   # just einops

Restart ComfyUI (or install via ComfyUI Manager, searching "ComfyUI-SpotEdit-Dev"). Two compatibility notes straight from the README: FP8 models are fine, Nunchaku is not - if your checkpoint loads through Nunchaku, expect breakage. And if your mask length doesn't match the latent token count, the node prints a warning and silently disables pruning - you get normal Qwen editing, no crash, which is a decent failure mode for a Dev pack. If the background still moves after all this, the problem is upstream: your mask is too tight or too loose, so go tune threshold before you blame the node.

CategorySpotEdit

Inputs (4)

NameTypeDefaultDescription
modelMODEL
reference_latentsLATENT
spotedit_maskSPOTEDIT_MASK
vaeoptVAE

Outputs (1)

NameTypeDescription
MODELMODEL