Zura · Save H3 Character References
Cache the expensive half of a MiniMax H3 take
- positive
- latent
- STRING
MiniMax H3 takes a pile of inputs - a face reference, a depth or pose control, a reference video, a dialogue or performance track - and encodes them into conditioning plus a paired video/audio latent before sampling even starts. On a second take with the same look and the same reference, all of that work is identical. GenjSaveH3Conditioning ("Zura · Save H3 Character References") is the half of the pair that writes it to disk so GenjLoadH3Conditioning can skip straight to sampling.
Worth being clear about what this caches: not your image, not a checkpoint - the encoded reference context for one specific configuration. That's why the pack's cache key includes the model file stamps, the reviewed shot, the character and opening image hashes, the prompt, the resolution, the audio and the lip-sync setting. Change the prompt and it's a different key, which is the correct behaviour and the thing that makes a cache trustworthy instead of a source of mystery output.
How saving works
Required inputs: positive (CONDITIONING - the encoded reference context the guider will use), latent (LATENT - H3's paired video/audio latent, a nested tensor), and cache_key (STRING, default empty).
Before writing, it does a structural check, and this is where most of the value is. It walks the conditioning metadata and verifies the H3-specific blocks - reference images, videos, audio and video-audio blocks - have the right tensor shapes: references at (1, 24, h, w, t), audio latents at (1, 32, 2, t), keyframe guides carrying an integer frame index. For the latent it verifies the nested pair, an even canvas, a timeline that satisfies the 5/17 frame grid (frames = 5 + 17 × ((t − 2) / 5)), and that the audio latent length equals round(frames / 24 × 40). Mismatched audio and video timelines are caught here rather than five minutes into a sample.
Then it writes output/genj/h3_conditioning/<key>.pt - atomic, via a .tmp file and a rename - and returns the key as a STRING. As an output node it also pushes "H3 character and performance references ready." to the UI. CPU copies of the tensors only, so the GPU keeps its memory.
The key is a hash, not a name
Invalid H3 reference cache key. is what you get for anything that isn't 64 lowercase hex characters. In Studio you never see a key; exported graphs carry the string. If you're hand-building the pair, generate one yourself - a sha256 hex digest of whatever recipe identifies your reference - and use the same string in both nodes. Don't type mycache1.
Install
ComfyUI Manager → search Zura Nodes → install → restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/ZURAVFX/ComfyUI_zura_nodes
python -m pip install -r ComfyUI/custom_nodes/ComfyUI_zura_nodes/requirements.txt
Pure PyTorch - no ffmpeg, no models for this node itself. The H3 stack it sits in is the heavyweight part: the reference-to-video transformer, the Qwen3-VL text encoder, both VAEs and the union control patch, all named in INSTALL_STUDIO.md.
Gotchas
- A cache is not a checkpoint of your progress. These files are tensors keyed by a recipe hash. Renaming one to reuse it under a different key is exactly the situation the loader's validation is designed to catch.
- Disk usage is quiet.
.ptfiles of conditioning plus nested latents add up across projects; they live underoutput/genj/h3_conditioning/and are safe to delete, at the cost of one rebuild. - Cache invalidation is by design, not a bug. Touch your text encoder file, change the prompt, or switch resolution, and the key changes and you re-encode. That's the price of never loading stale references into a render.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| positive | CONDITIONING | — | |
| latent | LATENT | — | |
| cache_key | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |