Nodes/ComfyUI-RH-Qwen-Image-2-1-diffusers/RH Qwen-Image 2.1 Diffusers
ComfyUI Node

RH Qwen-Image 2.1 Diffusers

One Node for All Four Qwen-Image 2.1 Modes — Transparency Included

By RH-RunningHub·Created 25 days ago·Updated 25 days ago· 2
RH Qwen-Image 2.1 Diffusers
  • image_1
  • image_2
  • image_3
  • image_4
  • image_5
  • image_6
  • image_7
  • image_8
  • image_9
  • image_10
  • images
  • alpha
◄prompt►
◄true_cfg_scale1.0►
◄num_inference_steps40►
◄output_resolution1024►
◄width0►
◄height0►
◄seed0►
◄use_kv_cachetrue►
◄negative_prompt►

What this node actually is

"RH" is RunningHub, a cloud ComfyUI host - and this node doesn't call it. No API key, nothing leaves your machine. It's a thin wrapper around the official diffusers QwenImage21Pipeline, with the three Qwen-Image 2.1 model classes vendored in. You're running the reference implementation, not a rewrite.

Why bother, when ComfyUI got single-file repacked weights within days? Ten-image multi-reference editing for a start, RGBA output with a real alpha channel, and the Qwen team's own sampling recipe instead of whatever your KSampler was set to.

Lineage, briefly: the 20B Qwen-Image family became the default open editing stack mostly on licensing - Apache 2.0 gave LoRA rights Flux Kontext's licence didn't - then 2.0 went API-only for months. 2.1 is the open-weights follow-up with a new recipe (Qwen3-VL encoder, single-stream block-causal transformer, AutoencoderKLQwenImage21 VAE), and it ships under the Qwen Research License, not Apache 2.0.

How it works

Your prompt goes through the official chat template into the Qwen3-VL encoder with any condition images - text and vision interleave into one sequence the transformer attends over. Denoising uses a FlowMatchEulerDiscreteScheduler with a dynamic time shift (0.5 at 256 tokens, 1.15 at 4096); no sampler dropdown, deliberately. The VAE reconstructs four channels, which the node splits for you.

Memory is the interesting part. All three heavy components register with ComfyUI ModelPatcher and stage on and off per stage, each with an activation reserve (~2 GiB for text, 3–8 GiB for the transformer). Text encoder and transformer are never resident at once, mirroring the upstream model_cpu_offload_seq. That's how a 24 GiB card runs a ~33 GB bf16 stack while your other checkpoints stay evictable, and the VAE decode tiles automatically above ~1.4 megapixels so 2K doesn't fall over. The log line reports the resolved dir and the mode; comfy-dynamic is the intended one.

The inputs that matter

prompt is required; image_1 … image_10 are the party trick. All empty = text-to-image, one image = instruction editing, several = official multi-reference composition. Order matters - later blocks attend to earlier ones, and a batched input contributes its frames in sequence. Beyond ten images it warns and truncates.

output_resolution behaves differently per mode: text-to-image builds a square that size, while image-conditioned mode treats it as an area budget and derives width/height from the last condition image's aspect ratio. Everything rounds to multiples of 32. For native 2K, set width and height explicitly - 2752×1536 is the official 16:9 pair, and 0 means auto.

true_cfg_scale defaults to 1.0 - guidance off, the official setting. Raising it alone does nothing: classifier-free guidance only kicks in when you also fill negative_prompt, and the driver warns you when you set the scale and leave it empty. Both on doubles per-step compute. use_kv_cache stays on; the prefix cache is valid because the transformer is block-causal, and off just recomputes everything every step.

Outputs: images is a three-channel IMAGE with any alpha composited over white, so previews and saves look normal; alpha is a MASK where 1 is opaque. Transparency is prompt-driven, not a toggle - use the official wording ("This is an RGBA image with transparency. A cute cartoon dragon sticker…"). Ordinary generations come back fully opaque there, so it's harmless to wire anyway.

Installing it

ComfyUI Manager, searching the pack title, or:

cd ComfyUI/custom_nodes
git clone https://github.com/RH-RunningHub/ComfyUI-RH-Qwen-Image-2-1-diffusers.git
cd ComfyUI-RH-Qwen-Image-2-1-diffusers
pip install -r requirements.txt

That pulls diffusers>=0.37, transformers>=4.57 for Qwen3-VL, accelerate and friends; torch is deliberately unpinned so it reuses your ComfyUI environment. The Qwen-Image 2.1 classes are vendored and registered into diffusers' namespace at load time, so you don't need an unreleased diffusers build.

Then the weights, ~33 GB bf16, in a strict diffusers layout:

cd ComfyUI/models
hf download Qwen/Qwen-Image-2.1 --local-dir diffusers/Qwen-Image-2.1

ModelScope has the same files. Keep the structure as shipped: model_index.json plus scheduler/, text_encoder/, processor/, transformer/, vae/. No tokenizer/ folder exists - the processor carries it. Non-standard location? Point RH_QWEN_IMAGE21_MODEL_DIR at the folder holding model_index.json.

Where it goes wrong

The node never appears. It's a V3 io.ComfyNode and only exports its mapping when comfy_api.latest.io imports cleanly. On older ComfyUI you get silence, not an error. Update ComfyUI.

"No diffusers pipeline directory found." The resolver scans one level under your diffusers roots for a folder named like Qwen-Image-2.1 holding a model_index.json, and the error prints what it scanned. Usually it's a half-finished download.

Out of VRAM anyway. There's no dtype widget, and that's deliberate: the pipeline loads as bfloat16 because handing transformers no usable dtype upcasts the weights to fp32 and no 24 GiB card survives that. If it still OOMs, drop width/height; the driver degrades to fallback staging on its own. Expect a slow first run - 33 GB off disk.

Something else broke after pip. Bumping diffusers or transformers in a shared env breaks packs you forgot you had. Check what pip wants to upgrade first.

CategoryRunningHub/Qwen-Image

Inputs (19)

NameTypeDefaultDescription
promptSTRINGPrompt guiding the generation. The pipeline wraps it in the official chat template before the Qwen3-VL encoder.
true_cfg_scaleFLOAT1.01–10Classifier-free guidance scale. Default 1.0 = no guidance (official recommendation). Needs a non-empty negative prompt to activate; doubles the compute per step when enabled.
num_inference_stepsINT404–100Denoising steps. Official recommendation is 40.
output_resolutionINT1024256–2048Target side length. Text-to-image derives a width/height around it; image-conditioned mode derives them from the last condition image's aspect ratio. Rounded to multiples of 32. Use width/height overrides for native-2K ratios (e.g. 2752x1536 16:9).
widthINT00–2752Explicit output width. 0 = derive from output_resolution / condition image aspect ratio. Official 2K 16:9 is 2752.
heightINT00–2752Explicit output height. 0 = derive from output_resolution / condition image aspect ratio. Official 2K 16:9 is 1536.
seedINT00–9223372036854776000Random seed. Same settings + same seed reproduce the image.
use_kv_cacheBOOLEANtrueCache text/condition keys and values after the first step (official default). Disabling it recomputes the whole prefix every step (slower).
image_1optIMAGECondition image slot 1/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
image_2optIMAGECondition image slot 2/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
image_3optIMAGECondition image slot 3/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
image_4optIMAGECondition image slot 4/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
image_5optIMAGECondition image slot 5/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
image_6optIMAGECondition image slot 6/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
image_7optIMAGECondition image slot 7/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
image_8optIMAGECondition image slot 8/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
image_9optIMAGECondition image slot 9/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
image_10optIMAGECondition image slot 10/10. Leave all empty for text-to-image; one image = single-image editing; up to ten = official multi-reference composition (a batched input contributes all its frames in order; later blocks attend to earlier ones, so order matters).
negative_promptoptSTRINGNegative prompt. Only takes effect together with true_cfg_scale > 1 (the model is trained to sample without guidance).

Outputs (2)

NameTypeDescription
imagesIMAGE—
alphaMASK—