Nodes/comfyui-obvpm-timeline/H3 Joint Audio Mask (obvpm)
ComfyUI Node

H3 Joint Audio Mask (obvpm)

Stop the refine from re-recording a soundtrack you already liked

By chanon·Created 21 days ago·Updated 2 days ago· 33
H3 Joint Audio Mask (obvpm)
  • latent
  • latent
audio_denoise0.00

This one's small and easy to skip, and skipping it is a mistake. H3 denoises video and audio together - they're one nested latent pair, and that's not a bug, it's the reason the model's audio actually matches the picture. But it means a refine pass will happily re-render sound that was already finished, and "already finished" usually describes the state of your dialogue.

H3 Joint Audio Mask holds the soundtrack while the picture is refined. One input, one number, one output.

The inputs

latent is the upscaled joint AV latent - video plus audio, the thing you're about to sample.

audio_denoise is the decision, and it's a strength rather than a switch:

  • 0 - the audio comes out exactly as it went in. This is the default and it's right for the ordinary case: an upscale/refine where the sound is done.
  • ~0.5 - the sound re-samples alongside the picture, which you want for lip sync. Here's the interesting part: at high sigma a frozen audio track gives a near-noise video nothing to move the mouth for, so a silent hold can actually produce worse sync than a re-sample. When you raise this, the resampled audio has to be discarded at save time: wire H3 Joint VAE Decode and Save's source_audio from H3 Join Latents' latent (or a separate audio latent) so the finished render keeps the source soundtrack. The sidecar stores the audio that was actually rendered, so this is a deliberate, checkable choice rather than a hope.

Output is latent - the same latent with the audio hold applied, and the tooltip is explicit about where it goes: wire it to the sampler's latent_image. Not the upscaler's output, not the empty latent.

Where it sits

H3 Join Latents ─> upscaler (temporal chunking ON) ─> H3 Joint Audio Mask
  ─> sampler.latent_image

That's the whole node's job in the refine branch: it's the last thing between the upscaled latent and the sampler, and it's what makes the refine a picture pass rather than a full regeneration of sound.

The same idea exists on the continuation side, by the way. H3 MCtx Apply Pins has a freeze_audio toggle that holds the whole audio mask at 0 for a per-clip refine, and its audio_denoise raises the held value the same way. Same tradeoff, different entry point - the pins version also works with no pins at all, which is what the first clip of a timeline needs.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/chanon/comfyui-obvpm-timeline

Restart ComfyUI. No pip installs: the pack's pyproject declares an empty dependency list on purpose, since torch, torchaudio, numpy, safetensors and av already ship inside ComfyUI. Requires ComfyUI 2026-08-13 or later for core H3. ComfyUI Manager: search comfyui-obvpm-timeline, and note that every node in the pack ends in (obvpm), so obvpm alone finds them in the node menu.

Nothing to download for this node - but the refine branch around it needs the H3 latents, the H3 video VAE and audio VAE, and the MiniMax H3 latent upscaler pack.

Troubleshooting

  • Audio sounds subtly re-recorded after a refine. audio_denoise wasn't 0. It's easy to inherit a value from a preset and not notice.
  • You set 0.5 for lip sync and the delivered audio is the re-sample. You didn't wire source_audio on the render node. The mask doesn't save you; the save node does.
  • Audio and video lengths drift apart. The trim/save side tail-matches audio to exactly frames/fps, because H3 rounds its audio grid up by about 8 ms per clip. That error compounds across a chain - which is exactly the sort of thing you notice ten clips later.
  • Nothing changed. Check where the wire actually went. Feeding the sampler from the upscaler's latent instead of this node's output is the standard mistake, and the node does nothing visible when it's bypassed.
  • Sound is fine but music sounds muffled. A held latent is preserved, not improved - a refine can't sharpen audio it's holding. If the audio needs work, that's a different pass.

The default is right far more often than not: hold the sound, refine the picture. Reach for the re-sample only when the mouth needs help.

Categoryobvpm/h3

Inputs (2)

NameTypeDefaultDescription
latentLATENTThe upscaled joint AV latent (video + audio).
audio_denoiseFLOAT0.000–10 = the audio comes out exactly as it went in. Higher lets it re-sample with the picture (0.5 for lip sync); save the source audio then.

Outputs (1)

NameTypeDescription
latentLATENTThe same latent with the audio hold. Wire to the sampler's latent_image.