Zura · Preserve H3 Background During Sampling
Keep the room, change the actor
- latent
- source_latent
- mask
- LATENT
Full-frame video regeneration is a lottery with your set design. Ask for a new performer in a shot and you can end up with the same person but a different kitchen - the counter moved, the window's on the other side, the lighting's warmer. If you liked the shot as it was and only wanted the human changed, you want the sampler to leave the rest of the frame alone.
That's this node: it turns your edit mask into H3's native per-token noise mask, so untouched regions start from the real source latent instead of noise.
How it works
Like Zura's other H3 nodes, it works on the nested audio-video latent - video tensor plus audio tensor. The source_latent you hand it is the padded source video encoded through the H3 video VAE, and your mask is the pixel-space edit mask.
The conversion is three stages, and each one is there for a reason:
- Spatial: 16×16 max-pooling, matching the VAE's spatial compression. Any pixel touched in a block leaves the whole block flagged.
- Temporal: H3's VAE encodes in 17-frame chunks with causal history, so a moving edge can bleed forward into later tokens within the same chunk. The node takes the temporal max of the mask across each 17-frame chunk - so if the mask touches any frame in a chunk, the whole chunk is treated as editable.
- Patch: a 2×2 max-pool in 3D with repeat-interleave, to line up with the DiT's patch granularity, then expanded to the full latent shape.
The result goes in as the video half of noise_mask, with the audio mask passed through untouched. Where the mask is 0, the sampler is told "this token is already correct" - it starts from your encoded source pixels and doesn't re-roll them.
Deliberately conservative on the temporal axis: it retains more than you masked, never less. Overshooting into the edit region costs you a little freedom; undershooting would leave a frozen half-frame of an arm mid-swing.
Inputs and outputs
latent-LATENT, the H3 audio-video latent you're about to sample.source_latent-LATENT, the padded H3 source video, stock-encoded with the H3 video VAE.mask-MASK,[frames, H, W]at the padded source video's pixel resolution.LATENT(output) - same latent, with the video noise mask set. Straight to the sampler.
Install
cd ComfyUI/custom_nodes && git clone https://github.com/ZURAVFX/ComfyUI_zura_nodes
pip install -r ComfyUI_zura_nodes/requirements.txt
Restart. This node itself is CPU-side index arithmetic - the encoders and the H3 base model are the real weights, and they use the H3 community licence that locks the downloadable weights out of several regions. The API is available everywhere; the local weights are not.
Common issues
"The approved mask must match the padded H3 source video." Two usual causes: the mask frame count doesn't match (you masked the trimmed clip, not the padded one), or the resolution is off by a factor. The check is exact - frames × H×16 × W×16.
"Encode the padded H3 source video with the MiniMax H3 video VAE." Wrong VAE, or you encoded the source at a different resolution than the latent expects. Encode the same padded frames you masked.
"Connect a MiniMax H3 audio-video latent." You're passing a video-only latent. This node needs the pair, because it has to preserve the audio stream's own mask while it writes the video one.
Nothing appears to be preserved. Check the order of operations: whatever writes the noise mask last wins. If your continuation-prefix node runs after this one, it will overwrite the mask state - the pack's own guidance is that continuation application comes after background and audio masking, so wire them in that order.
Edges you didn't want frozen. The 17-frame temporal max is the suspect. A mask that's tight on frame 1 of a chunk keeps that whole chunk editable, and a mask that grazes frame 17 keeps the next chunk's start alive too. Expect the editable region to be a bit fatter than what you drew; that's the price of not getting torn geometry.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| latent | LATENT | — | |
| source_latent | LATENT | — | |
| mask | MASK | — | |
| protect_unedited_regionsopt | BOOLEAN | false | Protect the union of unedited pixels across each VAE chunk. Keep original people or source lettering while changing the surrounding pixels. |
| protection_timingopt | COMBO | chunk | Chunk protects moving subjects conservatively. Causal prevents future captions from locking earlier empty areas; H3 VAE decoding can still mix pixels within a chunk. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | — |