Nodes/Joy-LTX 2.5 (JoyAI-Echo x LTX-2.5)/JoyLTX Multishot Sampler (LTX-2.5, AV-extend joins)
ComfyUI Node

JoyLTX Multishot Sampler (LTX-2.5, AV-extend joins)

One story, several shots, one video that stays seamless

By jlucasmcrell·Created 27 days ago·Updated 24 days ago· 2
JoyLTX Multishot Sampler (LTX-2.5, AV-extend joins)
  • model
  • clip
  • video_vae
  • audio_vae
  • upscale_model
  • start_image
  • shot_images
  • end_images
  • ref_images
  • images
  • audio
  • info
prompts
negativepc game, console game, video game, cartoon, childish, ugly
width960
height544
frames_per_shot193
shot_count0
joincontinue (AV extend: seamless take)
overlap3
seed553010
seed_per_shottrue
sampler_nameeuler_ancestral
sigmas_pass11.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0
two_passtrue
sigmas_pass20.85, 0.7250, 0.4219, 0.0
video_cfg1.00
audio_cfg1.00
frame_rate24
save_every_shotfalse
identity_refcuts only: frame from shot 1
identity_strength0.60
image_strength1.00
keyframe_strength0.80
ref_mask
ref_strength0.85

This is the node the whole pack is built around, and the idea is genuinely good: render each shot as its own generation - so VRAM only ever holds one shot's worth of latents - then join them into one video with an AV-extend. The previous shot's last frames and its sound are pinned into the head of the next one, so a take can be as long as you like with no visible seam, or you can cut between angles and keep the same voice. One story in, one video out, and the length of the final clip is not limited by your card.

The inputs split into two camps. The settings you'll touch on every project: prompts (the writer's {"prompts": [...]} JSON, or blocks separated by ---), width/height (960x544 default), frames_per_shot (8n+1 frames at 24 fps - 193 is 8 seconds), shot_count (0 = every prompt the writer produced), and join. The three join modes are the heart of the thing:

  • continue (AV extend: seamless take) pins the previous shot's last overlap latent frames - video and audio - at the head of the next. Same voice, same room, one continuous take across generations. The replayed head is trimmed on output.
  • cut (voice extends, new picture) pins only the audio tail: the voice carries straight across a picture cut, the picture is free to be a new angle. This is how you get dialogue continuity across a cut.
  • fresh pins nothing: independent shots, plain and simple.

Then the identity machinery, which is the second reason people buy into this pack. identity_ref (default "cuts only: frame from shot 1") attaches a frame of shot 1 to every later shot as an in-context keyframe reference - LTX-2.5 AddGuide, appended tokens that condition but never appear - so a cut to a new angle keeps the same face, clothes and room without any reference photos. identity_strength (0.6) is how hard it pulls: 0.4–0.7 gives you the same person with free composition, 1.0 is close to a first-frame copy. "All shots" also anchors continue mode to shot 1's look, which the tooltip notes fights slow texture drift on long takes.

The optional inputs are where reference photos enter: start_image (first frame of shot 1, image-to-video), shot_images (one image per shot, used as each shot's first frame in cut/fresh mode), end_images (one keyframe per shot at that shot's last frame - first→last-frame shots when combined with shot_images), and ref_images + ref_mask from Refs by Name or RefImage, which attach a reference photo per shot and lock each character's face and voice. two_pass (on by default) upscales each shot with the latent upsampler and refines - it needs upscale_model wired - and both passes pin the previous tail, so the refine never redraws the join. The distilled schedules ship as sigmas_pass1 (8 steps) and sigmas_pass2 (3 steps), with video_cfg and audio_cfg at 1.0. Leave those alone.

Outputs are images, audio, and info (a string logging what happened). save_every_shot writes each raw shot untrimmed to output/video/JOYLTX_SHOTS/ if you want the pieces.

Gotchas, from the pack's own code and README. Fewer, longer shots mean fewer joins: the README notes 4 × 30 s single-pass shots on 24 GB is a 2-minute take with three joins, so think in long takes. The "voice" in continue mode is pinned audio, so if a new speaker appears, the sampler has a mechanism to pin the audio from their own earlier shot instead of continuing the last voice. And one real trap the node defends against: an empty prompts input usually means the workflow file is a stale browser copy where ComfyUI dropped the link - reopen the workflow from the sidebar, don't rebuild it. Set up via the JoyLTX25 pack's install; if you're using the writer, expect occasional 503/empty responses from cloud models - pick another in the writer's list and rerun.

CategoryJoyLTX

Inputs (33)

NameTypeDefaultDescription
modelMODEL
clipCLIP
video_vaeVAE
audio_vaeVAE
promptsSTRINGThe writer's shot prompts: {"prompts": [...]} JSON or blocks separated by --- (wire the writer here, or paste your own).
negativeSTRINGpc game, console game, video game, cartoon, childish, ugly
widthINT960256–1920
heightINT544256–1920
frames_per_shotINT19325–14418n+1 frames per shot at 24 fps (193 = 8 s).
shot_countINT00–640 = every prompt the writer produced; N = the first N.
joinCOMBOcontinue (AV extend: seamless take)3 options: continue (AV extend: seamless take), cut (voice extends, new picture), fresh (independent shots)
overlapINT31–12Latent frames of the previous shot pinned at the head of the next one (3 = 17 pixel frames = 0.7 s). More = smoother join, less new content per shot.
seedINT5530100–18446744073709550000
seed_per_shotBOOLEANtrue
sampler_nameCOMBOeuler_ancestral44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
sigmas_pass1STRING1.0, 0.99375, 0.9875, 0.98125, 0.975, 0.909375, 0.725, 0.421875, 0.0distilled 8-step schedule
two_passBOOLEANtrueUpscale each shot with the latent upsampler and refine (needs upscale_model).
sigmas_pass2STRING0.85, 0.7250, 0.4219, 0.0
video_cfgFLOAT1.000–20
audio_cfgFLOAT1.000–20
frame_rateFLOAT2412–60
save_every_shotBOOLEANfalseAlso write each shot (untrimmed) as output/video/LTX_SHOTS/shot_*.mp4
identity_refCOMBOcuts only: frame from shot 1Keep the SAME people across shots without reference images: a frame of shot 1 (or the previous shot's last frame) is attached to every later shot as an in-context keyframe reference (LTX-2.5 AddGuide, appended tokens, cropped after sampling). 'cuts only' = cut/fresh modes; 'all shots' = also in continue mode (anchors the look to shot 1, which also fights slow texture drift on long takes).
identity_strengthFLOAT0.600–1How hard the reference pulls (attention weight of the appended keyframe). 0.4-0.7: same face/clothes/room, free composition; 1.0: near first-frame copy.
upscale_modeloptLATENT_UPSCALE_MODEL
start_imageoptIMAGEFirst frame of shot 1 (image-to-video).
shot_imagesoptIMAGEOne image per shot (batch); used as the first frame of each shot in cut/fresh mode (identity carry from your reference plates).
image_strengthoptFLOAT1.000–1
end_imagesoptIMAGEOne image per shot = keyframe at that shot's LAST frame (first->last-frame shots when combined with shot_images / identity).
keyframe_strengthoptFLOAT0.800–1How hard the end keyframes pull.
ref_imagesoptIMAGEOne REFERENCE PHOTO per shot (from JoyLTX Refs by Name, or any batch): attached to that shot as an in-context keyframe at frame 0 (appended tokens, cropped after pass 1) so the person in the photo is the person in the shot. Replaces the frame-of-shot-1 identity for shots that have a photo.
ref_maskoptSTRINGComma list, one token per shot from Refs by Name: the CHARACTER NAME of that shot ('-' = none). With names, the sampler locks each character to their own first rendered frame (visual lock) and their own audio tail (voice lock) in later shots. 1/0 also accepted (photo / no photo).
ref_strengthoptFLOAT0.850–1How hard a reference photo pulls (measured on one seed, 0.5/0.75/0.9/1.0). Below ~0.75 you get the hair and the clothes but a different face; 0.85-0.9 carries the face and the small things like glasses; 1.0 drags the photo's own room into the shot. Note the photograph does NOT carry age - the prompt has to say it.

Outputs (3)

NameTypeDescription
imagesIMAGE
audioAUDIO
infoSTRING