Nodes/ComfyUI_zura_nodes/Zura · Finish Motion Preparation
ComfyUI Node

Zura · Finish Motion Preparation

Stitching the per-section shards into one cache

By ZURAVFX·Created about a month ago·Updated a day ago· 2
Zura · Finish Motion Preparation
    • preparation_cache_key
    ◄cache_key►
    ◄total_frames120►
    ◄receipts_json[]►
    ◄metadata_json{}►

    The bounded preparation path processes a long shot in sections - 41 frames in the standalone example, 81 in Studio. Each section is saved as its own part with a receipt. This node takes the receipts and produces the single preparation cache the sampler actually samples from.

    It's the last step of preparation and it's an output node, so it always runs. Its four outputs-worth of work in exchange for one string: preparation_cache_key, which you then hand to a loader in the sampling graph.

    Inputs

    • cache_key - string, default empty. The 64-hex key for the merged result.
    • total_frames (default 120, min 1) - the full shot length. This is checked, not trusted: the reviewed shot's recorded frame count has to match it.
    • receipts_json (default "[]") - a JSON list of receipt paths, in timeline order. The list must be explicit and canonical; the node re-derives the expected set and compares, so a partial list, a duplicate, or a re-ordered one is an error rather than a surprise.
    • metadata_json (default "{}") - the preparation metadata object that goes into the merged record.

    What it verifies before it merges

    Quite a lot, and the pattern is consistent: prove the pieces belong to the reviewed shot, then write.

    The first receipt must carry a source_pin whose review_shot_id matches the pattern of a Studio review shot. The reviewed manifest for that shot is read back, and its clip's frame count must equal total_frames. The original source file's SHA-256 is recomputed and compared - if the source video changed after preparation, you get "The original Wan source changed after preparation." Every part is then scanned and checked for maximum part size, contiguous coverage from frame 0, and the end frame landing exactly on total_frames. Only then does it merge.

    After merging it opens the result as a window reader to prove it's readable, and it checks for user interruption during the scan so a long merge isn't uncancellable. On success it returns the key and writes "Prepared N Wan frames in bounded windows" to the UI.

    Two smaller things it refuses, both deliberately: more than 4096 receipts (a sanity bound on the JSON), and receipt paths that aren't plain strings. This node is reading file paths out of a text widget, so it does path containment work rather than trusting what's typed. Don't take that as an invitation to be clever with receipts_json - it comes from the section savers.

    Install

    Ships with the pack:

    cd ComfyUI/custom_nodes && git clone https://github.com/ZURAVFX/ComfyUI_zura_nodes
    pip install -r ComfyUI_zura_nodes/requirements.txt
    

    Manager: Zura Nodes by ZURAVFX, restart after. This node itself needs no model weights - but the parts it merges were produced by the prep path, which does need ComfyUI-WanAnimatePreprocess and the detection weights.

    Common issues

    "Wan merge requires every canonical preparation receipt in timeline order." The classic is running the sections out of order, or dropping the last one because it looked like a partial. Every section's receipt goes in the list, including the short final section, in order, and nothing else.

    "The original Wan source changed after preparation." You re-encoded, trimmed or replaced the source clip between preparing the sections and merging them. Re-prepare from the current file; the hash check exists because a merged cache that mixes two versions of the source would be silently wrong in exactly the places you'd blame on the model.

    "Wan merge no longer matches the reviewed full clip." total_frames disagrees with the reviewed shot. Count on the approved timeline: frames = seconds × 24, and the last section is whatever's left over.

    It re-runs every time you queue. It's an output node with an always-changed check, by design. That's correct for something validating file hashes across a shot, but it does mean a queue on a 20-second shot re-verifies every part before it can decide there's nothing to do.

    Merged fine, sampler still refuses the key. You're on the wrong loader. A windowed/streaming cache needs the windowed or file-backed loader, and the plain loader will not accept it.

    CategoryZura/Artist Studio

    Inputs (4)

    NameTypeDefaultDescription
    cache_keySTRING—
    total_framesINT120—
    receipts_jsonSTRING[]—
    metadata_jsonSTRING{}—

    Outputs (1)

    NameTypeDescription
    preparation_cache_keySTRING—