H3 Multishot Sampler (one node)
One node, a whole seamless take instead of a cut sequence
- model
- clip
- video_vae
- audio_vae
- start_image
- reference_images
- voice_ref
- upscale_model
- sigmas
- master_frames
- master_audio
- shots_rendered
- first_shot_frames
- first_shot_audio
The classic one. MiniMax-H3 generates roughly 10-15 second blocks, and if you've ever tried to chain two of them with stock nodes you know what happens: shot 2 re-imagines the scene from text, so the face shifts, the wardrobe drifts, the colour jumps, and what you have is a cut sequence, not a take. H3MultishotSampler is the pack's zero-dependency answer to that - it renders shot after shot and hands each one's last frame to the next as its first frame, using the checkpoint's own trained continuation task (fl2va's image-to-video mechanism), so the join is continuous by construction. Same face, same room, same light - because the next shot starts from an actual rendered picture, not a fresh reading of the prompt.
How the chaining works
Each shot's last frame becomes the next shot's first frame through fl2va's trained I2V path - the conditioning route the model was trained on, not a bolted-on hack. Two cleanups make the join invisible: the duplicated boundary frame is trimmed (one-frame stutter gone), and the seam audio gets a 40ms equal-power weld so the join doesn't dip in loudness. Identity holds through a second mechanism as well: byte-identical text. The prompt writer repeats each character's appearance block verbatim in every shot, so sampling noise around a reworded description can't drift the face. Frame pins the instance; text pins the category.
The inputs that matter
script- one prompt per shot,---on its own line between them (JSON{"prompts": [...]}also accepted). This is where the quality lives. The README's boundary rules are worth reading before you write one: each shot after the first opens holding the previous shot's closing arrangement with ~2 quiet seconds, and a spoken line never straddles two shots.shot_count-0= one shot per---block (leave it).1-8forces a total; a short script repeats its last block as a continuation.frames_per_shot- 243 default (~10.1s), 362 is the trained max (~15.1s), on H3's 17k+5 grid.seed_per_shot- leave ON. Measured: per-shot seeds hold the face; one seed for every shot drifted both face and voice.start_image- optional I2V first frame for shot 1 (a real first frame, unlike the memory sampler's same-named input). Later shots keep chaining from previous last frames.reference_images- character refs carried into every shot as<Picture 1>, etc. Bind them in the prompt: "She looks like the woman in<Picture 1>." Verified on ref2va.voice_ref- an audio anchor (<Audio 1>) that pins the voice across the chain. Also ref2va territory.self_anchor_voice- after shot 1 renders, its own audio becomes the reference for later shots. No file needed; write shot 1 so the character speaks a clean solo line.output_scale/upscale_model- post-decode resizing / real upscale. Read the tooltip carefully: with an upscale model wired,1.0does not mean off - it means don't correct, so you get the raw 4x. The console prints the projected size when the model loads; at 1344x768 a 4x upscale is 22GB a shot in system RAM.
Outputs: master_frames and master_audio (the joined take, seams trimmed), shots_rendered, and first_shot_frames / first_shot_audio so you can judge shot 1 before the chain commits.
Install and reality check
cd ComfyUI/custom_nodes
git clone https://github.com/jlucasmcrell/ComfyUI-H3-Multishot
or search H3 Multishot in ComfyUI-Manager (Registry: comfyui-h3-multishot). ComfyUI v0.30.0+, no pip dependencies. Models: checkpoint in models/diffusion_models/, encoder + VAEs in text_encoders/ and vae/. GGUF users also install ComfyUI-GGUF.
The pack is young - effectively zero community footprint on Reddit as of writing - and its README is refreshingly honest about limits: audio dulls slightly per hop on long chains (restart chains on scene cuts), and the texture ratchet is ~1.05-1.3x per join depending on settings. For 3-4 shot scenes the joins reviewed as one continuous take. It's a meticulous solo project (jlucasmcrell / joeygambino), free, and the docs are the best part of it - read the prompting rules before you queue, and a word clipped at a join is almost always your script, not the sampler.
Inputs (24)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| clip | CLIP | — | |
| video_vae | VAE | — | |
| audio_vae | VAE | — | |
| script | STRING | Shot 1 prompt goes here. --- Shot 2 prompt goes here. --- Shot 3 prompt goes here. | One prompt per shot, separated by --- on its own line. JSON {"prompts": [...]} also accepted. |
| shot_count | INT | 00–8 | The TOTAL number of shots - not shots per prompt. Leave it at 0 and the script decides: one shot per --- block, which is what you want for a written scene. 1-8 forces the total instead: extra blocks are dropped, and if the script is short the last block repeats as a continuation. Every shot renders. |
| width | INT | 76832–4096 | — |
| height | INT | 134432–4096 | — |
| frames_per_shot | INT | 2435–481 | Frames at 24fps on H3's 17k+5 grid (243 = ~10.1s; 362 = trained max ~15.1s; beyond is untested). |
| seed | INT | 00–18446744073709550000 | — |
| steps | INT | 201–50 | — |
| seed_per_shot | BOOLEAN | true | Leave ON. Measured: varying the seed per shot holds the face across the chain; using one seed for every shot made BOTH the face and the voice drift. Identity lives in the conditioning, not the seed. |
| start_imageopt | IMAGE | Optional first frame (I2V). Shot 1 starts from this image; later shots continue chaining from the previous shot's last frame as usual. Leave unconnected for pure text-to-video. | |
| reference_imagesopt | IMAGE | Optional SUBJECT/CHARACTER reference images (batch = multiple refs, e.g. via Batch Images), carried into EVERY shot as <Picture 1>, <Picture 2>, ... - distinct from start_image (which only seeds the I2V chain frame). Bind them in each shot's prompt: 'She looks like the woman in <Picture 1>.' Verified on the ref2va checkpoint. | |
| voice_refopt | AUDIO | Optional VOICE ANCHOR carried into EVERY shot as a reference audio (<Audio 1>). Feed a clean solo line of the character - e.g. a slice of stage A's output - and the voice is PINNED across the chain instead of re-performed from text (verified: control drifted, voice-ref held). Bind it in each shot's prompt: 'Her voice is the voice in <Audio 1>.' Works with keyframe chaining via the refs+keyframes merge patch. NOTE: verified on the ref2va checkpoint; fl2va was not trained with reference rows, so wire the ref2va model when using this. | |
| sampler_nameopt | COMBO | res_multistep | Sampling algorithm. res_multistep is the default and what every measurement in the docs used. |
| scheduleropt | COMBO | simple | Sigma schedule. simple is the default and what the docs measured. |
| sampler_overrideopt | STRING | Link a sampler NAME here (e.g. from H3 Studio Controls) to drive this widget from one master source. Overrides sampler_name when connected. | |
| scheduler_overrideopt | STRING | Link a scheduler NAME here to single-source it. Overrides scheduler when connected. | |
| self_anchor_voiceopt | BOOLEAN | false | AUTOMATIC voice identity: after shot 1 renders, its own audio becomes the reference (<Audio 1>) for every later shot - the voice the model actually performed is pinned, no file needed. Write shot 1 so the character speaks a clean solo line. An external voice_ref, if connected, takes priority. Use with a ref2va checkpoint. |
| output_scaleopt | FLOAT | 1.001–4 | FINAL size multiplier, applied after decode. No upscale model: a lanczos resize, 1.0 is off. WITH a model: the model runs at its OWN fixed factor (usually 4x) and this brings the result to source x this value, so 2.0 on a 4x model gives 2x, not 8x. CAREFUL - 1.0 does NOT mean off once a model is wired; it means do-not-correct, so you get the full 4x. At 1344x768 that is 5376x3072: 94 MB a frame, 22 GB a shot, and every shot stays in system RAM until the master is joined. The console prints the projected size when the model loads - read it. Adds resolution, not detail. Works with every continuity mode; the bank still stores base-resolution clips. |
| upscale_modelopt | UPSCALE_MODEL | Optional. Wire ComfyUI's Load Upscale Model here (ESRGAN and friends) to synthesise detail instead of merely resizing. Applied per shot after decode, at the model's own factor; if output_scale is also set, the result is resized to land exactly there. Slower than output_scale and it invents texture - on a chain, judge it on the LAST shot, where any texture ratchet is worst. | |
| sigmasopt | SIGMAS | Optional custom sigma schedule, replacing sampler/scheduler + steps entirely. Some turbo LoRAs ship a schedule they need in order to work at all. When this is connected the 'steps' and 'scheduler' widgets are IGNORED - the step count becomes len(sigmas)-1 - and the console says so. The two-pass upscale split is taken as a fraction of the supplied schedule. | |
| save_every_shotopt | BOOLEAN | false | Write EVERY shot to output/video/H3_SHOTS/ the moment it decodes, in addition to the master. Insurance for long chains: everything that fails after the last shot - a mux OOM, a full disk, a cancelled tab - otherwise destroys the whole render at once. Shots are written BEFORE the seam trim, so consecutive files overlap by ~1s; the master is still the clean join. Costs one file write per shot. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| master_frames | IMAGE | — |
| master_audio | AUDIO | — |
| shots_rendered | INT | — |
| first_shot_frames | IMAGE | — |
| first_shot_audio | AUDIO | — |