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.
This commit is contained in:
CalamitousFelicitousness
2026-04-25 04:21:45 +01:00
parent 5dbde4cbc4
commit 4dc8d659de
2 changed files with 18 additions and 5 deletions
+2 -2
View File
@@ -38,7 +38,7 @@ class LTXCaps:
guidance_rescale_default: float = 0.0
supports_canonical_stage2: bool = False
# Stage 1 at target/2 -> 2x upsample -> Stage 2 at target. Distilled needs upsampled latents
# for refine; same-res refine oversaturates. Condition variants would need per-stage rebuild.
# for refine; same-res refine oversaturates. Condition variants rebuild conditions per stage.
supports_two_stage_refine: bool = False
stage2_dev_lora_repo: Optional[str] = None
@@ -124,7 +124,7 @@ def get_caps(model_name: str) -> Optional[LTXCaps]:
elif variant == '2.0':
caps.stage2_dev_lora_repo = 'CalamitousFelicitousness/LTX-2.0-distilled-lora-384-Diffusers'
caps.supports_canonical_stage2 = caps.stage2_dev_lora_repo is not None
caps.supports_two_stage_refine = is_ltx2 and not is_condition_cls
caps.supports_two_stage_refine = is_ltx2
if is_ltx2:
if variant == '2.3':
+16 -3
View File
@@ -223,13 +223,26 @@ def run_ltx(task_id,
if condition_last is not None:
condition_images.append(condition_last)
conditions = []
conditions_stage2 = []
if caps.supports_multi_condition:
# Stage 1 conditions match base latent dims; Stage 2 rebuilds at final dims so frame
# indices and spatial sizes survive the 2x upsample. Same source PIL/file refs feed
# both calls; get_conditions handles the resize.
conditions = get_conditions(
width, height, condition_strength,
base_w, base_h, condition_strength,
condition_images, condition_files, condition_video,
condition_video_frames, condition_video_skip,
family=caps.family,
)
if (final_w, final_h) != (base_w, base_h):
conditions_stage2 = get_conditions(
final_w, final_h, condition_strength,
condition_images, condition_files, condition_video,
condition_video_frames, condition_video_skip,
family=caps.family,
)
else:
conditions_stage2 = conditions
sampler_name = processing.get_sampler_name(sampler_index)
sd_samplers.create_sampler(sampler_name, shared.sd_model)
@@ -439,8 +452,8 @@ def run_ltx(task_id,
refine_args['frame_rate'] = float(mp4_fps)
if caps.supports_image_cond_noise_scale and image_cond_noise_scale is not None:
refine_args['image_cond_noise_scale'] = image_cond_noise_scale
if caps.supports_multi_condition and conditions:
refine_args['conditions'] = conditions
if caps.supports_multi_condition and conditions_stage2:
refine_args['conditions'] = conditions_stage2
# Thread Stage-1 I2V init image through Stage 2 so first-frame identity survives refine.
if caps.is_i2v and caps.repo_cls_name in ('LTXImageToVideoPipeline', 'LTX2ImageToVideoPipeline') and p.task_args.get('image') is not None:
refine_args['image'] = p.task_args['image']