MiniMax H3 Lock Audio Latent (Internal)
Pin the soundtrack by zeroing its denoise mask
- target_latent
- audio_latent
- Locked AV Latent
If you take one idea away from this pack's digital-human support, take this one: locking audio isn't a mode, it's a mask. H3 samples video and audio as a single nested AV latent, and the sampler reads a noise-mask value of 0 as "preserve the input" and 1 as "denoise this fully." So "use my uploaded recording" reduces to: put the encoded waveform into the audio stream of the latent, and set the audio mask to zero.
That's the whole node. Its docstring: "Replace the H3 target audio stream and exclude it from denoising."
How it works
It checks three things before touching anything, and the checks are the interesting part because they're all about the nested latent's shape.
It requires the target latent's samples to be a nested tensor - H3's AV latent is a pair of streams, not a flat tensor, so a plain video latent fails here. It unbinds the pair and requires exactly two streams. And it requires the incoming audio_latent to be a non-nested single stream - one encoded audio, which is what VAEEncodeAudio gives you. Then it makes the source runnable: same device, same dtype, matching shape on every axis except the last.
The last axis is time, and it gets padded or truncated to the target's length. That matters for a very ordinary situation: your uploaded recording is 41 seconds, an individual segment is a 10-second window, and H3's audio stream wants a legal latent duration. So the node pads with zeros - silence - to reach it. The README is explicit that this padding is internal only and gets discarded during final assembly, where the continuous original waveform is restored instead. Once the audio is in place, it builds a fresh noise mask: the existing video mask (or ones if there wasn't one) plus an all-zero audio mask, and returns a new latent dict rather than mutating yours.
Why this is the good implementation and not a hack: it doesn't bypass sampling, doesn't zero out the model, and doesn't need a special sampler. The sampler runs completely normally with the audio conditioned at zero denoise, which is what keeps lip motion audio-driven while the waveform stays untouched - no separate avatar model in the loop.
Inputs and outputs
Required: target_latent (the nested H3 AV latent, from the Plan Encoder or the continuation step) and audio_latent (a single encoded audio stream - encode your slice with the H3 audio VAE first).
One output: Locked AV Latent, with the video stream, noise mask and everything else carried through, and only the audio stream and its mask changed.
In the shipped graphs you don't wire this yourself: the sampler and the loop's Prepare node insert it, and it only appears at all when the plan has locked audio.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Songssx/ComfyUI-MiniMaxH3-TimelineDirector.git
Restart, search MiniMax H3. No pip install - empty dependency list; the pack uses PyTorch and what ComfyUI already ships. This is an (Internal) dev-only node, so it's absent from the node menu unless dev mode is enabled. Requirements: recent ComfyUI with native H3 nodes, the H3 Ref2VA model, CLIP, video VAE and audio VAE, Python 3.10+.
Common issues
"Locked audio requires a nested MiniMax H3 AV latent." You handed it a flat latent. The target must come from H3's conditioning path, not from a video-only source.
"Locked audio requires one encoded audio latent." The audio side is nested - usually because you passed another AV latent, or a fresh latent from a video-encode path.
Shape incompatibility on the encoded audio. Your audio VAE isn't the H3 audio VAE, or the waveform was resampled to a different rate so the latent channel geometry no longer matches. Use the H3 audio VAE consistently and let the pack slice and pad.
You expected the full recording in the audio output and got the whole thing sounding stitched. Each segment only gets its slice here; the continuous source waveform is restored by the master node at the end of the chain. Also worth knowing: if the audio stream is muted in the plan rather than locked, you get silence on purpose instead of H3 generating replacement sound.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| target_latent | LATENT | — | |
| audio_latent | LATENT | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| Locked AV Latent | LATENT | — |