Nodes/ComfyUI-MAINodes/H3 Drift Control (alpha)
ComfyUI Node

H3 Drift Control (alpha)

The node that stops chained segments from going mushy

By matlowai·Created 17 days ago·Updated about 16 hours ago· 112
H3 Drift Control (alpha)
  • model
  • latent
  • full_sigmas
  • model
  • report
prefix_frames39
matched_steps8
taper_steps4

Chain H3 clips together long enough and the joins stop being clean in a way that's hard to put your finger on. The culprit is subtle: a chained segment's carried video prefix is bit-clean - the exact same conditioning fed to the model every single step. One seam loves that. A chain doesn't. Repeated clean conditioning accumulates contrast and texture error, and the pack measured the join decaying from about 0.9 at the first join to about 0.65 by the second, across every variant tested. That's H3 Drift Control's problem to solve.

The fix is delightfully counterintuitive: add a little of the sampler's own noise back to the disposable carried prefix, at every model evaluation, tapering to exact at the seam end. The model stops treating the prefix as impossibly clean - because it isn't anymore - and the accumulated error stops compounding. The README's numbers: joins hold 0.85-0.89 through link 4 on the newer chain, where the pre-fix chain fell to the 0.65 class by its second join.

How it works and what it demands

It clones your model and installs a dynamic denoise-mask patch, sized from the latent you give it. The wiring is short but specific:

  • model - the same base H3 model your pass-1 guider would use.
  • latent - the H3 V2V Init output, which supplies the video shape. It must already carry the noise mask - wire H3 V2V Init first; this node rewrites that mask, it doesn't create one, and it will error if there's nothing to rewrite.
  • prefix_frames (39), matched_steps (8), taper_steps (4) - the recipe. 39 frames = 12 latent steps on the 17k+5 grid, and matched_steps + taper_steps must sum to exactly that. 8 + 4 is the field-validated combination; the node enforces the constraint rather than guessing.

Feed your guider the node's model output, and it handles the rest. Audio is deliberately untouched - the frozen per-tick audio prefix stays hard, so dialogue continuity isn't disturbed by the fix that's saving the video.

The two refusals (both are features)

The node refuses to stack on another dynamic denoise-mask patch - two of them can't share a model, and it will tell you so. And it does not support sigma-split samplers: the pack's own graphs run one SamplerCustomAdvanced per pass, and this node assumes that shape. If you're running a split schedule, restructure before you add this.

Honest status

The matched+taper recipe is still one recipe, not a swept space - it's been replicated across two chains and new seeds, but the "one right setting" hasn't been mapped. Treat it as a well-measured default rather than a tuned answer. And remember it's adapted from Contex-Loop's Drift-Control AV (GPL-3.0), with the credit lines in h3_drift.py spelling out what was ported and what wasn't.

Installing it

Pure Python:

cd ComfyUI/custom_nodes
git clone https://github.com/matlowai/ComfyUI-MAINodes

Restart, look under MAINodes/alpha. Example graphs want ComfyUI-KJNodes; the nodes don't. H3 weights are community-licensed (US, EU, UK, South Korea excluded). If you're chaining segments, this plus H3 Delta Color Carry are the two hygiene nodes worth knowing - drift for the conditioning, color carry for the VAE round trips, and they don't overlap.

CategoryMAINodes/alpha

Inputs (6)

NameTypeDefaultDescription
modelMODELthe base H3 model your pass-1 guider would use
latentLATENTH3 V2V Init output: supplies the video shape and must carry the static noise_mask
prefix_framesoptINT395–3600carried handle in pixel frames, on the 17k+5 grid; 39 -> 12 latent steps
matched_stepsoptINT80–400older prefix steps held at full matched noise
taper_stepsoptINT41–400steps ramping matched -> exact toward the seam end; matched+taper must equal the prefix's latent steps
full_sigmasoptSIGMASoptional: the complete schedule if the sampler only sees a partial one; usually leave unwired

Outputs (2)

NameTypeDescription
modelMODEL
reportSTRING