Spaces:
Running on Zero
A newer version of the Gradio SDK is available: 6.27.0
title: LTX-2.5 Multiple Subject Reference
emoji: 🎭
colorFrom: indigo
colorTo: red
sdk: gradio
sdk_version: 6.26.0
app_file: app.py
python_version: '3.12'
pinned: false
short_description: Multi-subject reference images to video with LTX-2.5
startup_duration_timeout: 1h
models:
- LiconStudio/LTX-2.5-Multiple-Subject-Reference
- Lightricks/LTX-2.5-Diffusers
tags:
- ltx-2.5
- ic-lora
- multi-subject
- reference-to-video
- image-to-video
🎭 LTX-2.5 · Licon MSR V1
Up to four subject stills plus one scene still, named in the prompt (Image 1:,
Image 2:, Image 3: Scene, …), become a video with native audio that keeps every subject's
identity, clothing and the scene's look.
LiconStudio/LTX-2.5-Multiple-Subject-Reference
(rank 128, apache-2.0) on Lightricks/LTX-2.5
(22B, distilled), run through upstream diffusers.
How it works
Each reference still is repeated to 33 frames, VAE-encoded, given a learned slot embedding
and placed at a negative temporal position — slot i of N sits at pixel-frame
-(N - i), i.e. just before frame 0. The video tokens then retrieve subject identity through
the transformer's own self-attention. Reference tokens ride along at conditioning_mask = 1
(fully clean) and are cropped off before decoding.
| Base | Lightricks/LTX-2.5-Diffusers — distilled 22B DiT + Gemma-4 text encoder + video/audio VAEs. transformer_full/, prompt_enhancer/, diffusion_decoder/ and temporal_latent_upsampler/ are excluded from the snapshot |
| Adapter | LTX-2.5-Licon-MSR-V1.safetensors, strength 1.0. The file holds ComfyUI-style LoRA keys (only conversion: diffusion_model. → transformer.) and the non-LoRA reference_slot_embedding MLP, which is applied by hand |
| Code | diffusers main @ d57cecde — LTX2InContextPipeline, subclassed in msr.py |
| Hardware | ZeroGPU xlarge (96 GB). The 22B DiT plus the Gemma-4 encoder packs to ~71 GB, over the 48 GB slice |
| Output | 1280×704 @ 24 fps by default (1664×960 available), with LTX-2.5's native audio |
| Memory | expandable_segments:True. Stage 2 cycles ~1 GB activation buffers against a nearly full card; the default arena fragments and OOMs at 43k tokens where expandable segments complete in 87 s. Gemma and the connectors are released once each has produced its output |
Faithfulness to the reference implementation
The author's reference is a ComfyUI graph:
ComfyUI-LTX2.5-MSR plus
LTX2.5-MSR-sample-workflow.json. Every node is reproduced:
| ComfyUI node | Here |
|---|---|
ComfyUILTX25MSRICLoRALoader |
split_slot_state + load_lora_weights. The loader's metadata guards (reference_token_order=prepend, reference_slot_time_offsets=pic1_based_negative_time, reference_downscale_factor=1) hold for this checkpoint |
_resize_reference |
msr.msr_resize — 1:1 port. Subject slots letterbox onto a white canvas unless the source already covers the target in the same aspect family (landscape ≥ 1.25, portrait ≤ 0.8, else square), in which case centre-crop-resize; the background slot always centre-crop-resizes. Bilinear, no antialias, matching comfy.utils.common_upscale |
_slot_embedding |
msr.slot_embedding — slot_id/16 → [scaled, sin(scaled·f), cos(scaled·f)] → SiLU MLP → 128-dim code, added broadcast over the channel axis of the normalized reference latent. ComfyUI's LTX2 VAE normalizes inside encode (per_channel_statistics.normalize), which is exactly diffusers' _normalize_latents, so the two spaces agree |
LTXVAddGuide.append_keyframe(frame_idx=-(N-i)) |
coords[:, 0] += frame_offset / frame_rate after prepare_video_coords. ComfyUI adds the offset in pixel-frames before the model's × 1/frame_rate; prepare_video_coords applies the same causal shift + clamp(min=0) and has already divided, so the two are algebraically identical |
guide strength=1.0, no pixel mask |
ComfyUI's _build_guide_self_attention_mask returns None in that case, and diffusers builds no mask when conditioning_attention_strength == 1.0 — the stacks agree |
LTXVCropGuides |
output_type="latent" already returns only the base tokens |
PromptRelayEncode (one local segment) |
A single prompt textbox. With one segment the relay's token mask covers everything, so it reduces to encoding global + local concatenated — which is what the UI's prompt box is |
two ManualSigmas + two LTXVBaseSampler |
8 distilled sigmas at half resolution → ×2 latent upsample → 3 sigmas at full resolution, one torch.Generator threaded through both stages, MSR guide re-attached in stage 2 as in the graph |
CFGGuider cfg=1 / LTXVDualCFGGuider [1,1] |
every guidance knob explicitly zeroed (guidance_scale=1.0, stg_scale=0.0, modality_scale=1.0, guidance_rescale=0.0). The merged pipeline's defaults are SFT values and each adds a blended extra transformer pass that badly degrades distilled output |
LTXVAudioVAEDecode |
audio is decoded and muxed into the mp4 |
Deviations
- Resolution. The workflow renders 1664×960 × 361 frames (15 s). The default here is 1280×704 × 97 frames (4 s), which runs in 53 s so it fits comfortably in a visitor's ZeroGPU quota; both the workflow geometry (1664×960 × 97, 87 s) and 8 s at 1280×704 (73 s) are selectable under Advanced.
- Length ceiling. 76.2 GB stays resident during denoising and stage-2 activations cost
~0.33 MB per token, so the 96 GB slice tops out near 48k tokens. Combinations above 44,000
(
(latent_frames + slots × 5) × H/32 × W/32) are refused up front instead of dying in an OOM traceback — 15 s at the workflow resolution is simply out of reach here. - Tiled VAE decode. The final decode is tiled (untiled it wants >100 GB). Reference
encoding is not tiled, matching the node's
use_tiled_encode=False, with a tiled fallback only if it would OOM. use_keyframes_abs_pos_embeddingisTruein the transformer config, and ComfyUI applies that marker to first-frame tokens.LTX2InContextPipelinenever passesvideo_keyframes_mask, so it is skipped — but the parameter is zero-initialised in the base checkpoint and the LoRA does not train it, so the difference is exactly zero.
Examples
The three examples are the author's own validation references and prompts, taken verbatim from
validition_V1/
in the model repo (03, 06, 07 — the three shown on the model card), downscaled to 1280 px
and re-encoded as JPEG. The model repo is apache-2.0.
Licenses
Adapter: apache-2.0. Base model: the LTX-2 Community License.