H3 Add Noise
The glue that lets a second H3 sampler pick up where the first one stopped
- model
- noise
- sigmas
- latent_image
- latent
Nobody runs MiniMax H3 at 2K in one sampler pass if they can avoid it. It's a 33B omni-modal model, and the local builds people actually run are the INT8-ConvRot ones - on a 20- or 30-series card those live or die on VRAM. So the sane workflow is staged: a cheap low-res pass that produces clean video, upscale the clean latent, then a short refine pass at the end of the same schedule.
That second pass is where this node lives. You continue a trajectory by resuming with the remaining sigmas and add_noise=disable, so the sampler doesn't invent its own noise - but a sampler with noise disabled expects a latent that's already sitting at the right noise level, and what you have after an upscale is clean x0. H3 Add Noise closes that gap, and it's about as unglamorous as a node gets.
What it actually does
It re-noises a clean latent to the sigma you're about to resume at - exactly, in the round trip that matters.
The trick is that the sampler still runs its normal noise scaling even with noise disabled; it just feeds it zeros. Push clean x0 through that and you get (1 - sigma) * x0, a dimmed image rather than a starting state. So the node pre-divides: it writes x0 + sigma/(1 - sigma) * epsilon into the latent, and the sampler's own (1 - sigma) * latent lands exactly on (1 - sigma)*x0 + sigma*epsilon. The first sigma of the schedule is the target level - not the gap between the schedule's endpoints, which is what people assume.
Consequences fall straight out of that math. Sigma of exactly 1 can't be represented (1 - sigma is zero, and with DisableNoise the sampler would just throw the latent away), so it's rejected - that's why the first entry of a normal 8-step schedule won't work. Sigma 0, or an empty schedule, is a no-op that hands your latent straight back. The arithmetic is promoted to float32 so a sigma of 0.99999 doesn't round up to 1.0 in half precision and blow up. And it processes every stream it's given: standalone video, standalone audio, or both in a native nested AV latent.
The inputs that matter
Four required inputs, one output. There's nothing optional and no widget to fiddle with.
- model - the same H3
MODELyou're sampling with, patches included. The node reads its sampling object for the shift and audio scale, so a different model than the sampler uses is a mismatch. - noise - a
RandomNoisenode, purely so you control the seed. The continuation gets fresh noise, not the epsilon from the original run. - sigmas - the remaining schedule. Its first entry is your target noise level.
- latent_image - clean x0: a sampler's
denoised_output, a VAE-encoded latent, or the upscaled clean latent. Not a noisy sampler output.
Output is a single LATENT for the continuation sampler's latent input, alongside the same sigmas and add_noise=disable.
The 6+2 upscale run the author documents looks roughly like this:
first sampler.denoised_output -> H3 Separate AV Latent -> video latent
video latent -> Load MiniMax H3 Latent Upscaler / MiniMax H3 Latent Upscale
upscaled clean video -> H3 Add Noise.latent_image
first sampler.output -> H3 Separate AV Latent -> unchanged audio latent
H3 Add Noise.latent -> H3 Concat AV Latent.video_latent
unchanged audio -> H3 Concat AV Latent.audio_latent
H3 Concat AV Latent -> second sampler (remaining 2 sigmas, add_noise disabled)
Leave that audio alone. The audio stream rides the video schedule scaled by H3's audio shift ratio, so if you hand the node audio you want to keep, it re-noises it as if you were deliberately restarting it from clean x0. If only one stream should change, split the AV latent upstream.
Installing it
ComfyUI Manager, search ComfyUI Turing Utils - the repo is published as comfyui-svdint4, but the plugin calls itself Turing Utils everywhere (categories, logs, the internal comfyui_turing_utils package). Three names, one thing.
cd ComfyUI/custom_nodes
git clone https://github.com/wjie98/comfyui-svdint4
# then restart ComfyUI
The pack's headline feature is a bundled CUDA kernel you build with python -m pip install -v --no-build-isolation -e ./kernel. You don't need that for this node. It's plain PyTorch latent arithmetic - no kernel, no Triton, no compile step. The pack's requirements.txt is literally just safetensors, kept free of the kernel so the CUDA build stays an explicit, opt-in step. What you do need is a ComfyUI new enough for native H3: the node imports ComfyUI's MiniMaxH3AV latent format and ModelSamplingAV, so on an older install it can't load at all.
Where people get burned
The classic is a sigma of 1.0 from grabbing a whole schedule instead of its tail: H3 Add Noise requires 0 <= sigmas[0] < 1. Slice off the first entry and pass what remains.
Next, H3 Add Noise requires a MiniMax H3 model with FLOW_AV sampling - you connected something that isn't H3, or a model whose sampling patch isn't in place. Wire the exact model feeding the sampler.
Then structural mismatches: NOISE must return the same video/audio structure as the input latent, Expected H3 video [B,24,T,H,W] or audio [B,32,2,T], or a batch-size complaint. Those almost always mean you fed a single latent where the original was a nested AV pair, or the reverse. A plain video-only latent is fine; just don't mix forms.
One caveat the author states himself: this prepares a state, not solver history. Multistep samplers keep internal history between steps and two sampler nodes can't share it, so a continuation isn't a bit-exact resume. Usually that's fine - it's a correct start at the right sigma with a new noise realization - but the seam is real if you push a long second-stage schedule.
And practically: H3 is new enough that there's barely a community error trail for any of this. Most of what goes wrong here will be your own wiring, not a known bug.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | The H3 MODEL used by the continuation sampler, including its sampling patches. | |
| noise | NOISE | Connect RandomNoise to control the new noise seed. | |
| sigmas | SIGMAS | Remaining sampling schedule. Its FIRST sigma is the target level (0 <= sigma < 1). | |
| latent_image | LATENT | Clean x0: denoised_output, VAE-encoded latent, or upscaled clean latent. Do not pass an already-noisy sampler output. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| latent | LATENT | — |