Nodes/ComfyUI_zura_nodes/Zura · Load H3 Motion Window
ComfyUI Node

Zura · Load H3 Motion Window

Decoding one slice of a long clip without decoding the whole thing

By ZURAVFX·Created about a month ago·Updated a day ago· 2
Zura · Load H3 Motion Window
  • source_video
  • combined_mask_video
  • genuine_mask_video
  • full_audio_timeline
  • clip_details
  • source_frames
  • combined_mask
  • genuine_mask
  • performer_guard
  • window_audio
  • clip_details
◄window_json{}►

Here's the thing that kills windowed video renders: you split a two-minute clip into windows, and then every window loads the entire source video to find its 124 frames. Twenty windows, twenty full decodes, and a project that should have taken forty minutes takes all afternoon.

This node decodes only the interval it needs. Keyframe seek, read forward, stop. That's the headline and it's a real, measurable difference.

How it works

It opens the VIDEO inputs through ComfyUI's native stream-source contract - not get_components, which would materialise everything. For each of the three video wires it checks the trim window, confirms there's exactly one video stream, and confirms the stream's average rate is exactly 24 fps. Then it seeks to the first requested frame and decodes forward, verifying every frame's presentation timestamp lands on the expected frame index.

That strictness is the point. If your source is variable frame rate, or the trim isn't frame-aligned, or a frame is missing, you get a clear error instead of a window that's silently one frame out of step with its mask.

What comes out:

  • source_frames - the RGB frames for this window, padded up to H3's 124-frame context by repeating the last real frame.
  • combined_mask - the edit mask frames, same treatment.
  • genuine_mask - the "this is definitely the real performer" mask for the window.
  • performer_guard - and this is the interesting one. The node streams the whole shot's genuine mask to build the union of every pixel the real performer occupies across the entire shot, then hands you that single-frame union. It's a guard region: anywhere the performer ever stood, so protection logic can't be fooled by a frame where the tracker blinked. Frames get unioned with a logical OR, so it only grows.
  • window_audio - this window's slice of the global timeline, silence-padded to the native context length.
  • clip_details - the clip metadata with the window's own record stamped in: index, shot, input and owned intervals, valid frame count, overlap, padding.

That last output is what makes the pack's text-region cleanup shot-aware, and it's why the text_regions in this dict are the ones for this shot only.

The window_json field is the planner's internal record - an exact set of fields, validated field-by-field. Don't hand-author it.

Inputs and outputs

  • source_video, combined_mask_video, genuine_mask_video - three VIDEO wires. They must share the same active trim; that's a hard check.
  • full_audio_timeline - AUDIO, from Zura · Prepare Full H3 Audio.
  • clip_details - GENJ_CLIP, the reviewed clip metadata. Frame count and 24 fps are read from here.
  • window_json - STRING, default {}. From the planner.
  • Outputs: source_frames (IMAGE), combined_mask (MASK), genuine_mask (MASK), performer_guard (MASK), window_audio (AUDIO), clip_details (GENJ_CLIP).

Install

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

Restart. This one leans on PyAV (av) for the interval decoding - it's in the pack's requirements.txt, and it's the one dependency here you might genuinely be missing if you installed by copying files rather than running the requirements. FFmpeg on PATH is still needed for the pack's video assembly generally.

Common issues

"Prepare source and masks at a constant 24 fps before H3 window decoding." Variable-frame-rate phone footage. Run it through a constant-fps conversion first; the node will not guess.

"Source, combined mask and genuine mask must use the same active VIDEO trim." You trimmed one of the three. Trim all of them identically, or none.

"The native VIDEO ended before the requested H3 frame interval." Your clip details claim more frames than the file has. That's a re-prepare, not a re-render.

"Cut-aware H3 cleanup needs shot-local text_regions_by_shot metadata." Older clip details from before the cut-aware cleanup existed. Re-review the clip.

Memory. Each window is bounded - 124 frames of RGB plus masks at your working raster - but performer_guard costs one more full-resolution frame, and the guard is built by streaming the whole shot's mask every time. On a long shot with many windows, that's repeated work; it's the price of a guard region that can't be fooled.

CategoryZura/Artist Studio/H3 Windows

Inputs (6)

NameTypeDefaultDescription
source_videoVIDEO—
combined_mask_videoVIDEO—
genuine_mask_videoVIDEO—
full_audio_timelineAUDIO—
clip_detailsGENJ_CLIP—
window_jsonSTRING{}—

Outputs (6)

NameTypeDescription
source_framesIMAGE—
combined_maskMASK—
genuine_maskMASK—
performer_guardMASK—
window_audioAUDIO—
clip_detailsGENJ_CLIP—