🔗 H3 Relay · Seed from Video
Your H3 film doesn't have to start with H3
- video
- video_vae
- audio_vae
- audio
- latent
- report
H3 is a great 4-to-15-second model. It's also, like every open video model of this generation, a machine for making clips that end before your scene does. So you stitch - usually by last-frame chaining: decode segment 1, grab its final frame, feed it back as the start image for segment 2. It works, and it quietly costs you: every hop is a pixel decode and re-encode, so color and detail drift, and the audio has no idea what the previous segment sounded like.
🔗 H3 Relay · Seed from Video is the entry point to the other answer. It takes a video you already have and encodes it into stage 0 of a relay chain - the same on-disk latent sidecar every relay node reads and writes - so the chain continues outward without touching pixels again. Real footage, an older render from a different model, someone else's clip: none of that came out of H3, and none of it can be stage 0 on its own.
What it actually produces
Feed it frames: picture through your H3 video VAE, audio through your H3 audio VAE, both packed the way the sampler expects. Then it writes ComfyUI/output/relay_kit/<run_id>/stage_00000.safetensors, plus a "bed" sidecar (audio_00000.safetensors) - the file Audio Seam reads when it patches the previous segment's room tone into the next head.
It also stamps a lineage header marking the segment source=video with no parent stage - that's how you tell later which segment came from reality. From there, Latent Load, Copy Bridge, Trim AV and Audio Seam treat stage 0 like any other.
The three things it refuses to let you do wrong
H3 has hard grid constraints and a source video has never heard of them. This node snaps you onto all three and says what it snapped:
- Frame count has to land on 5+17k (5, 22, 39, 56, …). Get it wrong and the bridge's tail-slice starts at the wrong phase and refuses everything. With
snapon its defaulttrim, the node cuts at the frame tail to the nearest legal length and records how many frames it dropped. - Width and height must be multiples of 16, and must match what the chain samples at. This is the most common first-run wall - the bridge rejects cross-resolution latents outright.
- Audio must match the video's length. Longer is trimmed, shorter zero-padded, missing becomes a silent seed, so the next segment doesn't die on "context latent has no audio stream".
Inputs you actually touch
video- the IMAGE output fromLoadVideo. The only required wiring that isn't a widget.video_vae/audio_vae- the same H3 VAEs your conditioning node uses. Wrong VAE and you get an error naming the shape it wanted back.width/height- leave both at 0 and it follows the source, rounded down to a multiple of 16, no crop, no stretch. Fill both only if your chain samples there; then it center-crops and Lanczos-fits. One zero and one value is an error by design.run_id/stage_index- the film name and which stage this clip is (0, normally).run_idmust match the rest of the graph exactly, or stage 1 goes hunting for a file that doesn't exist.
Optional: audio (LoadVideo's audio output - skip it and you get a silent seed), snap (error if you'd rather pre-cut yourself), note for the sidecar header.
Outputs are latent and report. The report is the honest one - frames in, frames used, frames dropped, canvas, latent steps, what happened to the audio, where the bed went. Read it once per run; it's the fastest way to learn snap ate seven frames of your shot. And leaving latent unwired won't skip it, since it's an output node: the file write is the product.
Install
Manager → search h3-latent-relay (the registry name drops the "ComfyUI" prefix), or:
cd ComfyUI/custom_nodes
git clone https://github.com/ZenHG/ComfyUI-H3-Latent-Relay.git
Restart the backend afterwards - refreshing the browser loads nothing. You need ComfyUI ≥ 0.35.0 with MiniMax-H3 support; on an older host the nodes still register and the relay silently does nothing, a miserable way to lose an afternoon. requirements.txt covers torch, safetensors, av>=17, numpy, packaging, comfy-aimdo. No third-party packs needed.
Where people get burned
Your source's frame rate is assumed to be 24. It can't read fps off an IMAGE tensor, so a 30 fps clip is read as 24 and comes out slow. Transcode to 24 first if timing matters.
Silent source means a silent bed. With no audio input the bed is zeroes, so Audio Seam patches silence into later segments and reports that it did. Fine if you wanted a silent opening; surprising if you assumed it'd find room tone.
The finished film doesn't include your source. Auto-concat stitches stages 1..N; the clip you seeded from is the head - join it in an editor.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| video | IMAGE | 【接法】已有视频的画面帧(LoadVideo 的画面输出)。 它会变成链的第 1 段,之后各段照常往外接。 | |
| video_vae | VAE | 【接什么】H3 的视频 VAE(与出词节点用的同一个)。 | |
| audio_vae | VAE | 【接什么】H3 的音频 VAE(与音频解码用的同一个)。 | |
| width | INT | 00–8192 | 【画面宽】0 = 跟随源视频(默认,源尺寸向下取到 16 的倍数,不动内容)。 填具体值 = 按这里居中裁切重采样,且必须与后续各段、出词节点一致(不一致桥会拒)。 ⚠ 两个都要么填 0、要么都填值。 |
| height | INT | 00–8192 | 【画面高】0 = 跟随源视频(默认,源尺寸向下取到 16 的倍数,不动内容)。 填具体值 = 按这里居中裁切重采样,且必须与后续各段、出词节点一致(不一致桥会拒)。 ⚠ 两个都要么填 0、要么都填值。 |
| run_id | STRING | relay | 【填什么】片名。 源视频会存成这一段的边车,必须与后面各段一字不差。 |
| stage_index | INT | 00–9999 | 【填什么】源视频是第几段。 通常填 0(当第 1 段),后面从 1 起往外接。 |
| audioopt | AUDIO | 【接法】源视频的音轨(LoadVideo 的音频输出)。 不接 = 静音种子,缝处音频由本段生成接管。 | |
| snapopt | COMBO | trim | 【帧数不在档上怎么办】trim = 按帧尾裁到最近的合法档(默认)。 error = 直接报错,由你自己先裁好再喂进来。 |
| noteopt | STRING | 【可留空】写进边车头的备注,比如「源片 v2」。 |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| latent | LATENT | — |
| report | STRING | — |