⏩ H3 Relay · Finite Run
Your H3 Clip Is Five Seconds Long. This Node Runs the Rest While You're Away
- model
- clip
- vae
- audio_vae
- sampler
- sigmas
- image
- ref_image_1
- ref_image_2
- ref_image_3
- voice_anchor
- last_latent
- images
- audio
- report
MiniMax-H3 generates 4–15 second clips. That's the model, not a setting you got wrong. So anyone making anything longer ends up in the same loop: queue segment 1, watch it, bump the stage number, rewrite the prompt to pick up the action, queue again. It works - and it's a dozen clicks per minute of footage, with you there for all of them.
⏩ H3 Relay · Finite Run turns that loop into one submit. You say how many segments you want, it builds the whole chain server-side and runs it start to finish - no frontend buttons, no per-segment edits, works from /prompt with the browser closed.
What it's really doing
The clever bit isn't the sampling. When you queue it, the node returns a graph instead of a tensor, and ComfyUI's engine registers each node in it as an ephemeral node in the same prompt. Public API, no monkey patching.
Each segment becomes a ten-node chain: MiniMaxH3ImageToVideo → H3RelayCopyBridge → RandomNoise → BasicGuider → SamplerCustomAdvanced → H3RelayLatentSave → VAEDecode / VAEDecodeAudio → H3RelayTrimAV → H3RelayJoinAV. No Latent Load either - the bridge pulls the previous segment off disk itself from run_id + stage number.
The continuation underneath is the pack's whole reason for existing. Instead of decoding segment 1 to mp4, re-encoding it and using that as an anchor - the last-frame-to-first-frame chaining everyone does with Wan - it copies the tail of the previous segment's AV latent bit-for-bit into the new one's initial latent and masks it so those frames don't get redrawn. No VAE round trip, no re-encoding drift, and audio is pinned with the picture. The pack's own seam checks read 0.000 across 7 sampling steps in hard mode.
The inputs a beginner actually sets
model, clip, vae, audio_vae and the sampling pair sampler / sigmas are shared by every segment. Then it's four things:
prompts- one block per segment, blocks separated by a line of three or more dashes. Block 1 feeds segment 1. Fewer blocks thansegmentserrors instead of quietly running short. One prompt for everything? Leavepromptsempty and useprompt.segments- how many. Default 2, max 64.run_id- the film's name. The one people get wrong: it locates every intermediate file inoutput/relay_kit/<run_id>/and every "read the previous segment". Don't reuse it for a different film.settle_frames- keep 0 for same-camera continuation. Set -1 for a new camera angle and it walks the hard cut back to the segment boundary. Measured: 0 gives a 0.020 frame jump; chopping 16 settle frames instead makes it 0.055, i.e. worse.
length only accepts the 5+17k ladder (5, 22, 39, 56, 73…158) and context_frames 5/22/39/56/73/90/107/124; off-ladder values raise rather than snapping.
Outputs
last_latent, images, audio, report. It isn't an output node, so nothing is saved until you save it: images and audio into CreateVideo, that into SaveVideo. last_latent is the final segment's tail if you want to continue later; report prints the plan and sidecar paths.
Install
ComfyUI Manager → Custom Nodes Manager → search h3-latent-relay (the registry id isn't the repo name; repos there can't start with "ComfyUI"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/ZenHG/ComfyUI-H3-Latent-Relay.git
Then restart the backend - refreshing the browser does nothing. No third-party node pack is needed here; only torch and safetensors, which ComfyUI ships. You do need ComfyUI ≥ 0.35.0 with MiniMax-H3 support, and that's the sharp edge: on an older build the nodes register fine and continuation just silently doesn't happen. H3 weights aren't in the pack.
Where people get burned
Memory. The joined output is one tensor resident in memory - total, not peak. At 1216×672 with 192-frame segments: 0.9 GiB for two, 4.4 GiB for ten, 16.2 GiB for thirty-seven. A 12 GB card realistically stops near ten. The node does that arithmetic from your settings and puts it in report.
No fixing it later. There's no Audio Seam or Post node in the expanded graph, and you can't eyeball segment 3 and re-roll just that one. from_segment covers recovery: set it to N and the first segment's bridge pulls stage N-1 off disk, erroring before anything loads if it's missing. It's mutually exclusive with image - your start point is somebody else's tail.
References. Use ref_image_1..3, not image. One set for the whole film is what refs_mode: lock is for; swapping per segment means the model re-recognises faces once the pinned window ends, and you get a hard cut where you wanted a seam.
Hand-writing API JSON? The frontend inserts an extra control_after_generate value right after seed, so widgets_values needs one more entry than the schema. Get it wrong and everything after seed shifts a slot - the pack's own example was rejected with HTTP 400 that way.
Inputs (29)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | 【接法】接你图里模型链的最后一级(放大器/LoRA 都在它之后接)。 | |
| clip | CLIP | 【接法】接 CLIP 读取节点的输出,各段的词都靠它编码。 | |
| vae | VAE | 【接法】接视频 VAE,画面编解码用它。 | |
| audio_vae | VAE | 【接法】接音频 VAE,声音编解码用它。 | |
| sampler | SAMPLER | 【接法】接采样器选择节点(如 euler),各段共用。 | |
| sigmas | SIGMAS | 【接法】接噪声表节点(步数与调度),各段共用同一个。 | |
| prompt | STRING | 【每段共用的一份词】只跑一种内容时填这里。 想每段不同词,用下面的 prompts 格。 | |
| segments | INT | 21–64 | 【跑几段】一次提交跑完几段。 填 3 = 从第 1 段跑到第 3 段。要配合 prompts 的词块数。 |
| seed | INT | 00–18446744073709550000 | 【随机种子】各段用同一个种子。 0 是常用的固定值;想各段不同请分次提交。 |
| run_id | STRING | relay | 【片子名】这部片子的名字,比如 myfilm、ep01。 各段中间文件与读上一段都靠它定位,多段必须填。 |
| width | INT | 134464–8192 | 【画面宽】16 的倍数,和出词节点填同一个数。 |
| height | INT | 76864–8192 | 【画面高】16 的倍数,和出词节点填同一个数。 |
| length | INT | 1245–3600 | 【每段帧数】24 帧每秒,124 帧约 5 秒。所有段一样长(与手动连跑一致)。 只认 5+17k 档:5/22/39/56/73/90/107/124/158/192/226… 非档值直接报错,不静默吸附。 |
| context_frames | INT | 225–124 | 【复制窗】从上一段尾部钉多少帧进本段。 只认 5/22/39/56/73/90/107/124,窗越长缝越稳。 |
| mask_mode | COMBO | hard | 【复制档位】hard = 复制区每步钉回不动(推荐,默认)。 taper / ramp / blend / window 是实验档,只在与旧结果对照时用。 |
| pin_audio | BOOLEAN | true | 【复制音频】开(默认)= 上一段尾部音频一起钉进本段。 关 = 音频各自生成,缝处可能不连贯。 |
| imageopt | IMAGE | 【首帧图】第 1 段的第一帧,各段用同一张。不接 = 纯文生成视频。 与下面三个参考图槽不能同时接:官方两个节点各缺对方那一槽。 续接要人物与场景稳定请用参考图,别用首帧图。 | |
| ref_image_1opt | IMAGE | 【参考图 1】外观参考,对应词里的 <Picture 1>。人物或场景,全片共用。 接了任意一张就走官方参考图生视频,与首帧图不能同时接。 | |
| ref_image_2opt | IMAGE | 【参考图 2】第二张外观参考,常见用法是第二个人的身份与服装。 不接 = 只用一张。 | |
| ref_image_3opt | IMAGE | 【参考图 3】第三张外观参考,常见用法是场景空间与材质。 不接 = 只用前两张。 | |
| promptsopt | STRING | 【每段各自的词】用单独一行三个以上短横线分块,第 1 块喂第 1 段。 块数不够会直接报错,不会悄悄少跑。 | |
| voice_anchoropt | LATENT | 【声音参考】本段说话人的音频锚,各段共用同一个。 不接 = 用上一段自己的音频尾。 | |
| noteopt | STRING | 【备注】写进每段中间文件的备注,比如「22 帧窗 v2」。 | |
| settle_framesopt | INT | 0-1–36 | 【按镜位选】同机位续接保持 0;换机位/换镜填 -1。 沉降区 = 复制区之后模型复现上一段的那几帧。 · 同机位:裁它们正是缝处跳帧的源头(实测 0 帧 0.020、16 帧 0.055)⇒ 保持 0; · 换机位:-1 自动把硬切退回段边界(实测三档全过)。 |
| from_segmentopt | INT | 00–9999 | 【从第几段之后起跑】0 = 从第 1 段起跑(默认)。 填 N = 接第 N 段往外跑;视频起段后填 1。 ⚠ 盘上必须有该段的边车文件, 没有会在开跑前就报错,不等模型上卡。 接续已有段时别接首帧图 image。 |
| ref_image_sizeopt | COMBO | match | 【参考图尺寸】match(默认)= 按画面尺寸缩每张参考图(只缩不放,保持比例)。 max = 保留更大尺寸。只在接了参考图时生效。 |
| refs_modeopt | COMBO | lock | 【定妆照用法】lock(默认)= 全片同一组,一镜到底的唯一无冲突解。 first_only = 只喂本批第 1 段,后续段靠外观参考跟随镜头。 没有「每段换一组」这一档:那是换镜,不是续接。 |
| ref_anchor_modeopt | COMBO | off | 【外观参考指向】off 不用;first 指第 1 段;roll 指上一段。 first 身份最稳,但进新环境会过时。 roll 跟随镜头,但长片会漂。 参考与定妆照同层,不一致会互相抢。 建议配对:first 配 lock,roll 配 first_only。 |
| ref_anchor_framesopt | INT | 51–64 | 【外观参考帧数】从参考段开头取几帧当基准,默认 5。 取多了会把参考段的动作也拖进来。 只在 ref_anchor_mode 不是 off 时生效。 |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| last_latent | LATENT | — |
| images | IMAGE | — |
| audio | AUDIO | — |
| report | STRING | — |