mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 09:14:35 +02:00
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.
This commit is contained in:
@@ -234,8 +234,6 @@ def run_ltx(task_id,
|
||||
condition_images = []
|
||||
if ltx_init_image is not None:
|
||||
condition_images.append(ltx_init_image)
|
||||
if condition_last is not None:
|
||||
condition_images.append(condition_last)
|
||||
conditions = []
|
||||
conditions_stage2 = []
|
||||
if caps.supports_multi_condition:
|
||||
@@ -246,14 +244,14 @@ def run_ltx(task_id,
|
||||
base_w, base_h, condition_strength,
|
||||
condition_images, condition_files, condition_video,
|
||||
condition_video_frames, condition_video_skip,
|
||||
family=caps.family,
|
||||
family=caps.family, num_frames=get_frames(frames), condition_last=condition_last,
|
||||
)
|
||||
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,
|
||||
family=caps.family, num_frames=get_frames(frames), condition_last=condition_last,
|
||||
)
|
||||
else:
|
||||
conditions_stage2 = conditions
|
||||
|
||||
@@ -16,6 +16,7 @@ def _model_change(model_name: str):
|
||||
return (
|
||||
gr.update(visible=False), # input_media_accordion
|
||||
gr.update(visible=False), # multi_condition_group
|
||||
gr.update(visible=False), # last_image
|
||||
gr.update(visible=False), # upsample_accordion
|
||||
gr.update(visible=False), # refine_accordion
|
||||
gr.update(value=False), # upsample_enable (reset)
|
||||
@@ -38,6 +39,7 @@ def _model_change(model_name: str):
|
||||
return (
|
||||
gr.update(visible=caps.supports_input_media),
|
||||
gr.update(visible=caps.supports_multi_condition),
|
||||
gr.update(visible=caps.supports_multi_condition), # last_image
|
||||
gr.update(visible=True),
|
||||
gr.update(visible=True),
|
||||
gr.update(value=False),
|
||||
@@ -73,7 +75,7 @@ def create_ui(prompt, negative, styles, overrides, mp4_fps, mp4_interpolate, mp4
|
||||
ltx_init_image = gr.Image(label='Image', elem_id='ltx_init_image', type='pil', image_mode='RGB', width=256, height=256)
|
||||
ltx_condition_strength = gr.Slider(label='LTX input strength', minimum=0.0, maximum=1.0, step=0.05, value=1.0, elem_id='ltx_condition_strength')
|
||||
with gr.Row():
|
||||
last_image = gr.Image(label='Last image', elem_id='ltx_last_image', type='pil', image_mode='RGB', width=256, height=256)
|
||||
last_image = gr.Image(label='Last image', elem_id='ltx_last_image', type='pil', image_mode='RGB', width=256, height=256, visible=False)
|
||||
multi_condition_group = gr.Group(visible=False)
|
||||
with multi_condition_group:
|
||||
gr.Markdown('**Prefix conditioning**: supply a video or gallery to anchor the opening frames', elem_id='ltx_prefix_conditioning_label')
|
||||
@@ -123,6 +125,7 @@ def create_ui(prompt, negative, styles, overrides, mp4_fps, mp4_interpolate, mp4
|
||||
outputs=[
|
||||
input_media_accordion,
|
||||
multi_condition_group,
|
||||
last_image,
|
||||
upsample_accordion,
|
||||
refine_accordion,
|
||||
upsample_enable,
|
||||
|
||||
+17
-5
@@ -138,15 +138,15 @@ def _condition_cls(family: str):
|
||||
return LTXVideoCondition
|
||||
|
||||
|
||||
def make_condition(condition_cls, family: str, frames, strength: float, is_video: bool):
|
||||
def make_condition(condition_cls, family: str, frames, strength: float, is_video: bool, index: int = 0):
|
||||
if family == '2.x':
|
||||
return condition_cls(frames=frames, index=0, strength=strength)
|
||||
return condition_cls(frames=frames, index=index, strength=strength)
|
||||
if is_video:
|
||||
return condition_cls(video=frames, frame_index=0, strength=strength)
|
||||
return condition_cls(image=frames, frame_index=0, strength=strength)
|
||||
return condition_cls(video=frames, frame_index=index, strength=strength)
|
||||
return condition_cls(image=frames, frame_index=index, strength=strength)
|
||||
|
||||
|
||||
def get_conditions(width, height, condition_strength, condition_images, condition_files, condition_video, condition_video_frames, condition_video_skip, family: str = '0.9'):
|
||||
def get_conditions(width, height, condition_strength, condition_images, condition_files, condition_video, condition_video_frames, condition_video_skip, family: str = '0.9', num_frames=None, condition_last=None):
|
||||
condition_cls = _condition_cls(family)
|
||||
if condition_cls is None:
|
||||
return []
|
||||
@@ -186,6 +186,18 @@ def get_conditions(width, height, condition_strength, condition_images, conditio
|
||||
log.debug(f'Video condition: family={family} frames={len(condition_frames)} size={condition_frames[0].size} strength={condition_strength}')
|
||||
except Exception as e:
|
||||
log.error(f'LTX condition video: {e}')
|
||||
if condition_last is not None:
|
||||
try:
|
||||
if isinstance(condition_last, str):
|
||||
from modules.api.api import decode_base64_to_image
|
||||
condition_last = decode_base64_to_image(condition_last)
|
||||
condition_last = condition_last.convert('RGB').resize((width, height), resample=Image.Resampling.LANCZOS)
|
||||
# 2.x reads index as a latent index and accepts -1 for the final frame; 0.9 uses a pixel index.
|
||||
last_index = -1 if family == '2.x' else max((num_frames or 1) - 1, 0)
|
||||
conditions.append(make_condition(condition_cls, family, condition_last, condition_strength, is_video=False, index=last_index))
|
||||
log.debug(f'Video condition: family={family} last={condition_last.size} index={last_index} strength={condition_strength}')
|
||||
except Exception as e:
|
||||
log.error(f'LTX condition last image: {e}')
|
||||
return conditions
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user