From bd6abfc3e462cde9129a4195e0238eb3e4cb1b8b Mon Sep 17 00:00:00 2001 From: CalamitousFelicitousness Date: Tue, 18 Aug 2026 00:46:16 +0100 Subject: [PATCH] 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. --- modules/ltx/ltx_ui.py | 4 ++-- modules/ltx/ltx_util.py | 15 ++++++++++----- modules/video_models/video_ui.py | 29 +++++++++++++---------------- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/modules/ltx/ltx_ui.py b/modules/ltx/ltx_ui.py index 11f0d5cba..bd6cd709f 100644 --- a/modules/ltx/ltx_ui.py +++ b/modules/ltx/ltx_ui.py @@ -128,9 +128,9 @@ def create_ui(prompt, negative, styles, overrides, script_inputs, mp4_fps, mp4_i def load_model(model_name: str): - ltx_util.load_model('LTX Video', model_name) + return ltx_util.load_model('LTX Video', model_name) - btn_load.click(fn=load_model, inputs=[model], outputs=[]) + btn_load.click(fn=load_model, inputs=[model], outputs=[text]) model.change( fn=_model_change, diff --git a/modules/ltx/ltx_util.py b/modules/ltx/ltx_util.py index 914c86834..68e25f86a 100644 --- a/modules/ltx/ltx_util.py +++ b/modules/ltx/ltx_util.py @@ -19,22 +19,27 @@ def get_frames(frames: int): return int(8 * (int(frames) // 8)) + 1 -def load_model(engine: str, model: str): +def load_model(engine: str, model: str) -> str: if model is None or model == '' or model == 'None': shared.sd_model = None - return - t0 = time.time() + return 'Video model unloaded' from modules.video_models import models_def, video_load - selected: models_def.Model = [m for m in models_def.models[engine] if m.name == model][0] + selected = models_def.find(engine, model) + if selected is None: # the dropdown lists the separators it groups models under, and they name no model + msg = f'Video model not loaded: engine="{engine}" model="{model}"' + log.warning(msg) + return msg + t0 = time.time() # video_load owns the cache; pipe-class mismatch inside it invalidates the name-based hit # when Unload Models (or any external swap) silently replaced shared.sd_model. log.info(f'Load video: engine="{engine}" selected="{model}" {selected}') - video_load.load_model(selected) + msg = video_load.load_model(selected) t1 = time.time() shared.sd_model = sd_models.apply_balanced_offload(shared.sd_model) t2 = time.time() timer.process.add('load', t1 - t0) timer.process.add('offload', t2 - t1) + return msg or f'Video model loaded: {selected.name}' def upsample_pipe_stale(upsample_pipe, upsample_repo_id) -> bool: diff --git a/modules/video_models/video_ui.py b/modules/video_models/video_ui.py index 894082314..c67549da1 100644 --- a/modules/video_models/video_ui.py +++ b/modules/video_models/video_ui.py @@ -25,17 +25,12 @@ def engine_change(engine): def get_selected(engine, model): - found = [model.name for model in models_def.models.get(engine, [])] - if len(models_def.models[engine]) > 0 and len(found) > 0: - selected = [m for m in models_def.models[engine] if m.name == model][0] - return selected - return None + return models_def.find(engine, model) def model_change(engine, model): debug(f'Video change: engine="{engine}" model="{model}"') - found = [model.name for model in models_def.models.get(engine, [])] - selected = [m for m in models_def.models[engine] if m.name == model][0] if len(found) > 0 else None + selected = get_selected(engine, model) url = video_utils.get_url(selected.url if selected else None) return url @@ -43,19 +38,21 @@ def model_change(engine, model): def model_load(engine, model): debug(f'Load video: engine="{engine}" model="{model}"') selected = get_selected(engine, model) - yield f'Video model loading: {selected.name}' - if selected: - if 'None' in selected.name: + if selected is None: # the dropdown lists the separators it groups models under, and they name no model + if model and model.startswith('─'): + msg = 'Video model not loaded: dropdown separator selected' + elif model in (None, '', 'None'): sd_models.unload_model_weights() msg = 'Video model unloaded' else: - from modules.video_models import video_load - msg = video_load.load_model(selected) - else: - sd_models.unload_model_weights() - msg = 'Video model unloaded' + msg = f'Video model not found: engine="{engine}" model="{model}"' + log.warning(msg) + yield msg + return + yield f'Video model loading: {selected.name}' + from modules.video_models import video_load + msg = video_load.load_model(selected) yield msg - return msg def create_ui_outputs():