Zura · Verify Matching Speech Performance
The node that tells you your face motion and your audio don't match — before the 25-minute render
- footage
- selected_video
- clip_details
- opening
- verified_footage
- approved_opening
- performance_seed
Wan speech replacement is a two-model pipeline with a cache in the middle, which means it has a specific and very annoying failure mode: you generate a facial performance against one audio track, change the audio (or the seed, or the character look), render anyway, and get 25 minutes of beautifully animated mouth movement that isn't saying anything. ZuraWanSpeechGuard (Zura · Verify Matching Speech Performance) exists to make that impossible. Its docstring is blunt: a CPU provenance gate that returns the same native inputs without inference.
What it actually does
No sampling, no model loading, no GPU. It reads the saved guide manifest for guide_key, then tries to falsify your setup, in order:
- Is the manifest complete? A guide that's only
pending- queued, but never recorded as successfully completed - is rejected. - Does re-hashing the recipe data still produce
guide_keyitself? A recipe edited after the fact no longer matches its own key. - Does the guide's crop still validate, and does the guide's MP4 still hash to the recorded digest? It re-checks the file, not a cached belief about it.
- Does the prepared footage's
speech_provenancepoint at this guide's artifact digest? That's where the two halves of the pipeline are joined, and it catches face motion made against a different performance.
Then it compares the timeline and media. clip_details must still report the same reviewed shot, source hash, start, frame count, fps and duration. The source file is re-digested and the review's approved mask hash must still match. The connected selected_video is decoded and compared frame-for-frame, tensor-equal against the prepared frames, and its audio signature must match the one recorded when the guide was made. The soundtrack is then re-loaded from clip_details["audio_source"] and checked against the performance's signature, so a re-encoded track fails even if it sounds the same. Your seed must equal the seed the performance was made with, and the approved opening image is hashed on disk and compared pixel for pixel with the opening tensor you wired in.
On the windowed preparation path this streams in small bounded windows instead of loading both videos - same equality, less RAM.
The inputs, and why there are three outputs
footage (ZURA_FOOTAGE) comes from the preparation loader; selected_video, clip_details and opening are native wires; approved_opening_file is a string path resolved through ComfyUI's annotated-filepath helper, so it can live in a subfolder of input/; seed is the integer that went into the performance; guide_key is the verified guide's 64-hex key.
The outputs are verified_footage, approved_opening and performance_seed, and there are three because this node is a pass-through at the sampling boundary: you wire those forward, not your originals. It doesn't try to prove the past, it makes the present provable by handing you checked copies. It isn't an output node; it's a gate on the wire.
It re-runs on every queue (IS_CHANGED returns a NaN marker), deliberately: cached CPU tensors don't prove the guide, the source video or the soundtrack still exist unchanged on disk.
Install
Nothing extra for this node specifically - the pack, plus the speech-guide models it verifies.
cd ComfyUI/custom_nodes
git clone https://github.com/ZURAVFX/ComfyUI_zura_nodes
python -m pip install -r ComfyUI_zura_nodes/requirements.txt
Then run Setup_Wan_Speech_Windows.cmd once from the pack folder. It checks and downloads the Wan 2.1 I2V 480p fp8 base, the InfiniteTalk single-speaker patch (~5.1 GB), chinese-wav2vec2-base.bin, the lightx2v distill LoRA, the Wan 2.1 VAE, umt5_xxl_fp8_e4m3fn_scaled and clip_vision_h. The helper doesn't install Python packages; if huggingface_hub is missing it prints the command for your ComfyUI Python and you rerun it. It also reports missing native packs - you want ComfyUI-WanVideoWrapper and VideoHelperSuite.
Troubleshooting
Most of what you'll see here is the node talking:
The facial performance has not completed verification.- the guide exists but is still pending. Let the queue finish successfully and let the pack promote it; a guide rendered once and cancelled stays pending.- Anything about the seed, audio or approved look arrives with the pack's own remedy attached: "Change audio, character look or seed in Studio and regenerate the facial performance, then reopen the animation graph." That's the fix - no setting on this node makes a mismatched pair valid.
The facial-performance provenance is missing or invalid.is the catch-all for a deleted manifest - the records live underoutput/genj/wan_speech_guides/, so cleaning that folder surfaces it.
If you're comfortable in graph view, the pack explicitly allows a bypass: connect your own native face-motion guide deliberately. What you can't do is quietly leave a mismatched one in place - the guard will notice, and that's the whole value here. Weigh it against the honest state of the guide itself: local native speech is the newest, least-validated part of this pipeline, capped at 30 seconds and one visible face, with big head turns and occlusions called out as unvalidated.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| footage | ZURA_FOOTAGE | — | |
| selected_video | VIDEO | — | |
| clip_details | GENJ_CLIP | — | |
| opening | IMAGE | — | |
| approved_opening_file | STRING | — | |
| seed | INT | 00–18446744073709550000 | — |
| guide_key | STRING | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| verified_footage | ZURA_FOOTAGE | — |
| approved_opening | IMAGE | — |
| performance_seed | INT | — |