From 6acde69467d97ec8a54294d05f5bff83db58642e Mon Sep 17 00:00:00 2001 From: CalamitousFelicitousness Date: Sun, 26 Apr 2026 03:08:19 +0100 Subject: [PATCH] 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 --- modules/framepack/framepack_worker.py | 11 ++++++++++- modules/ltx/ltx_process.py | 15 ++++++++++++--- modules/video_models/video_run.py | 13 ++++++++++++- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/modules/framepack/framepack_worker.py b/modules/framepack/framepack_worker.py index fdd9637c9..09b62b6cb 100644 --- a/modules/framepack/framepack_worker.py +++ b/modules/framepack/framepack_worker.py @@ -322,6 +322,15 @@ def worker( if is_last_section: break + if mp4_interpolate > 0: + from modules.processing_video import apply_video_interpolation + # history_pixels is 5-D (N,C,T,H,W) in [-1,1]; RIFE needs 4-D (T,C,H,W) in [0,1] + x = history_pixels.squeeze(0).permute(1, 0, 2, 3) + x = (x.clamp(-1., 1.) + 1.0) * 0.5 + x = apply_video_interpolation(None, x, count=mp4_interpolate) + x = x * 2.0 - 1.0 + history_pixels = x.permute(1, 0, 2, 3).unsqueeze(0) + total_generated_frames, _video_filename, _thumb = save_video( p=None, pixels=history_pixels, @@ -334,7 +343,7 @@ def worker( mp4_sf=mp4_sf, mp4_video=mp4_video, mp4_frames=mp4_frames, - mp4_interpolate=mp4_interpolate, + mp4_interpolate=0, pbar=pbar, stream=stream, metadata=metadata, diff --git a/modules/ltx/ltx_process.py b/modules/ltx/ltx_process.py index 1ec2ff53a..778b0452b 100644 --- a/modules/ltx/ltx_process.py +++ b/modules/ltx/ltx_process.py @@ -563,9 +563,18 @@ def run_ltx(task_id, except Exception: aac_sample_rate = 24000 - # LTX conditions the model on mp4_fps as the source frame rate; RIFE inflates frames at save time. - # Scale the saved fps by the interpolation factor so the output preserves the user's intended duration. - save_fps = mp4_fps * (mp4_interpolate + 1) if mp4_interpolate > 0 else mp4_fps + 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); 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) + x = x * 2.0 - 1.0 + pixels = x.permute(1, 0, 2, 3).unsqueeze(0) + # LTX is conditioned on mp4_fps as the source rate; scale saved fps to keep duration constant + from modules.processing_video import interpolation_factor + save_fps = mp4_fps * interpolation_factor(p) num_frames, video_file, _thumb = save_video( p=p, pixels=pixels, diff --git a/modules/video_models/video_run.py b/modules/video_models/video_run.py index 3454faf69..60acf1625 100644 --- a/modules/video_models/video_run.py +++ b/modules/video_models/video_run.py @@ -160,12 +160,23 @@ def generate(*args, **kwargs): else: audio = None + if mp4_interpolate > 0 and pixels is not None: + 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) + x = x * 2.0 - 1.0 + pixels = x.permute(1, 0, 2, 3).unsqueeze(0) + from modules.processing_video import interpolation_factor + save_fps = mp4_fps * interpolation_factor(p) _num_frames, video_file, _thumb = video_save.save_video( p=p, pixels=pixels, audio=audio, binary=processed.bytes, - mp4_fps=mp4_fps, + mp4_fps=save_fps, mp4_codec=mp4_codec, mp4_opt=mp4_opt, mp4_ext=mp4_ext,