Nodes/H3 Relay/H3 Relay Windowed Edit · Character Swap
ComfyUI Node

H3 Relay Windowed Edit · Character Swap

H3 Relay Windowed Edit is how you swap a character into footage you already shot

By akatz-ai·Created 3 months ago·Updated 10 days ago· 44
H3 Relay Windowed Edit · Character Swap
  • model
  • clip
  • video_vae
  • audio_vae
  • source
  • reference_image
  • source_audio
  • edited_frames
  • window_plan
◄fps24.00►
◄promptReplace the person in <Video 1> with the character in <Picture 1>. Preserve motion, framing and scene.►
◄window_frames124►
◄history_frames18►
◄seed904234►
◄steps8►
◄cfg1.00►
◄sampler_nameer_sde►
◄schedulersimple►
◄denoise1.00►
◄source_count0►
◄window_controls{}►

The character-consistency problem got rerouted. Instead of trying to generate the same person twice, everyone now generates once and edits - feed a reference and source footage to a video model and let it restage the shot. MiniMax H3 does this well enough that "replace the person in the reference video with the person from the reference image" became a launch-week party trick.

The catch is the one you'd predict: H3's honest range is 4–15 seconds. H3 Relay Windowed Edit · Character Swap is the wrapper that takes a longer source clip, splits it into H3-sized windows, carries generated history between them so the character doesn't change identity halfway through, and stitches the result back to exactly your source length.

What you wire in

The model side is native H3: model, clip, video_vae, audio_vae. Both VAEs are used - H3 generates picture and audio together, and the reference conditioning needs the audio VAE too. The pack's Pack LTX Model node isn't involved here; that's for the LTX finishing path.

Then the content: source (your prepared frames), reference_image (the character - only the first image is used, matching the single-character contract), and source_audio optionally, if you want the original soundtrack available.

Settings worth understanding:

  • prompt - defaults to Replace the person in <Video 1> with the character in <Picture 1>. Preserve motion, framing and scene. Those <Video 1> / <Picture 1> tokens are H3's native reference addressing, not decoration.
  • window_frames - maximum target size per window, default "124" (5.17s). Short clips and final windows shrink automatically to the smallest valid size that fits.
  • history_frames - 0 for independent windows, 1 for a generated boundary frame only, or 18/35/52… (17k+1) for real sliding history. Default 18. It must be smaller than the window.
  • seed - the master. Window one uses it, window two uses master + 1, and so on. Keep it fixed and reroll individual windows; changing it starts everything over.
  • steps 8, cfg 1, sampler_name er_sde, scheduler simple, denoise 1 - the native H3 defaults. source_count exists so you can pass the preparation node's source_frames and exclude the padding that prep adds to reach the H3 grid.

Two outputs, and one of them is not a video

edited_frames is the assembled IMAGE batch - feed it to a video-saving node. window_plan is a JSON string describing every actual source range, target size, effective history, padded tail and discarded boundary, plus the policy tag adaptive-target-v1. It looks like a debugging leftover; keep it. When a seam looks wrong, the plan tells you which window is responsible, and an unchanged plan is part of what makes a checkpoint reusable.

Watching it work

Each completed window publishes a small MP4 preview card on the node before the next window starts - hover to play, tap on a touch screen. Every card has a seed field and a Reroll button: rerolling window four keeps one through three and rebuilds four and everything after it, which is the behaviour you want, because later windows inherit the changed history.

Ordinary Run with unchanged inputs reuses completed windows, including across a restart. There are no lock toggles to manage. Change the prompt, the reference, the source pixels, the window or history size, a sampler setting or a model file and the whole set resets with the old checkpoints left on disk. Rationale: reuse checks real input bytes and a hash of the model graph, not filenames.

Install

cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/akatz-ai/h3-relay.git

Manager → H3 Relay → install → restart. Needs ComfyUI 0.32.0 or newer, FFmpeg on PATH, the H3 FL2VA/Ref2VA diffusion models, Qwen3VL text encoder and both H3 VAEs from the pack's MODELS.md. No pip dependencies - dependencies = [], which for a video pack is a small mercy.

Where people get burned

  • Not 24 fps, or dimensions not divisible by 32. The node rejects both up front. Use H3 Prepare Video · Auto Size & Length first; it normalizes frame rate and lands you on the grid.
  • A 30-second clip on a 24GB card. Windows accumulate CPU RAM and disk. This is an experimentation workflow, not a streaming implementation - the pack's disk-staged long-form runner is a different chain (Sequence Start → Generate Shot → Assemble). Start with ten seconds.
  • Expecting pixel-identical preservation outside the person. An edit model re-emits the whole frame. Background text, reflections and occlusions will move. No prompt fixes that; it's structural.
  • Identity drifting anyway. Check history first - history_frames=0 means each window is independent and the character will wander. Then check that you're not changing settings between runs, since a configuration reset silently regenerates everything with fresh derived seeds.
  • The character reference is only the first image. Batch in a grid of poses, not a batch of frames, if you want more than one view.
  • License. H3's weights are territory-restricted (the US, EU, UK and South Korea are outside the license's Applicable Territory). The pack's GPL-3.0 says nothing about your model rights.
CategoryH3 Relay

Inputs (19)

NameTypeDefaultDescription
modelMODEL—
clipCLIP—
video_vaeVAE—
audio_vaeVAE—
sourceIMAGE—
reference_imageIMAGE—
fpsFLOAT24.00—
promptSTRINGReplace the person in <Video 1> with the character in <Picture 1>. Preserve motion, framing and scene.—
window_framesCOMBO124Maximum generated frames per window; short clips and tails shrink automatically, excluding past history: 107 = 4.46s, 124 = 5.17s. Valid H3 sizes are 17n+5.
history_framesCOMBO180 = independent windows; 1 = generated boundary only; 18/35/52... = H3 sliding history. Includes one boundary frame. Must be smaller than window_frames.
seedINT9042340–18446744073709550000Master seed. Window 1 uses this value; later windows use master + window index. Changing it starts fresh windows and clears per-window overrides. Keep fixed to reroll individual windows.
stepsINT81–100—
cfgFLOAT1.000–100—
sampler_nameSTRINGer_sde—
schedulerSTRINGsimple—
denoiseFLOAT1.000–1—
source_audiooptAUDIO—
source_countoptINT00 uses all input frames. Connect preparation's source_frames to exclude its model-padding tail.
window_controlsoptSTRING{}—

Outputs (2)

NameTypeDescription
edited_framesIMAGE—
window_planSTRING—