diff --git a/installer.py b/installer.py
index eda04a677..9e7e7e4b2 100644
--- a/installer.py
+++ b/installer.py
@@ -584,7 +584,7 @@ def check_diffusers():
t_start = time.time()
if args.skip_all:
return
- target_commit = "7564fb016dabda0c943416190fc92398c50b1b20" # diffusers commit hash == 0.40.0.dev0 == 08-11-2026
+ target_commit = "d5baa4fb548294f47dbca49890abd4b291204c60" # diffusers commit hash == 0.40.0.dev0 == 08-15-2026
# if args.use_rocm or args.use_zluda:
# sha = '043ab2520f6a19fce78e6e060a68dbc947edb9f9' # lock diffusers versions for now
pkg = package_spec('diffusers')
diff --git a/modules/devices.py b/modules/devices.py
index 114b1623a..ff7096530 100644
--- a/modules/devices.py
+++ b/modules/devices.py
@@ -548,7 +548,7 @@ def set_sdpa_params():
log.debug(f'Torch attention installed: flashattn={flash} sageattention={sage}')
from diffusers.models import attention_dispatch as a
- log.debug(f'Torch attention available: flash={a._CAN_USE_FLASH_ATTN} flash3={a._CAN_USE_FLASH_ATTN_3} aiter={a._CAN_USE_AITER_ATTN} sage={a._CAN_USE_SAGE_ATTN} flex={a._CAN_USE_FLEX_ATTN} npu={a._CAN_USE_NPU_ATTN} xla={a._CAN_USE_XLA_ATTN} xformers={a._CAN_USE_XFORMERS_ATTN} kernels={a.is_kernels_available()} sdnq=True') # pylint: disable=protected-access
+ log.debug(f'Torch attention available: flash={a._CAN_USE_FLASH_ATTN} flash3={a._CAN_USE_FLASH_ATTN_3} sage={a._CAN_USE_SAGE_ATTN} flex={a._CAN_USE_FLEX_ATTN} npu={a._CAN_USE_NPU_ATTN} xla={a._CAN_USE_XLA_ATTN} xformers={a._CAN_USE_XFORMERS_ATTN} kernels={a.is_kernels_available()} sdnq=True') # pylint: disable=protected-access
except Exception as e:
log.warning(f'Torch SDPA: {e}')
diff --git a/modules/loader.py b/modules/loader.py
index 14aea1c11..275afadae 100644
--- a/modules/loader.py
+++ b/modules/loader.py
@@ -11,7 +11,6 @@ from modules import timer, errors
from modules.logger import log
-log.info('Initializing: packages')
initialized = False
errors.install()
logging.getLogger("DeepSpeed").disabled = True
diff --git a/modules/ltx/ltx_process.py b/modules/ltx/ltx_process.py
index 3f4ba7257..5d8836f6e 100644
--- a/modules/ltx/ltx_process.py
+++ b/modules/ltx/ltx_process.py
@@ -698,5 +698,5 @@ def run_ltx(task_id,
progress.finish_task(task_id)
p.close()
- log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={t_end-t0:.2f} timers={timer.process.dct()} memory={memstats.memory_stats()}')
- yield video_file, f'LTX: Generation completed | File {video_file} | Frames {num_frames} | Resolution {resolution} | f/s {fps} | it/s {its} ' + f"
"
+ log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={t_end-t0:.2f} timers={timer.process.dct(no_total=True)} memory={memstats.memory_stats()}')
+ yield video_file, f'Video | File {video_file} | Frames {num_frames} | Resolution {resolution} | f/s {fps} | it/s {its} ' + f""
diff --git a/modules/minimax/minimax_video.py b/modules/minimax/minimax_video.py
index 4c6482fbb..60e6ffe46 100644
--- a/modules/minimax/minimax_video.py
+++ b/modules/minimax/minimax_video.py
@@ -3,7 +3,7 @@ import time
from PIL import Image
import numpy as np
from modules.logger import log
-from modules import shared, devices, processing, timer, progress, paths, sd_models, scripts_manager, call_queue, memstats, processing_video
+from modules import shared, devices, errors, processing, timer, progress, paths, sd_models, scripts_manager, call_queue, memstats, processing_video
from modules.video_models import models_def, video_save, video_utils
@@ -98,42 +98,6 @@ def generate(task_id, _ui_state,
progress.start_task(task_id)
memstats.reset_stats()
timer.process.reset()
- workflow = load_model(model) # override workflow based on loaded model
- if not workflow:
- progress.finish_task(task_id)
- log.error('Video: model not loaded')
- return None, 'Model not loaded'
- p = processing.StableDiffusionProcessingVideo(
- sd_model=shared.sd_model,
- video_engine=engine,
- video_model=model,
- prompt=prompt,
- styles=styles,
- seed=int(seed) if seed is not None else -1,
- steps=int(steps),
- width=width,
- height=height,
- frames=frames,
- do_not_save_grid=True,
- do_not_save_samples=not mp4_frames,
- outpath_samples=paths.resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_video),
- ops=['video'],
- )
- video_minimax.apply_overrides(p, shared.sd_model, still=False, audio=audio_enable)
- video_minimax.set_sampler_shift(shared.sd_model, video_shift=video_shift, audio_shift=audio_shift)
- log.debug(f'Video: engine="{engine}" model="{model}" workflow={workflow} cls={shared.sd_model.__class__.__name__} shift={video_shift}:{audio_shift} kwargs={p.task_args}')
- processing.fix_seed(p)
- p.ops.append('video')
- p.scripts = scripts_manager.scripts_video
- p.script_args = args
-
- prepare_inputs(workflow, p, init_image, last_image, reference_media)
-
- _processed: processing.Processed = scripts_manager.scripts_video.run(p, *args)
- processed = processing.process_images(p)
-
- sd_models.offload_ondemand(shared.sd_model, reason='finish', force=True) # force offload all loaded modules to cpu
- devices.torch_gc(force=True) # free gpu memory before saving video
# init vars
pixels = None
@@ -141,65 +105,109 @@ def generate(task_id, _ui_state,
video_file = None
aac_sample_rate = 32000
- audio = getattr(processed, 'audio', None) if audio_enable else None
- if audio is not None:
- audio = audio[0].float().cpu() if audio.ndim == 3 else audio.float().cpu()
- aac_sample_rate = getattr(shared.sd_model, 'audio_sampling_rate', 32000)
+ try:
+ workflow = load_model(model) # override workflow based on loaded model
+ if not workflow:
+ progress.finish_task(task_id)
+ log.error('Video: model not loaded')
+ return None, 'Model not loaded'
+ p = processing.StableDiffusionProcessingVideo(
+ sd_model=shared.sd_model,
+ video_engine=engine,
+ video_model=model,
+ prompt=prompt,
+ styles=styles,
+ seed=int(seed) if seed is not None else -1,
+ steps=int(steps),
+ width=width,
+ height=height,
+ frames=frames,
+ do_not_save_grid=True,
+ do_not_save_samples=not mp4_frames,
+ outpath_samples=paths.resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_video),
+ ops=['video'],
+ )
+ video_minimax.apply_overrides(p, shared.sd_model, still=False, audio=audio_enable)
+ video_minimax.set_sampler_shift(shared.sd_model, video_shift=video_shift, audio_shift=audio_shift)
+ log.debug(f'Video: engine="{engine}" model="{model}" workflow={workflow} cls={shared.sd_model.__class__.__name__} shift={video_shift}:{audio_shift} kwargs={p.task_args}')
+ processing.fix_seed(p)
+ p.ops.append('video')
+ p.scripts = scripts_manager.scripts_video
+ p.script_args = args
- images = getattr(processed, 'images', [])
- if isinstance(images, list):
- pixels = video_save.images_to_tensor(images)
- elif isinstance(images, np.ndarray):
- pixels = video_save.numpy_to_tensor(images)
- else:
- log.error(f'Video: images={images} type={type(images)} unsupported')
+ prepare_inputs(workflow, p, init_image, last_image, reference_media)
- if pixels is None:
- return None, "MiniMax: No frames generated"
+ _processed: processing.Processed = scripts_manager.scripts_video.run(p, *args)
+ processed = processing.process_images(p)
- if mp4_interpolate > 0:
- p.video_interpolate = mp4_interpolate
- from modules.processing_video import apply_video_interpolation
- # pixels is 5-D (N,C,T,H,W) in [-1,1]; RIFE needs 4-D (T,C,H,W) in [0,1]
- x = pixels.squeeze(0).permute(1, 0, 2, 3)
- x = (x.clamp(-1., 1.) + 1.0) * 0.5
- x = apply_video_interpolation(p, x, count=mp4_interpolate) # sets p.video_interpolated otherwise main save_video would do it also
- x = x * 2.0 - 1.0
- pixels = x.permute(1, 0, 2, 3).unsqueeze(0)
+ sd_models.offload_ondemand(shared.sd_model, reason='finish', force=True) # force offload all loaded modules to cpu
+ devices.torch_gc(force=True) # free gpu memory before saving video
- save_fps = mp4_fps * processing_video.interpolation_factor(p)
- num_frames, video_file, _thumb = video_save.save_video(
- p=p,
- pixels=pixels,
- audio=audio,
- mp4_fps=save_fps,
- mp4_codec=mp4_codec,
- mp4_opt=mp4_opt,
- mp4_ext=mp4_ext,
- mp4_sf=mp4_sf,
- mp4_video=mp4_video,
- mp4_frames=mp4_frames,
- mp4_thumb=mp4_thumb,
- mp4_interpolate=mp4_interpolate,
- aac_sample_rate=aac_sample_rate,
- metadata={},
- )
- _n, _c, _t, h, w = pixels.shape
- del pixels
- if audio is not None:
- del audio
+ audio = getattr(processed, 'audio', None) if audio_enable else None
+ if audio is not None:
+ audio = audio[0].float().cpu() if audio.ndim == 3 else audio.float().cpu()
+ aac_sample_rate = getattr(shared.sd_model, 'audio_sampling_rate', 32000)
+
+ images = getattr(processed, 'images', [])
+ if isinstance(images, list):
+ pixels = video_save.images_to_tensor(images)
+ elif isinstance(images, np.ndarray):
+ pixels = video_save.numpy_to_tensor(images)
+ else:
+ log.error(f'Video: images={images} type={type(images)} unsupported')
+
+ if pixels is None:
+ return None, "MiniMax: No frames generated"
+
+ if mp4_interpolate > 0:
+ p.video_interpolate = mp4_interpolate
+ from modules.processing_video import apply_video_interpolation
+ # pixels is 5-D (N,C,T,H,W) in [-1,1]; RIFE needs 4-D (T,C,H,W) in [0,1]
+ x = pixels.squeeze(0).permute(1, 0, 2, 3)
+ x = (x.clamp(-1., 1.) + 1.0) * 0.5
+ x = apply_video_interpolation(p, x, count=mp4_interpolate) # sets p.video_interpolated otherwise main save_video would do it also
+ x = x * 2.0 - 1.0
+ pixels = x.permute(1, 0, 2, 3).unsqueeze(0)
+
+ save_fps = mp4_fps * processing_video.interpolation_factor(p)
+ num_frames, video_file, _thumb = video_save.save_video(
+ p=p,
+ pixels=pixels,
+ audio=audio,
+ mp4_fps=save_fps,
+ mp4_codec=mp4_codec,
+ mp4_opt=mp4_opt,
+ mp4_ext=mp4_ext,
+ mp4_sf=mp4_sf,
+ mp4_video=mp4_video,
+ mp4_frames=mp4_frames,
+ mp4_thumb=mp4_thumb,
+ mp4_interpolate=mp4_interpolate,
+ aac_sample_rate=aac_sample_rate,
+ metadata={},
+ )
+ _n, _c, _t, h, w = pixels.shape
+ del pixels
+ if audio is not None:
+ del audio
+
+ except Exception as e:
+ log.error(f'Video: engine="{engine}" model="{model}" workflow={workflow} {e}')
+ errors.display(e, 'Video')
+ finally:
+ jobid = getattr(shared.sd_model, 'sdnext_phaseid', None) # previous jobid if any
+ shared.state.end(jobid) # clear the previous job if exists
+ progress.finish_task(task_id)
+ p.close()
t1 = time.time()
- progress.finish_task(task_id)
- p.close()
-
resolution = f'{w}x{h}' if num_frames > 0 else None
summary = timer.process.summary(min_time=0.25, total=False).replace('=', ' ')
memory = shared.mem_mon.summary()
total_time = max(t1 - t0, 1e-6)
fps = f'{num_frames/total_time:.2f}'
its = f'{(steps)/total_time:.3f}'
- log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={total_time:.2f} timers={timer.process.dct()} memory={memstats.memory_stats()}')
+ log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={total_time:.2f} timers={timer.process.dct(no_total=True)} memory={memstats.memory_stats()}')
- ui_text = f'MiniMax: Generation completed | File {video_file} | Frames {num_frames} | Resolution {resolution} | f/s {fps} | it/s {its} ' + f""
+ ui_text = f'Video | File {video_file} | Frames {num_frames} | Resolution {resolution} | f/s {fps} | it/s {its} ' + f""
return video_file, ui_text
diff --git a/modules/progress.py b/modules/progress.py
index 890ead043..409c2d69f 100644
--- a/modules/progress.py
+++ b/modules/progress.py
@@ -20,6 +20,7 @@ def start_task(id_task):
global current_task # pylint: disable=global-statement
current_task = id_task
pending_tasks.pop(id_task, None)
+ log.debug(f'State: start id={id_task} pending={len(pending_tasks)} finished={len(finished_tasks)}')
def record_results(id_task, res):
@@ -30,10 +31,12 @@ def record_results(id_task, res):
def finish_task(id_task):
global current_task # pylint: disable=global-statement
+ log.debug(f'State: end id={id_task}')
if current_task == id_task:
current_task = None
- finished_tasks.append(id_task)
- if len(finished_tasks) > 16:
+ if id_task not in finished_tasks:
+ finished_tasks.append(id_task)
+ if len(finished_tasks) > 1024*1024:
finished_tasks.pop(0)