Nodes/ComfyUI_zura_nodes/Zura · Apply Encoded H3 Control
ComfyUI Node

Zura · Apply Encoded H3 Control

Wiring MiniMax H3's ControlNet the way the sampler expects

By ZURAVFX·Created about a month ago·Updated a day ago· 2
Zura · Apply Encoded H3 Control
  • model
  • model_patch
  • prepared_control
  • MODEL
◄strength1.00►
◄start_percent0.00►
◄end_percent1.00►

ControlNet on a video DiT isn't a plugin you bolt on; it's a model patch the sampler has to know about before it starts denoising. This node is the last step of a three-node chain in this pack that prepares H3's control payload by hand, and it's the one that decides how hard the control pushes and when it lets go.

What it is

The H3 control path in this pack is deliberately split into three visible nodes rather than one magic box:

  1. Zura · Prepare H3 Control Pixels - fits your source and depth videos to the exact raster and frame count the target latent implies, and produces the visibility mask.
  2. Stock VAEEncode ×2 - you encode fitted_control and masked_source yourself with the H3 video VAE. The pack is explicit that these are stock nodes on purpose.
  3. Zura · Pack H3 Control Latents - concatenates the two encodes plus visibility into a 49-channel latent.

Then this node: ZuraH3ApplyEncodedControl takes that packed latent and a loaded H3 ControlNet model patch, and returns a patched MODEL you sample with normally.

How it works

Under the hood it subclasses ComfyUI's native MiniMaxH3FunControlPatch from comfy_extras.nodes_minimax_h3 - so this is the real H3 control path, not a reimplementation, with the Zura-specific job of holding a pre-computed control latent and re-cloning it whenever the native code has wiped its working copy. That re-clone in prepare_control_latent is the reason the node exists rather than you just using the native one: the prepared tensor is the expensive artifact, and the node refuses to let native cleanup mutate it.

Two behaviours worth knowing:

  • strength of 0 short-circuits and returns the model untouched. That sounds trivial, but it's the cleanest way to A/B a control pass: leave the whole chain in the graph, set strength to 0, and you get the identical unconditional sampler with no wasted work.
  • start_percent / end_percent convert to sigma bounds via the model's own sampling object. So they're relative to your schedule, and the classic ControlNet advice applies unchanged: release the condition once composition has formed instead of holding it through the whole sample. A control that's too strong at the end is where you get the tell-tale "burned into the geometry" look.

The node also validates that the prepared control is float32 and that the packed tensor matches the sampler's target shape - if you packed at the wrong resolution you get a clear error at sampling time instead of noisy garbage.

Inputs and outputs

  • model - your loaded H3 model.
  • model_patch - the loaded H3 fun-control union patch.
  • prepared_control - the 49-channel latent from Pack H3 Control Latents.
  • strength - default 1.0, range 0–10. Same nominal scale as ControlNet weights; on H3 the useful range is narrower than the slider suggests.
  • start_percent / end_percent - default 0.0 / 1.0.
  • MODEL - the patched model, out to your guider.

Install

Nothing special here: install the pack once. Manager → Zura Nodes, or:

cd ComfyUI/custom_nodes && git clone https://github.com/ZURAVFX/ComfyUI_zura_nodes
pip install -r ComfyUI_zura_nodes/requirements.txt

The control model is a separate download - minimax_h3_fun_controlnet_union_2.0_pruned_int8_convrot.safetensors from Comfy-Org's MiniMax-H3 repo, into ComfyUI/models/model_patches/. Plus the H3 base weights, text encoder and both VAEs. And accept the H3 community licence before you download anything; it's territory-restricted.

Common issues

"Prepared H3 control must use float32." You round-tripped the packed latent through something that changed its dtype. Pack and apply in the same pass.

"Prepared H3 control does not match this sampler's target video shape; prepare it again." The target latent changed between preparing and sampling - usually a resolution widget. The control raster is derived from the target latent, so any change means re-running the whole prepare chain.

"Use the actual loaded native H3 ControlNet MODEL_PATCH." The model_patch slot wants the patch object, not the patched MODEL. ZuraH3PrepareControlPixels and this node both take model_patch for exactly this reason; feeding them the output of this node won't typecheck.

Strength feels like a cliff. It is. 0.3 is a suggestion, 1.0 is a mandate, and past 2 you'll start seeing the depth guide bleed into the output as literal structure. Sweep it once on a five-second clip and write the number down.

CategoryZura/Artist Studio/Data

Inputs (6)

NameTypeDefaultDescription
modelMODEL—
model_patchMODEL_PATCH—
prepared_controlLATENT—
strengthFLOAT1.000–10—
start_percentFLOAT0.000–1—
end_percentFLOAT1.000–1—

Outputs (1)

NameTypeDescription
MODELMODEL—