Silver H3 Staged Multishot (encode once / sample once / decode once)
Making MiniMax-H3 hold one shot for a minute and a half
- model
- clip
- video_vae
- audio_vae
- prompts
- start_image
- guide_audio
- char_refs_all
- char_refs_index
- char_audio
- master_audio
- saved_video
Every open video model falls apart at the same place: the join. You make five good ten-second clips and then discover the character's jacket changed, the room shifted two stops, and the voice is a different person. SilverH3StagedMultishot is the pack's attempt to make that seam invisible - unlike the batch node next to it, it isn't pretending independent clips are a long video. It chains them.
The output is one continuous take, N shots long. Same three-phase discipline as Silver H3 Batch (all prompts encoded in one text-encoder session, all shots sampled with the DiT resident, one streamed decode pass), but the shots are wired to each other in latent space, so motion, exposure and speech carry through a cut instead of restarting.
How the shots join
Two modes, selected by the ref2v toggle rather than by which inputs you happened to connect.
With ref2v OFF (fl2v), start_image seeds shot 1 the way stock image-to-video does, and shots 2+ chain on the previous shot's actual last frame through H3's native first/last keyframe channel. Use an fl2v-capable checkpoint, and expect character refs to be dropped with a warning: fl2v keyframes and identity refs are contradictory by construction, because the ref latents replace the keyframe latents.
With ref2v ON, start_image is ignored and shots 2+ inject the previous shot's last frame as the first reference block - the next shot gets to re-angle around that anchor instead of being pinned to it. This is the mode where char_refs_all, char_refs_index and char_audio do their work.
Either way, motion is carried by a per-step latent handoff, and that's a slightly expensive trick: each finished shot's tail has to be decoded to build the next shot's reference, forcing a DiT ↔ VAE swap at every join. The text encoder still loads only once, and it's the biggest of the three models, so the staging wins - but the README is honest that the per-join swap is unavoidable, not a bug.
What to actually set
prompts (one per shot, a STRING_LIST - feed it from Silver H3 Line Batch or Silver H3 Prompt List), overall_prompt for the scene-wide master, and then width / height / frames_per_shot (243 default ≈ 10.1s on the 17k+5 grid).
The three continuity knobs are where this node's personality lives:
latent_handoff_taper(15) is the percentage of a shot that carries the previous shot's motion as a linear fade. 15% of a 10s clip is 1.5s of carry-over. It makes a seam continue; it does not create a transition. If your prompt opens with its own cut, drop this toward 0–5% so stale motion stops fighting the description.audio_lock(ON) makes the next shot's audio head a locked replay of the previous tail, trimmed symmetrically on decode. Off means a silent join: the new head is kept whole and the previous tail is trimmed with a fade-out, so script each shot to land its line and hold still.audio_onset_guard(ON) parks the quietest ~0.4s of the previous shot's audio latent just past the locked span so the model can't plan speech underneath the replay.
context_frames (5, up to 39) is how many decoded tail frames feed the next shot as temporal context - 1 is stock single-keyframe behaviour, higher values buy continuity at the cost of a VAE encode per join. pin_renorm and color_reanchor are both on by default and both exist to stop brightness and white balance drifting down a long chain. guide_audio is the spine: encode the whole voice recording once and every shot's audio locks to its slice, which is the closest thing to "the voice cannot change" you'll get. double_pass and upscale_factor are the same refine-and-upscale pair as in the batch node.
Outputs are just master_audio and saved_video. The take lands in a dated subfolder as one mp4 per shot plus _master.mp4, each shot written and freed the moment it decodes - which is why a long run that dies on shot 7 leaves shots 1–6 on disk instead of nothing. Use those files: the mp4s are the trimmed, correct output.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/SilverAndJade/comfyui-silver-nodes
Restart, then either load SilverH3Staged_Turbo_3x10s.json from the repo or search "Silver Nodes" in Manager. The nodes use comfy_api.latest video types and PyAV, so keep ComfyUI current, and you need H3 weights - about 42.5GB, under the MiniMax H3 Community License, which excludes the US, EU, UK and South Korea. The repo's H3BATCH.md is the long-form reference and is genuinely worth reading.
Where it bites
A bad shot means re-running the chain. That's the price of coupling: shots are deterministic start to finish, but not independently re-rollable. If that matters more to you than continuity, use Silver H3 Batch, where the master is a hard-cut stitch rather than a transition.
Reusing an image batch shorter than your shot count won't gap-fill. char_refs_index reuses its last image for the rest, and there's no way to attach a reference to just shot 3. One voice at a time, too - no two-hander dialogue. The README's "not supported yet" section is accurate.
Updates can leave stale graphs, and expect [SilverH3][dbg] console noise on long runs - the forensics are compiled in at the moment.
Inputs (33)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| clip | CLIP | — | |
| video_vae | VAE | — | |
| audio_vae | VAE | — | |
| prompts | STRING_LIST | A single LIST of prompt strings - one PER SHOT (e.g. the output of the Silver H3 Prompts Builder or Prompt List Builder, or a plain string turned into a 1-entry list). Every prompt is text-encoded in ONE text-encoder session before any sampling starts. Empty entries are skipped. | |
| overall_prompt | STRING | Optional SCENE-WIDE MASTER prompt prepended to EVERY shot's prompt before encoding (overall + shot). Put the shared scene description here and the per-shot specifics in the prompts list. | |
| ref2v | BOOLEAN | false | Continuity MODE (must match your checkpoint): OFF / fl2v - start_image seeds shot 1 (I2V); shots 2+ chain on the previous shot's ACTUAL LAST FRAME via H3's native first_frame keyframe channel (last frame is first frame). Character refs are ignored in this mode. ON / ref2v - start_image is ignored. Shots 2+ inject the previous shot's last frame as the FIRST reference block (before any char_ref) - the shot may re-angle around that anchor. Character refs ride on every shot for identity. BOTH modes carry motion into the next shot via latent handoff (head clone + per-step locks + taper). Use an fl2v model when OFF, a ref2v/ref2va model when ON. |
| width | INT | 76832–4096 | — |
| height | INT | 134432–4096 | — |
| frames_per_shot | INT | 24339–1450 | Frames at 24fps on H3's 17k+5 grid (243 = ~10.1s per shot). Trained range is ~124-362; beyond is RoPE-extrapolation territory. |
| seed | INT | 00–18446744073709550000 | — |
| steps | INT | 201–50 | — |
| sampler_name | COMBO | res_multistep | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 |
| scheduler | COMBO | simple | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 |
| start_imageopt | IMAGE | fl2v mode ONLY: the FIRST FRAME of shot 1 (I2V). Encoded once during the ENCODE phase and handed over the way stock Image-to-Video does it - vision tokens through the text encoder plus the frame-0 keyframe latent. Only shot 1 is seeded by this; shots 2+ always chain on the previous shot's ACTUAL last frame via the keyframe channel (last frame is first frame). IGNORED in ref2v mode (the ref2v toggle). In fl2v mode character refs are ignored - fl2v and refs are contradictory, char refs are DROPPED with a warning if given while fl2v. | |
| latent_handoff_taperopt | FLOAT | 150–100 | LATENT handoff bleeding: percent of THIS shot that carries the previous shot's motion as a linear fade - makes the seam CONTINUE (the cut stays invisible); it does NOT create a transition. Transitions are prompt-authored: if this shot's prompt opens with one, drop toward 0-5% so stale motion doesn't fight it. 15% of a 10s clip = 1.5s of carry-over, a good default. 0 = hard seam. Saved videos are always 24 fps. |
| audio_onset_guardopt | BOOLEAN | true | AUDIO onset guard: appends the quietest ~0.4s of shot's AUDIO LATENT just past the locked span, so the model cannot plan speech under the replay - otherwise the free region resumes mid-word and the trim chops the line's opening. Latent-domain version: no decode involved. |
| audio_lockopt | BOOLEAN | true | ON: the next shot's audio head is a locked replay of the previous tail and the replayed span is dropped on decode (symmetric trim). OFF: audio generates freely - the new head's audio is kept in full and the PREVIOUS tail is trimmed instead, so script each shot to land its line and hold still for the last beat. |
| context_framesopt | INT | 51–39 | Motion context: how many decoded frames from the previous shot's tail are used as temporal context for the next shot. 1 = single keyframe (stock behaviour); 5 = one latent block; 22 = two blocks; 39 = three blocks (maximum). Higher values give stronger shot-to-shot continuity at the cost of one extra VAE encode per join. Snaps to the H3 temporal grid. |
| pin_renormopt | BOOLEAN | true | Pin Renorm: normalizes the std of each shot's latent tail to match the chain baseline (shot 0). Prevents brightness/contrast drift between shots at zero cost. |
| color_reanchoropt | BOOLEAN | true | Color Re-anchor: stabilizes per-frame RGB statistics across shots (nudges each context frame's mean/std toward the chain root) and applies a seam color match at each cut boundary (affine transform faded over 24 frames). Reduces exposure/white-balance jumps between shots. |
| seed_per_shotopt | BOOLEAN | true | Varying the seed per shot holds identity across the chain better than one shared seed. |
| guide_audioopt | AUDIO | AUDIO SPINE: a continuous audio track for the WHOLE take (a voice recording, a song, a low-res long pass). Encoded ONCE in the ENCODE phase; each shot's audio stream is then locked to its time-slice of the spine at every sampling step - the video follows the locked audio (lips included) and the voice cannot change between shots. Shot stride accounts for the 22-frame join trim, so the spine stays in sync across the whole piece. Any sample rate; mono is upmixed. | |
| char_refs_allopt | IMAGE | Optional CHARACTER REFERENCE list: EVERY image here rides EVERY shot (stable <Picture N> labels across the whole take). 1..k images, one per reference (character, prop, location...). Encoded ONCE in the ENCODE phase - image ref rows PLUS <Picture N> vision tokens in every shot's text conditioning: outfit/face carry with NO temporal claim, so it never fights the join keyframes. Aspect preserved (downscaled toward the generation's pixel area, never stretched). Combined with char_refs_index (deduped) when both ride. IGNORED in fl2v mode (the ref2v toggle OFF): char refs and fl2v keyframes contradict, so fl2v drops refs with a warning. In ref2v mode (toggle ON) they are the identity anchor, second only to the chained last-frame reference. | |
| char_refs_indexopt | IMAGE | Optional CHARACTER REFERENCE list INDEXED BY SHOT: image i is ridden by SHOT i (per-position; a list shorter than the shots reuses its last image for the rest). Each shot references a DIFFERENT <Picture N>, so the labels shift per shot. Leave unconnected to disable indexed refs (see char_refs_all for refs on every shot). | |
| char_audioopt | AUDIO | Optional CHARACTER VOICE REFERENCE (ref2va). Encoded ONCE in the ENCODE phase and ridden by EVERY shot as a DiT-side audio ref row plus <Audio N> tokens - voice/style identity with no timing claim, so it never fights guide_audio (the driving spine) or the generated speech. Single track only (one voice at a time). Any sample rate; mono is upmixed. IGNORED in fl2v mode (toggle OFF): fl2v drops refs with a warning. | |
| filename_prefixopt | STRING | SilverH3 | Output filename prefix. Saved into a dated subfolder prefix_yyyymmddHHMMSS/ as shot_01.mp4, shot_02, ... plus _master.mp4 (the combined take). |
| formatopt | COMBO | mp4 | Container/codec for the saved video. mp4 = H.264 in an mp4 container; auto picks the usual pairing. |
| frame_compressionopt | FLOAT | 23.000–51 | H.264 CRF for the saved video. 0 = lossless (huge file), 23 = default good quality. |
| double_passopt | BOOLEAN | false | Second sampling pass over EACH shot's FULL latent at a reduced denoise (Motion-Director style refine). Re-sampling from the already-sampled latent with only the bottom of the sigma schedule regenerates fine detail. The shot chain (latent handoff / first frame + audio lock) is re-applied during the refine so the continuity locks survive it. Costs one extra DiT sample per shot. |
| double_pass_denoiseopt | FLOAT | 0.250.01–1 | How much of the first-pass latent is re-noised for the refine pass. 0.25 = only the bottom 25% of the sigma schedule - a light refine that keeps composition, 0.5+ visibly rewrites it, 1.0 = a full re-roll of that shot. |
| double_pass_stepsopt | INT | 81–50 | Sampling steps for the refine pass. 8 is plenty for a 0.25-denoise refine; raise only when denoise is pushed higher or quality demands it. |
| upscale_factoropt | FLOAT | 1.001–2 | Spatial latent upscale applied to every shot's video BEFORE the refine pass / decode: the video latent is trilinearly resampled to this factor and decoded at the larger size (recommended combo: upscale 1.25x + double_pass to fill the new detail). 1.0 = native resolution. The upscaled latent is decoded at the larger size; audio is unaffected. The refine pass's VRAM cost scales with the upscaled area. The latent handoff chain is kept at native resolution. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| master_audio | AUDIO | Master audio at the audio VAE's rate (per-shot audios assembled and crossfaded at the seams). |
| saved_video | STRING | Path of the combined streamed take (_master.mp4) that Phase C wrote direct to disk, with ONE mp4 per shot saved alongside in the dated subfolder (each shot streamed out as it decodes - one shot in RAM at a time - so progress survives a long run and the shots can be re-combined manually). |