ComfyUI Node

Reference Latent+

Stop dragging the whole photo in — Reference Latent+ lets you take just the face

By shootthesound·Created 4 months ago·Updated 3 months ago· 34
Reference Latent+
  • conditioning
  • vae
  • image_1
  • image_2
  • image_3
  • image_4
  • mask_1
  • mask_2
  • mask_3
  • mask_4
  • conditioning
max_megapixels1.0
mask_fill_modepixel_grey
image1_strength0.85
image1_facefalse
image1_hairfalse
image1_bodyfalse
image1_clothesfalse
image1_backgroundfalse
image1_ignore_areanone
image1_feather0
image1_grow0
image1_start_percent0.000
image1_end_percent1.000
image2_strength0.85
image2_facefalse
image2_hairfalse
image2_bodyfalse
image2_clothesfalse
image2_backgroundfalse
image2_ignore_areanone
image2_feather0
image2_grow0
image2_start_percent0.000
image2_end_percent1.000
image3_strength0.85
image3_facefalse
image3_hairfalse
image3_bodyfalse
image3_clothesfalse
image3_backgroundfalse
image3_ignore_areanone
image3_feather0
image3_grow0
image3_start_percent0.000
image3_end_percent1.000
image4_strength0.85
image4_facefalse
image4_hairfalse
image4_bodyfalse
image4_clothesfalse
image4_backgroundfalse
image4_ignore_areanone
image4_feather0
image4_grow0
image4_start_percent0.000
image4_end_percent1.000

Stock ComfyUI has a ReferenceLatent node, and it's about as thin as a node gets: drop a latent in, it tacks it onto your conditioning under the reference_latents key, done. Binary. Whole image, every step, no strength knob. The moment you want "that character's face but not their pose, background, and crop," it's useless - you're back to LoRA training or a ControlNet that fights your composition.

Reference Latent+ is the version the stock node never grew up to be. It's a drop-in replacement by shootthesound (Peter Neill, the same person behind the Fizgig Klein LoRA workbench and the LoRA block analyzer - a known quantity on r/StableDiffusion) that gives you per-image strength, per-image timestep gating, auto-masks, and up to four references in a single node. If you're doing reference-based character or style transfer on Flux, Flux2/Klein, Wan, Hunyuan, Qwen-Image, Z-Image, or Lumina2, this is the node you reach for.

How it works

Same trick as stock ReferenceLatent, one layer deeper. The node VAE-encodes your images internally (yes, there's a vae input, so no more hand-wiring LoadImage → VAE Encode → ReferenceLatent chains) and attaches them to your conditioning's reference_latents key, which those models read directly. Two things make it smart:

  • Per-image timestep gating. Each ref gets its own start_percent / end_percent. The node partitions the denoising schedule so every timestep has exactly one set of active refs - no double-counting. This is the killer feature on Flux2/Klein: style and identity live in the clean, late timesteps, so gating a ref to 0.6–1.0 lets your prompt's composition run free early and only adds the ref's look at the end.
  • Megapixel cap. max_megapixels (default 1.0) downscales each ref by area before encoding, aspect preserved, never upscaled. Reference latents cost quadratic attention, so a 2K ref photo will wreck your generation speed; capping keeps it proportional to a 1024² render.

The inputs that matter

Only four required: conditioning, vae, image_1, plus the max_megapixels and mask_fill_mode globals. Connect image_1 and an image_2 slot appears; connect that and image_3 shows up - progressive disclosure, up to four refs.

  • image1_strength - signed, -5.0 to 50.0, default 0.85. 1.0 equals stock behavior; 0 bypasses that image entirely; negative is the experimental "anti-reference" that pushes the model away from that ref.
  • image1_face / hair / body / clothes / background - MediaPipe auto-mask regions. Tick "face" and only the face gets encoded as a ref. No more background leaking into your output. grow, feather, and ignore_area refine the mask.
  • image1_start_percent / end_percent - that timestep gate. Defaults to 0→1 (always on).

Output is a single conditioning tensor - wire it into your KSampler's positive input and you're done.

Installing it

Via ComfyUI Manager, search "Reference Latent+" (pack title comfyui-ReferenceLatentPlus). Or the manual way:

cd ComfyUI/custom_nodes
git clone https://github.com/shootthesound/comfyui-ReferenceLatentPlus

Then restart ComfyUI. It appears under advanced/conditioning > Reference Latent+. The MediaPipe auto-mask feature is optional: pip install mediapipe into your ComfyUI venv and the selfie_multiclass model auto-downloads to models/mediapipe/ on first use. There's a ready Klein 9B example workflow in examples/.

Where people get burned

  • No MediaPipe = silent no-op. Ticking a region does nothing if the package isn't installed - no error, the ref just isn't masked. Explicit mask_N wiring still works regardless.
  • latent_zero and latent_noise are off-distribution. No model trained on masked reference latents; at high mask coverage behavior is exploratory. pixel_grey (the default) stays in-distribution - treat it as the safe option.
  • Negative strength is experimental. Great for "make it not look like this," unpredictable otherwise.
  • reference_latents_method is Flux-only. Other models ignore it harmlessly, so don't sweat the key not mattering on Wan.

The masking-of-ref-latents idea is genuinely novel - nobody else in the ecosystem does it, which means there's no community-validated baseline. Test the defaults on your own use case, then fiddle. That's the whole point of the node.

Categoryadvanced/conditioning

Inputs (56)

NameTypeDefaultDescription
conditioningCONDITIONING
vaeVAE
image_1IMAGE
max_megapixelsFLOAT1.00.1–4Caps each ref image by area. Downscales only — small images pass through. Lower = faster (fewer attention tokens).
mask_fill_modeCOMBOpixel_greyHow masked-out regions are neutralised before the model attends to the ref. pixel_grey: replace masked pixels with 0.5 grey before VAE encode. In-distribution; the masked latent has soft uniform signal. latent_zero: encode full image, then zero the latent at masked positions. Constant K/V at those tokens (= layer bias) so attention distributes uniformly over them. Spiritual equivalent of 'transparent'. latent_noise: same as latent_zero but fills with Gaussian noise instead of zeros. Different attention shape — random K/V means no Q matches strongly, model weakly ignores those tokens.
image_2optIMAGE
image_3optIMAGE
image_4optIMAGE
mask_1optMASKOptional explicit mask for image 1. Overrides this image's auto-mask config below.
mask_2optMASKOptional explicit mask for image 2 (overrides auto-mask).
mask_3optMASKOptional explicit mask for image 3 (overrides auto-mask).
mask_4optMASKOptional explicit mask for image 4 (overrides auto-mask).
image1_strengthoptFLOAT0.85-5–50Per-image strength (signed). 1.0 = stock ReferenceLatent strength. 0.85 = empirical sweet spot. 0 = bypass this image entirely. Negative = anti-reference (model pulled away from this ref's features).
image1_faceoptBOOLEANfalseFace skin
image1_hairoptBOOLEANfalseHair
image1_bodyoptBOOLEANfalseBody skin
image1_clothesoptBOOLEANfalseClothes
image1_backgroundoptBOOLEANfalseBackground (tick to use the background only — handy for environment refs)
image1_ignore_areaoptCOMBOnoneExclude a side strip from the auto-mask. Useful when multiple subjects are in frame.
image1_featheroptINT00–200Soften mask edges by N pixels (0 = sharp). 10-30 is usually enough.
image1_growoptINT0-200–200Grow (>0) or shrink (<0) the mask by N pixels. Useful for tucking or extending the masked area beyond what MediaPipe detected.
image1_start_percentoptFLOAT0.0000–1Fraction of denoising at which this image's ref starts applying. 0 = active from the very first step.
image1_end_percentoptFLOAT1.0000–1Fraction of denoising at which this image's ref stops applying. 1 = active through the last step. For Flux2/Klein 9B, style/identity signal concentrates at the clean end of denoising — try start=0.6, end=1.0 to apply the ref only at the late (clean) timesteps and let the noisy/early timesteps freely follow your prompt's composition.
image2_strengthoptFLOAT0.85-5–50Per-image strength (signed). 1.0 = stock ReferenceLatent strength. 0.85 = empirical sweet spot. 0 = bypass this image entirely. Negative = anti-reference (model pulled away from this ref's features).
image2_faceoptBOOLEANfalseFace skin
image2_hairoptBOOLEANfalseHair
image2_bodyoptBOOLEANfalseBody skin
image2_clothesoptBOOLEANfalseClothes
image2_backgroundoptBOOLEANfalseBackground (tick to use the background only — handy for environment refs)
image2_ignore_areaoptCOMBOnoneExclude a side strip from the auto-mask. Useful when multiple subjects are in frame.
image2_featheroptINT00–200Soften mask edges by N pixels (0 = sharp). 10-30 is usually enough.
image2_growoptINT0-200–200Grow (>0) or shrink (<0) the mask by N pixels. Useful for tucking or extending the masked area beyond what MediaPipe detected.
image2_start_percentoptFLOAT0.0000–1Fraction of denoising at which this image's ref starts applying. 0 = active from the very first step.
image2_end_percentoptFLOAT1.0000–1Fraction of denoising at which this image's ref stops applying. 1 = active through the last step. For Flux2/Klein 9B, style/identity signal concentrates at the clean end of denoising — try start=0.6, end=1.0 to apply the ref only at the late (clean) timesteps and let the noisy/early timesteps freely follow your prompt's composition.
image3_strengthoptFLOAT0.85-5–50Per-image strength (signed). 1.0 = stock ReferenceLatent strength. 0.85 = empirical sweet spot. 0 = bypass this image entirely. Negative = anti-reference (model pulled away from this ref's features).
image3_faceoptBOOLEANfalseFace skin
image3_hairoptBOOLEANfalseHair
image3_bodyoptBOOLEANfalseBody skin
image3_clothesoptBOOLEANfalseClothes
image3_backgroundoptBOOLEANfalseBackground (tick to use the background only — handy for environment refs)
image3_ignore_areaoptCOMBOnoneExclude a side strip from the auto-mask. Useful when multiple subjects are in frame.
image3_featheroptINT00–200Soften mask edges by N pixels (0 = sharp). 10-30 is usually enough.
image3_growoptINT0-200–200Grow (>0) or shrink (<0) the mask by N pixels. Useful for tucking or extending the masked area beyond what MediaPipe detected.
image3_start_percentoptFLOAT0.0000–1Fraction of denoising at which this image's ref starts applying. 0 = active from the very first step.
image3_end_percentoptFLOAT1.0000–1Fraction of denoising at which this image's ref stops applying. 1 = active through the last step. For Flux2/Klein 9B, style/identity signal concentrates at the clean end of denoising — try start=0.6, end=1.0 to apply the ref only at the late (clean) timesteps and let the noisy/early timesteps freely follow your prompt's composition.
image4_strengthoptFLOAT0.85-5–50Per-image strength (signed). 1.0 = stock ReferenceLatent strength. 0.85 = empirical sweet spot. 0 = bypass this image entirely. Negative = anti-reference (model pulled away from this ref's features).
image4_faceoptBOOLEANfalseFace skin
image4_hairoptBOOLEANfalseHair
image4_bodyoptBOOLEANfalseBody skin
image4_clothesoptBOOLEANfalseClothes
image4_backgroundoptBOOLEANfalseBackground (tick to use the background only — handy for environment refs)
image4_ignore_areaoptCOMBOnoneExclude a side strip from the auto-mask. Useful when multiple subjects are in frame.
image4_featheroptINT00–200Soften mask edges by N pixels (0 = sharp). 10-30 is usually enough.
image4_growoptINT0-200–200Grow (>0) or shrink (<0) the mask by N pixels. Useful for tucking or extending the masked area beyond what MediaPipe detected.
image4_start_percentoptFLOAT0.0000–1Fraction of denoising at which this image's ref starts applying. 0 = active from the very first step.
image4_end_percentoptFLOAT1.0000–1Fraction of denoising at which this image's ref stops applying. 1 = active through the last step. For Flux2/Klein 9B, style/identity signal concentrates at the clean end of denoising — try start=0.6, end=1.0 to apply the ref only at the late (clean) timesteps and let the noisy/early timesteps freely follow your prompt's composition.

Outputs (1)

NameTypeDescription
conditioningCONDITIONING