CoachBate H3 Per-Subject Denoise
One denoise value, a subject walking toward the camera. This node splits the difference.
- model
- av_latent
- transform
- av_latent
- report
- model
The problem with one number
A sampler builds one sigma schedule for a whole clip, so every frame gets the same denoise. That is fine until the subject moves: a shot where someone walks from the back of the room to the lens has tiny frames that need a strong pass (there's no detail to preserve, so let H3 synthesise a face) and large frames that need a gentle one (the detail is real, don't rewrite it). Any single value you pick is wrong for half the clip.
CoachBate H3 Per-Subject Denoise scales denoise strength per frame, inversely to how big the
subject is. ComfyUI's noise_mask scales denoising per latent position, so varying it along the
temporal axis gets you per-frame strength out of a single sampling pass. Granularity is one latent
frame - 17 pixel frames per 5 latents, so roughly every 3.4 frames.
The part that isn't just a mask
A mask on its own doesn't work here, and the reason is specific to H3. When H3 holds a region, it hands it back almost clean (0.999 clean + 0.001 noise) and relies on per-token timesteps to tell the model that region sits at the conditioning timestep. Suppress that telling and the injected latent is far cleaner than the step it lands in, while the sampler keeps mixing it in on every step - the disagreement grows and you get a repeating grid at latent-cell size. A mask reaching the result twice, in other words: once through the sampler, once through the timestep shift.
So this node patches the model twice. It keeps its video mask out of H3's per-token timesteps (the audio entry is passed through untouched, which is what MiniMaxH3NativeAudioLock needs for lipsync), and it re-noises the held frames to the sigma the sampler is actually on, so the latent is simply true for the step it's on and nothing needs declaring.
That's why model is a required input. Pass the model in, take the returned one out, and hand
that to the guider - wire the original past it and you've done nothing at all.
Inputs and outputs
Required: model, av_latent, transform (straight from Track + Crop), plus the tuning set.
denoise_multiplier_small_subject/denoise_multiplier_large_subject- both default 1.0, and they are multipliers on the denoise you set on BasicScheduler, not denoise values. At 1.0 those frames get your full denoise. At 0.8 they get 80% of it. Note the trap the tooltip states outright: below 1.0, no frame in the clip receives the full denoise you set, so the whole clip comes out gentler. Defaults are flat on purpose, sodenoiseon the scheduler keeps meaning what it says.scale_mode-absolute_px(the default) uses real subject size in source pixels viasubject_px_small(default 30) andsubject_px_large(default 120). That's the safe one across a batch: a video that never has a small subject gets the baseline throughout.relative_to_clipnormalises to this clip's own min/max, so its smallest subject always gets the full boost - useful for tuning one video to its extremes, wrong for a batch.gamma- curve on the interpolation. Above 1 keeps strength high until the subject is genuinely large; below 1 drops it off early.smooth_frames(default 9) - smooths the strength curve over time. An abrupt denoise change between neighbouring frames shows up as a texture pop, so this wants to be generous rather than precise.
Outputs: av_latent, report, and model.
Where it goes in the chain
After MiniMaxH3NativeAudioLock - this node preserves that node's audio-side zeros, which are
what keep the audio clean. It sits between CoachBate H3 Inject Video Latent and the sampler, and
its model output goes to the guider while its av_latent goes to the sampler.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/CoachBate/ComfyUI-CoachBate.git
or ComfyUI Manager, search "CoachBate", then restart. It appears under CoachBate / H3 Subject
Refine. No pip dependencies of its own, but the refine chain as a whole needs
ultralytics (for the tracking) and the Video Helper Suite.
Where people get burned
- Nothing changed. The returned
modelisn't reaching the guider. It's the single most common mistake with this node, because the input model still looks perfectly valid. - The whole clip got softer after lowering the small-subject multiplier. Expected - remember it scales your scheduler denoise for every frame, and the small end only sets the ceiling.
- A visible texture change mid-shot. Raise
smooth_frames; the strength curve is too abrupt for the frames to blend.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | The H3 model, on its way to the sampler. Required: making a per-frame mask behave takes two changes to the MODEL rather than to the latent. This node's video mask is kept out of H3's per-token timesteps, and the frames that mask holds back are re-noised to the step the sampler is on instead of being handed back nearly clean. Pass the returned model on to the guider. | |
| av_latent | LATENT | — | |
| transform | H3FACEXFORM | — | |
| denoise_multiplier_small_subject | FLOAT | 1.000–1 | MULTIPLIER on the denoise set on BasicScheduler, applied where the subject is SMALLEST. Not a denoise value in itself: at 1.0 those frames get the full BasicScheduler denoise, at 0.8 they get 80% of it. Below 1.0 NO frame in the clip receives the FULL denoise you set, which makes the whole clip gentler. |
| denoise_multiplier_large_subject | FLOAT | 1.000–1 | MULTIPLIER on the denoise set on BasicScheduler, applied where the subject is LARGEST. Lower preserves the real detail those frames already have, since a big subject needs less rebuilding than a distant one. |
| scale_mode | COMBO | absolute_px | absolute_px: strength is set by real subject size in SOURCE pixels via subject_px_small/large. Safe across a batch - a video that never has a small subject gets the baseline throughout. relative_to_clip: normalise to this video's own min/max, so its smallest subject always gets the full boost regardless of actual size. Use when tuning a single video to its extremes. |
| subject_px_small | FLOAT | 304–400 | Subject height (SOURCE px) at or below which the full denoise_multiplier_small_subject is applied. Genuinely tiny subjects only. |
| subject_px_large | FLOAT | 1208–800 | Subject height (SOURCE px) at or above which denoise_multiplier_large_subject is applied. Calibrated so a video whose smallest subject is ~90px gets only a mild boost - that size was already fine at the baseline denoise - and anything past 120px gets none. |
| gamma | FLOAT | 1.00.2–4 | Curve on the interpolation. >1 keeps strength high until the subject is genuinely large; <1 drops it off early. |
| smooth_frames | INT | 91–61 | Smooth the strength curve over time. An abrupt change in denoise between neighbouring frames is visible as a texture pop, so this wants to be generous. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| av_latent | LATENT | — |
| report | STRING | — |
| model | MODEL | — |