Gen2 Apply QwenImage ControlNet (outdated)
Wrapping the model with VideoX control context
- model
- controlnet
- vae
- control_image
- inpaint_image
- mask
- model
The middle of the (outdated) QwenImage ControlNet chain: this node takes your diffusion model plus a loaded QwenImage ControlNet and a control image, prepares the VideoX-style control context, and outputs a wrapped model ready for this pack's sampler. It's the node that actually does the ControlNet wiring - "Apply" in the standard ComfyUI sense, but with QwenImage's specifics baked in. You don't use it outside this pack's pipeline; its output type is GEN2_WRAPPED_MODEL, which only the Gen2 QwenImage Control Sampler consumes.
How it works
The heavy lifting is building the control context. QwenImage's ControlNet conditions on a 132-feature context, and this node assembles it the way VideoX's QwenImageControlPipeline does:
- The control image is VAE-encoded (using the
GEN2_VAEfrom Gen2 Load QwenImage VAE) into latents, normalized with the VAE config's mean/std. - An inpaint mask (from your
maskinput) is processed into a mask latent; without a mask it defaults to all-ones. - An
inpaint_image(optional) is encoded to init latents; without one, zeros. - The three - control latents, mask latent, init latents - are concatenated (16 + 1 + 16 = 33 channels) and packed into sequence format.
That context, scaled by control_context_scale, gets attached to the wrapped transformer along with the ControlNet's control layers, so the sampler can inject the condition at the right attention points during denoising. If your image isn't a multiple of 16, it's rounded down first - feed it sizes that already divide by 16 to avoid surprises.
Inputs and the one dial that matters
model(MODEL) - your QwenImage diffusion model from a normal Load Diffusion Model.controlnet(GEN2_CONTROLNET) - from Gen2 Load QwenImage ControlNet.vae(GEN2_VAE) - from Gen2 Load QwenImage VAE.control_image(IMAGE) - the conditioning image.control_context_scale- default 0.8, range 0–2, step 0.05. This is the control strength, analogous to ControlNet weight elsewhere: higher = tighter adherence to the condition. The KB's controlnet essay is a good reminder that on modern DiT models the published weights run lower than the old SD-era 1.0, so 0.8 as a default is a sensible starting point.- Optional:
inpaint_image(IMAGE) andmask(MASK) - together they enable the inpaint mode, where the control context also carries the init image and mask.
Output: model (GEN2_WRAPPED_MODEL).
Installation
Needs the full QwenImage stack: VideoX-Fun as a custom node, diffusers, optionally ComfyUI-GGUF. Pack install via ComfyUI Manager (search "ComfyUI-gen2"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/petmycat/ComfyUI-gen2
cd ComfyUI-gen2
pip install -r requirements.txt
Common issues
- Output won't connect to a normal KSampler. Correct -
GEN2_WRAPPED_MODELonly feeds this pack's sampler. That's by design. - ControlNet has no visible effect. Check
control_context_scale(too low = near-zero conditioning) and that the ControlNet weights are actually QwenImage ones (see the loader's article). Also confirm the control image isn't being downscaled oddly by the 16-px rounding. - Missing VAE / VideoX errors. The Apply node needs the pack's
GEN2_VAE, not a stock ComfyUI VAE. Wrong VAE → wrong latents → garbage context, silently.
This is the node where the outdated pipeline earns its keep if you're chasing VideoX-exact reproducibility. Otherwise, native QwenImage ControlNet options in the wider ecosystem will be simpler to wire.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| controlnet | GEN2_CONTROLNET | — | |
| vae | GEN2_VAE | — | |
| control_image | IMAGE | — | |
| control_context_scale | FLOAT | 0.800–2 | — |
| inpaint_imageopt | IMAGE | — | |
| maskopt | MASK | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| model | GEN2_WRAPPED_MODEL | — |