Nodes/PromptMasterLD/🎬 H3 Multishot - LD
ComfyUI Node

🎬 H3 Multishot - LD

The H3 Multishot Sampler, Tamed

By Lora-DaddyΒ·Created 6 days agoΒ·Updated 2 days agoΒ· 5
🎬 H3 Multishot - LD
  • model
  • clip
  • video_vae
  • audio_vae
  • start_image
  • reference_images
  • voice_ref
  • upscale_model
  • sigmas
  • sampler
  • latent
  • master_frames
  • master_audio
  • shots_rendered
β—„scriptShot 1 prompt goes here. --- Shot 2 prompt goes here. --- Shot 3 prompt goes here.β–Ί
β—„shot_count0β–Ί
β—„width768β–Ί
β—„height1344β–Ί
β—„frames_per_shot243β–Ί
β—„seed0β–Ί
β—„steps20β–Ί
β—„seed_per_shottrueβ–Ί
β—„sampler_nameres_multistepβ–Ί
β—„schedulersimpleβ–Ί
β—„sampler_overrideβ€”β–Ί
β—„scheduler_overrideβ€”β–Ί
β—„self_anchor_voicefalseβ–Ί
β—„output_scale1.00β–Ί
β—„save_every_shotfalseβ–Ί
β—„transitioncutβ–Ί
β—„transition_frames6β–Ί
β—„vram_guardfalseβ–Ί

Multishot is how you get past H3's fifteen-second wall

H3 samples a clip at a time - trained around 4–15 seconds, with a hard-ish ceiling beyond that. So a real scene is several clips that need to feel like one continuous take: same person, same voice, same room. The H3 Multishot Sampler exists for exactly that. It takes a ----separated script, samples each shot in sequence, and chains each one from the previous shot's last frame so the action carries across the boundary.

H3 Multishot - LD (🎬 H3 Multishot - LD, under LD / PromptMaster / Long form) is that upstream sampler with one important upgrade: H3 Studio's latent can drive it. Connect Studio's latent output and the node reads width, height and frames-per-shot from its shape - the FRAME bar in Studio becomes the only place size is decided, so the writer and the sampler physically cannot disagree. Leave latent unconnected and it behaves exactly like the original upstream node.

The two dials that decide whether your characters survive

  • script - one prompt per shot, --- on its own line between them. JSON {"prompts": [...]} also works.
  • shot_count - the total number of shots, not shots-per-prompt. 0 (the default) lets the script decide: one shot per --- block, which is what you want for a written scene. Force 1–8 and extra blocks get dropped.
  • seed_per_shot - leave it ON. This is the one the docs measured, and the result is counterintuitive: varying the seed per shot holds the face across the chain, while one seed for every shot made both the face and the voice drift. Identity lives in the conditioning, not the seed.

Then the reference slots: start_image seeds shot 1 for image-to-video; reference_images are character references carried into every shot as <Picture 1> etc.; voice_ref is a clean solo line of your character fed as <Audio 1> so the voice is pinned instead of re-performed each shot. If you don't have a clean vocal line, self_anchor_voice does it automatically - after shot 1 renders, its own audio becomes the reference for every later shot, no file needed. Write shot 1 so the character actually speaks.

The finishing stack

Two knobs do the quality work after decode: upscale_model (wire ComfyUI's Load Upscale Model - ESRGAN and friends - to synthesise real detail per shot) with output_scale as the final size multiplier, and transition (cut, or a fade/dissolve applied to rendered frames so it's exact - audio is ducked to match) with transition_frames for how long each side lasts. save_every_shot writes each shot to output/video/H3_SHOTS/ the moment it decodes - insurance against a mux OOM at the end of a long chain destroying everything. vram_guard evicts the DiT before each text encode; off by default because it costs a model swap per shot, but flip it on if you hit Fault failed: 2 on a card that doesn't fit.

You can also hand the sampler a SAMPLER node (the MiniMax H3 Turbo sampler included) or a SIGMAS schedule to replace its dropdowns, which is how a turbo or LoRA curve stays consistent across the whole chain.

Outputs and install

Outputs: master_frames (IMAGE), master_audio (AUDIO), and shots_rendered (INT) - the concatenated deliverable plus a count.

cd ComfyUI/custom_nodes
git clone https://github.com/Lora-Daddy/PromptMasterLD
cd PromptMasterLD
pip install -r requirements.txt

Restart (or ComfyUI Manager β†’ "PromptMasterLD"). This node wraps the vendored upstream ComfyUI-H3-Multishot, which the pack loads under the hood - install the pack and the sampler comes with it. The place people go wrong is almost always conditioning, not the sampler: feed it reference images of a different face than your first shot and watch the identity fight itself across the chain. Keep one face, one voice, one room, and let seed_per_shot do its counterintuitive thing.

CategoryLD/PromptMaster/Long form

Inputs (29)

NameTypeDefaultDescription
modelMODELβ€”
clipCLIPβ€”
video_vaeVAEβ€”
audio_vaeVAEβ€”
scriptSTRINGShot 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_countINT00–8The 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.
widthINT76832–4096Ignored when 'latent' is connected.
heightINT134432–4096Ignored when 'latent' is connected.
frames_per_shotINT2435–481Frames at 24fps on H3's 17k+5 grid (243 = ~10.1s; 362 = trained max ~15.1s; beyond is untested). Ignored when 'latent' is connected β€” the latent's frame count is ONE shot's length.
seedINT00–18446744073709550000β€”
stepsINT201–50Ignored when 'sigmas' is connected.
seed_per_shotBOOLEANtrueLeave 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_imageoptIMAGEOptional 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_imagesoptIMAGEOptional 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_refoptAUDIOOptional 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_nameoptCOMBOres_multistepSampling algorithm. res_multistep is the default and what every measurement in the docs used. Ignored when 'sampler' is connected.
scheduleroptCOMBOsimpleSigma schedule. simple is the default and what the docs measured. Ignored when 'sigmas' is connected.
sampler_overrideoptSTRINGLink a sampler NAME here (e.g. from H3 Studio Controls) to drive this widget from one master source. Overrides sampler_name when connected.
scheduler_overrideoptSTRINGLink a scheduler NAME here to single-source it. Overrides scheduler when connected.
self_anchor_voiceoptBOOLEANfalseAUTOMATIC 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_scaleoptFLOAT1.001–4FINAL 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_modeloptUPSCALE_MODELOptional. 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.
sigmasoptSIGMASAny SIGMAS node β€” the Scheduler already in the graph. Connected, it REPLACES scheduler + steps for every shot, so the single-shot and multishot paths cannot drift apart on step count.
save_every_shotoptBOOLEANfalseWrite 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.
transitionoptCOMBOcutWhat happens AT each shot boundary. 'cut' is the raw chained output. The fades are applied to the rendered frames, so they are exact β€” they do not depend on the model choosing to obey a prompt. Audio is ducked to match, so picture and sound dip together.
transition_framesoptINT61–48Length of EACH SIDE of the transition, in frames at 24fps. 6 gives a ~0.5s dip (6 out, 6 in). Ignored when transition is 'cut'.
vram_guardoptBOOLEANfalseOFF is identical to the upstream sampler. ON evicts the DiT before each shot's text encode and releases the encoder before each sample, which prevents 'aimdo … Fault failed: 2' when the models do not fit the card β€” at the cost of a full model swap per shot. On a 24GB card with a 27GB encoder that roughly doubled a six-shot render. Leave it off and drop the canvas instead; turn it on only if the fault comes back at a size you actually want.
sampleroptSAMPLERAny SAMPLER node β€” MiniMax-H3 Turbo Sampler (4-step), KSamplerSelect, anything that outputs SAMPLER. Connected, it REPLACES the sampler_name dropdown for every shot. This is how the Turbo sampler gets used in multishot: the dropdown can only name algorithms that live in comfy core, and Turbo is a node.
latentoptLATENTH3 Studio's latent output. Its shape sets width, height and frames_per_shot for EVERY shot, so the FRAME bar is the only place size is decided. The latent's contents are not sampled β€” the sampler builds a fresh empty latent per shot, as it always did.

Outputs (3)

NameTypeDescription
master_framesIMAGEβ€”
master_audioAUDIOβ€”
shots_renderedINTβ€”