87 Commits

Author SHA1 Message Date
CalamitousFelicitousness 3f80bb05b0 docs(ltx): correct the refine default comment and stale file references
The refine-default comment claimed Condition variants are excluded from two-stage
refine, but supports_two_stage_refine has no such carve-out and ltx_process builds
a second condition set so conditioning survives the upsample. Two file references
had also drifted: ltx_process.py:179 moved, and the offload hook keying now lives
in sd_offload_balanced. Name the symbols instead of the line numbers.
2026-08-25 23:21:21 +01:00
Vladimir Mandic 1946892b7f improve memory reporting, explicit interpolation and minimax tracking
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-08-25 09:11:46 +02:00
Vladimir Mandic d239bfcde1 placeholder video upscale
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-08-21 10:26:17 +02:00
CalamitousFelicitousness 9c11929780 fix(ltx): place the 0.9 latent upsampler on the compute device
Its 2.x sibling always did, so only the 0.9 path hit a cpu weight against cuda
latents. Also logs why a run is refused, which until now travelled only in the
raised error.
2026-08-19 01:45:46 +01:00
CalamitousFelicitousness 8d69b011e1 feat(ltx): add a keyword core to the ltx runner
run_ltx reported failure by yielding a string, which is why LTX had no API.
run() is the core underneath: keyword arguments named as video_run.run names
them, a VideoResult back, VideoError out with 499 for an interrupt. The lock,
progress and summary stay in the adapter, whose signature is unchanged since
callers bind to it by keyword. Failure now closes the processing object and
deactivates networks, which abort never did.
2026-08-19 01:45:46 +01:00
CalamitousFelicitousness bd0ea5ee1b fix(ltx): resolve every conditioning source the same way
The gallery branch took an upload handle or a PIL image, so an encoded string
fell through to .convert and was logged as a failed condition. Strings now go
to the api decoder, which reads base64 and upload refs rather than paths.
2026-08-19 01:45:46 +01:00
CalamitousFelicitousness bd6abfc3e4 fix(video): resolve dropdown model selection through the registry
Both load buttons matched the dropdown value against the raw row list, so the
separators the list uses for grouping resolved to a row with no repo. The
loader returned early on that row without loading or reporting, and the ltx
tab went on to record load and offload timings for a load that never ran.

Selection now goes through models_def.find, which knows a separator names no
model, and both buttons say what happened. The ltx button had no output bound
at all, so its message went nowhere.
2026-08-18 00:46:16 +01:00
Vladimir Mandic 12bf006b00 improve state management
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-08-15 19:21:51 +02:00
Vladimir Mandic 807a9be6b5 del audio after processing
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-08-14 16:03:45 +02:00
Vladimir Mandic b0649e0ec1 group offloading changes
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-08-14 15:59:51 +02:00
Vladimir Mandic f8c86d0d57 change video defaults
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-08-14 12:16:22 +02:00
CalamitousFelicitousness 5cb6efea34 fix(ltx): apply the 2.5 stage-2 lora to the text connectors
The stage 2 LoRA stores its connector deltas as
diffusion_model.{video,audio}_embeddings_connector, but
LTX2LoraLoaderMixin.lora_state_dict recognizes connectors only under the 2.3
text_embedding_projection prefix. All 3544 keys are routed into the transformer
namespace and peft drops the 224 that land nowhere, leaving refine with a
transformer-only adapter.

Wrapping lora_state_dict moves those keys onto the connectors component using
the rename table from the convert_ltx2_to_diffusers script. The wrapper is inert
once no misrouted keys appear, so it needs no version check.
2026-08-14 03:39:01 +01:00
CalamitousFelicitousness 5814d5c4b3 feat(ltx): add the ltx-2.5 model family
2.5 reuses the LTX-2 pipeline classes, so it is described through the
capability table: Gemma 4 text encoder, cross-timestep conditioning, and the
upsampler and stage 2 LoRA that now ship inside the model repo. The repo
carries the distilled scheduler config, so Dev rows restore the terminal
shift, and the Dev transformer sits in transformer_full.

Distilled rows stop forcing dynamic shifting on, which remapped their sigma
schedule. Auto duration hands the clip length to the duration head.
2026-08-14 03:39:01 +01:00
CalamitousFelicitousness 45fc1a0243 fix(ltx): scope cached upsamplers and scheduler overrides to the run
The sampler shift override looked for flow_shift, which only UniPC-style
schedulers declare, so it never reached the flow-match schedulers 2.x uses.
Config keys are now restored only when the run wrote them, and a cached
upsampler is rebuilt once its repo or the model's VAE changes.
2026-08-14 03:39:01 +01:00
CalamitousFelicitousness 5735b8f47d fix(ltx): pin guidance and cross-timestep on every 2.x call path
Some paths left both to pipeline defaults, which track the current upstream
model: distilled picked up guidance it already bakes in, and 2.0 could land on
2.3's joint-sigma path.
2026-08-14 03:39:00 +01:00
Vladimir Mandic ad6f3d3e11 minimax ui
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-08-13 15:33:47 +02:00
Vladimir Mandic 0ddd0f7091 minimax-h3 i2i
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-08-13 11:23:57 +02:00
Vladimir Mandic e280938e79 add prompt enhance to ltx and fix audio
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-07-28 13:11:21 +02:00
Vladimir Mandic 9dec85040e video: support for scripts/extensions
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-07-28 10:43:58 +02:00
Vladimir Mandic b7944a1be9 video model loader
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-07-13 11:26:33 +02:00
Vladimir Mandic 98a7d17207 linting
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-07-03 22:05:33 +02:00
Vladimir Mandic b3cf481c11 Merge pull request #4970 from vladmandic/feat/video-models
Feat/video models
2026-07-01 11:11:57 +02:00
CalamitousFelicitousness b02a480e08 feat(ltx): wire last-frame conditioning into LTX tab
The LTX tab already collected a last-frame image but anchored every condition at index 0, so it never acted as a last frame. Build a separate condition for it at the final frame: index -1 for the 2.x family (latent index, negatives wrap) and num_frames-1 for 0.9 (pixel index). The Last image input now shows only for Condition models, the pipelines that accept multi-frame conditioning.
2026-06-30 23:00:36 +01:00
Vladimir Mandic 825b714753 cleanup
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-06-29 10:05:31 +02:00
Vladimir Mandic 37f0d7c1c1 fix ltx
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-06-26 10:52:51 +02:00
Ryan Meador 11096bc0aa feat(video): add thumbnail save toggle 2026-06-02 23:43:58 -04:00
Vladimir Mandic bd47b693d2 update transformers and cleanup ui labels
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-06-02 07:45:37 +02:00
Ryan Meador b63e5ceeae fix(ltx): align cached prompt tensors with device 2026-05-31 17:52:44 -04:00
Vladimir Mandic 5a4a1ff2a1 cleanup
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-05-28 12:11:01 +02:00
CalamitousFelicitousness 394d4e5b84 fix(ltx): patch connectors regression and group model dropdown
- monkey-patch LTX2ConnectorTransformer1d.forward to restore pre-#13564
  padding logic when the upstream torch.flip pattern is detected; fixes
  word-order scrambling in audio dialogue tracks
- reorganize LTX model entries into version-group separators (2.3 v1.1,
  2.3 v1.0, 2.0, 0.9.x) with base/distilled subgroups; separators are
  selectable no-ops handled in run_ltx
2026-05-21 03:01:51 +01:00
Vladimir Mandic f67562b912 - all guidance values set to -1 to enable using model defaults
- log default values used if not overriden by user
- rename inconsistent guidance variables:

p.cfg_scale
p.image_cfg_scale -> p.cfg_image
p.diffusers_guidance_rescale -> p.cfg_rescale
p.pag_scale -> p.cfg_true
p.pag_adaptive -> p.cfg_adaptive

Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-05-16 11:06:23 +02:00
Vladimir Mandic c8d6fd5cf8 Revert "much stricter ruff linting"
This reverts commit 310dbf1574.
2026-05-11 08:13:57 +02:00
Vladimir Mandic 310dbf1574 much stricter ruff linting
Co-authored-by: Copilot <copilot@github.com>
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2026-05-11 07:15:37 +02:00
CalamitousFelicitousness a37443d8f1 fix(ltx): wrap explicit encode_prompt in inference_context
Upstream LTX2 encode_prompt is not @torch.no_grad-decorated; only __call__
is. Calling encode_prompt directly from ltx_process recorded the full
Gemma3 forward graph.
2026-05-04 21:44:07 +01:00
CalamitousFelicitousness 4523e7c3ac fix(ltx,processing): address pr #4819 review
review feedback from vladmandic on commit 80fde086f.

- run_ltx: drop the inline random.seed() / randrange resolve and use
  processing.fix_seed(p) right after the StableDiffusionProcessingVideo
  construction. p.seed carries the resolved int across every stage
  (latent_pass, both upsample paths, refine, post-refine vae_decode).
  matches the existing fix_seed(p) call sites in img2img.py:30,
  video_run.py:101, xyz_grid.py:266 and 8 others.

- process_decode: add AudioFrameList(list) subclass and attach_audio
  helper to carry output.audio onto the returned frame list. mirrors
  the existing output.bytes early-return contract: samples.audio
  survives downstream so process_images_inner can collect it via the
  Processed.audio kwarg.

- drop the p.audio_capture transit in process_diffusers and the
  fallback read in process_images_inner. p is input params, not
  output state.
2026-05-04 02:52:42 +01:00
CalamitousFelicitousness 80fde086f9 fix(ltx): close three two-stage audit gaps
- resolve seed=-1 once at top of run_ltx and thread the int through every
  stage (StableDiffusionProcessingVideo, _latent_pass, upsample 0.9/2.x,
  refine, post-refine vae_decode). get_generator(-1) reseeds globally per
  call so each stage was rolling an uncorrelated value; p.seed now carries
  the resolved seed so reruns reproduce.

- pre-encode prompts via shared.sd_model.encode_prompt before the latent
  path; park the four tensors on CPU and pass them as prompt_embeds /
  *_attention_mask kwargs through _latent_pass and refine_args. Stage 2
  reuses Stage 1's embeds instead of re-running the text encoder. The
  manual encode is outside pipe.__call__ so the post-forward offload hook
  never fires; apply_balanced_offload(force=True) re-anchors the device
  map so the text encoder doesn't stay pinned through Stage 1.

- skip audio_vae.decode + vocoder on refine when audio_enable=False:
  output_type='latent' bypasses the internal audio + video decode and
  hands off to the post-refine vae_decode block. Per-step audio
  cross-attention still runs for video conditioning.
2026-05-03 06:18:56 +01:00
CalamitousFelicitousness 41ffa78438 fix(ltx): align stage 2 audio to canonical pr #13217
drop the project-specific stage 1 direct audio decode (a6870f7d2). smoke
testing showed broadband tinniness on distilled is BWE-bound, not stage 2
corruption, so the deviation didn't fix the underlying issue.

revert to canonical:
- _latent_pass returns video latents only; result.audio is unused.
- stage 2 receives audio_latents=None (default), prepare_audio_latents
  generates fresh gaussian noise, audio scheduler runs the 3 stage-2
  sigmas under identity guidance, video<->audio cross-attention
  conditions the audio branch.
- capture stage 2 result.audio[0].float().cpu() for save.

upstream evidence: pipeline_ltx2.py:937-940 documents audio_latents as
pre-generated noisy latents (initial gaussian, not stage 1 output); no
caller in diffusers threads stage outputs into the kwarg.

non-latent path is unchanged and continues to work via p.audio_capture.
2026-05-02 19:56:30 +01:00
CalamitousFelicitousness 207e7d8b3b fix(processing): preserve pipeline audio across process_decode
process_decode strips video pipeline output to a flat list of frames at the
PIL early-return (processing_diffusers.py:461-465), so any output.audio is
lost before processing.process_images returns. video pipelines that produce
synchronized audio (LTX-2 audio-capable models) were getting silent mp4s on
the non-latent path.

stash output.audio on p.audio_capture before process_decode runs and let
processing read it back as a fallback when samples is a flat list.

ltx_process non-latent branch strips the (B, 2, N) batch dim with [0] so
write_audio's .T+contiguous() path produces interleaved bytes for AAC s16.
2026-05-02 19:43:43 +01:00
CalamitousFelicitousness a6870f7d27 fix(ltx): decode stage 1 audio directly, discard stage 2 audio output
stop threading stage 1 audio_latents into stage 2 refine. Lightricks/LTX-2#126
reports the two-stage pipeline degrades audio quality, confirmed locally as
clean speech with tinny ambient/foley/music on the threaded path.

root cause: stage 2 prepare_audio_latents calls _create_noised_state at
noise_scale=0.909 (pipeline_ltx2.py:704-714, 598-603), keeping ~9% of stage 1
signal. 3 refine steps recover speech via video<->audio cross-attention but
not broadband content.

new path: _latent_pass decodes audio_latents to waveform via audio_vae +
vocoder mirroring pipeline_ltx2.py:1471-1473 exactly (input cast to
audio_vae.dtype, no module dtype mutation). stage 2 result.audio is
discarded; cross-attention still runs each block for video conditioning.
2026-05-02 19:42:59 +01:00
CalamitousFelicitousness 506f5e1c29 fix(ltx): audio toggle ux and audio mux stream registration
relabel toggle to 'LTX save audio' (default true) since audio always
generates on 2.x audio-capable models; the toggle gates mux only. hint
added to locale_en.json.

split add_audio_stream from write_audio. avformat_write_header runs on
first container.mux() and freezes the stream set, so audio added after
video packets has time_base=0/0 and raises 'Cannot rebase to zero time.'
atomic_save_video registers the audio stream before the encode loop.
2026-05-02 19:38:08 +01:00
CalamitousFelicitousness b48bf5236b fix(ltx): handle PIL list output from refine path in interpolation wiring
LTX refine pipe uses output_type='pil' so result.frames[0] returns a list, not a 5-D tensor. Convert via images_to_tensor before the helper sees it, mirroring what save_video already does for the same input.
2026-04-27 01:13:47 +01:00
CalamitousFelicitousness 6acde69467 feat(video): route video pipelines through interpolation helper
LTX, video_run, and framepack_worker bypass process_images_inner, so
they call apply_video_interpolation explicitly before save_video. Save
receives already-inflated frames; the sentinel guard skips its own pass.

- LTX and video_run scale mp4_fps by interpolation_factor(p) so duration
  is preserved instead of stretched (LTX is conditioned on source fps)
- FramePack pre-divides at gen time per get_latent_paddings, so save fps
  stays at mp4_fps; worker passes p=None so save call uses
  mp4_interpolate=0 to skip directly
- replaces the inline (mp4_interpolate+1) fps math at LTX with the
  helper-driven equivalent
2026-04-26 03:08:19 +01:00
CalamitousFelicitousness a2cccddee0 fix(ltx): scale fps to preserve duration with RIFE interpolation
LTX conditions the model on mp4_fps as the source frame rate, then
RIFE inflates frame count at save. Without compensation, save fps
stays equal to source fps and the video becomes (mp4_interpolate+1)x
slow-motion (e.g. 121 frames at 24 fps with mp4_interpolate=1 saved
as 242 frames at 24 fps = 10s instead of the intended 5s). Scale the
saved fps by the interpolation factor at the LTX call site so output
duration matches user intent.

FramePack already pre-divides mp4_fps at generation time (compute-
saving semantic baked into UI math), so it does not need this fix.
The pipelines now produce duration-correct output via two different
mechanisms; standardization is tracked for the RIFE-in-processing
follow-up.
2026-04-25 21:15:06 +01:00
CalamitousFelicitousness fb73256b5e fix(ltx): align Distilled Stage 2 with canonical recipe
Distilled refine ran without the scheduler swap and identity guidance
kwargs prescribed by huggingface/diffusers#13217; only Dev got that
setup via the supports_canonical_stage2 branch. Distilled is already
trained at identity but still needs the recipe applied to avoid the
four-way composition double-dipping on top of the distilled sigma
schedule (oversaturation/striping).

Unify the branches under family == '2.x'; gate only the LoRA load and
unload on supports_canonical_stage2.
2026-04-25 04:49:26 +01:00
CalamitousFelicitousness 4dc8d659de feat(ltx): two-stage refine for condition variants
Conditions were built once at the user's chosen resolution, so condition
variants either ran same-res for both stages (blocked by the previous
gate) or fed base-res conditions to a final-res refine on the manual
upsample+refine path. Build conditions twice when staging is active:
once at base dims for Stage 1, once at final dims for Stage 2. Drop the
condition-class exclusion from supports_two_stage_refine.
2026-04-25 04:21:45 +01:00
CalamitousFelicitousness 5dbde4cbc4 fix(ltx): two-stage refine for Distilled 2.x T2V/I2V
auto_refine_upsample gated on supports_canonical_stage2 (Dev-only LoRA
path), so Distilled refine ran same-res for both stages and oversaturated.
Split the gate: supports_two_stage_refine covers any 2.x non-condition
variant and drives the staging plan plus UI Refine default;
supports_canonical_stage2 stays Dev-only for the LoRA branch.
2026-04-25 04:17:27 +01:00
CalamitousFelicitousness 67c77f7c4f feat(ltx): default Refine on for Dev 2.x T2V/I2V
Lightricks' production recipe for Dev is Stage 1 + 2x upsample + Stage 2
refine. Until now the UI reset Refine to False on every model change, so
users picking Dev got a single-pass generation that does not match the
recommended flow. Default Refine to on for variants that support the
canonical Stage 2 recipe; multi-condition variants stay off.
2026-04-21 02:46:40 +01:00
CalamitousFelicitousness f72f89c993 chore(ltx): silent=True on run-internal offload walks
Modules already inventoried at load time; repeating the six-line dump at
each upsample or refine boundary is redundant. silent=True suppresses
the per-module DEBUG lines; op=init and Model class= INFO stay intact.
2026-04-21 02:14:52 +01:00
CalamitousFelicitousness b58f0ae282 fix(ltx): exclude shared VAE from upsample pipe balanced_offload
The upsample pipes receive shared.sd_model.vae as a constructor formality;
the forward pass is pure latent to latent. Main pipe already owns that
VAE's accelerate hook lifecycle, so walking it again from the upsample
pipe raises "Cannot copy out of meta tensor" when the main pipe has
offloaded params to meta. Skip it in the walk.
2026-04-21 02:13:58 +01:00
CalamitousFelicitousness f79e466183 refactor(ltx): rename temp_scheduler_opts to ltx_scheduler_opts
Per PR #4783 review; namespace the helper with the module.
2026-04-21 02:13:09 +01:00