Add console logging to all VFI interpolation nodes

Log mode/params, pass progress, chunk count, and output frame count
for BIM-VFI, EMA-VFI, SGM-VFI, and GIMM-VFI interpolation nodes.
Segment nodes also log their input frame range and target fps output range.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-14 21:14:11 +01:00
parent 2f1cc17f5c
commit 13a89c5831

View File

@@ -219,6 +219,7 @@ class BIMVFIInterpolate:
Interpolated frames as [M, C, H, W] tensor on storage_device
"""
for pass_idx in range(num_passes):
logger.info(f"BIM-VFI: pass {pass_idx + 1}/{num_passes}, {frames.shape[0]} -> {2 * frames.shape[0] - 1} frames")
new_frames = []
num_pairs = frames.shape[0] - 1
pairs_since_clear = 0
@@ -290,6 +291,18 @@ class BIMVFIInterpolate:
num_passes = {2: 1, 4: 2, 8: 3}[multiplier]
mult = multiplier
N = images.shape[0]
expected = mult * (N - 1) + 1
if use_target_fps:
if num_passes == 0:
expected = int(math.floor((N - 1) / source_fps * target_fps)) + 1
logger.info(f"BIM-VFI: {N} frames, {source_fps}fps -> {target_fps}fps (downsampling), expected output: {expected} frames")
else:
expected_target = int(math.floor((N - 1) / source_fps * target_fps)) + 1
logger.info(f"BIM-VFI: interpolating {N} frames, {source_fps}fps -> {target_fps}fps (oversample {mult}x, {num_passes} pass(es)), expected output: {expected_target} frames")
else:
logger.info(f"BIM-VFI: interpolating {N} frames, {mult}x ({num_passes} pass(es)), expected output: {expected} frames")
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if all_on_gpu:
@@ -314,6 +327,9 @@ class BIMVFIInterpolate:
if end == total_input:
break
if len(chunks) > 1:
logger.info(f"BIM-VFI: processing in {len(chunks)} chunk(s)")
# Calculate total progress steps across all chunks
total_steps = sum(self._count_steps(ce - cs, num_passes) for cs, ce in chunks)
pbar = ProgressBar(total_steps)
@@ -353,6 +369,7 @@ class BIMVFIInterpolate:
# Convert back to ComfyUI [B, H, W, C], on CPU
result = result.cpu().permute(0, 2, 3, 1)
logger.info(f"BIM-VFI: done, {result.shape[0]} output frames")
return (result, oversampled)
@@ -401,6 +418,7 @@ class BIMVFISegmentInterpolate(BIMVFIInterpolate):
return (images[:1], model)
segment_images = images[start:end]
logger.info(f"BIM-VFI segment {segment_index}: input frames [{start}:{end}] of {total_input}")
if use_target_fps:
num_passes, mult = _compute_target_fps_params(source_fps, target_fps)
@@ -420,6 +438,8 @@ class BIMVFISegmentInterpolate(BIMVFIInterpolate):
if j_start > j_end:
return (images[:1], model)
logger.info(f"BIM-VFI segment {segment_index}: target fps output j=[{j_start}..{j_end}]")
if num_passes == 0:
# Downsampling — select from segment input directly
oversampled_fps = source_fps * mult
@@ -750,6 +770,7 @@ class EMAVFIInterpolate:
clear_cache_after_n_frames, pbar, step_ref):
"""Run all interpolation passes on a chunk of frames."""
for pass_idx in range(num_passes):
logger.info(f"EMA-VFI: pass {pass_idx + 1}/{num_passes}, {frames.shape[0]} -> {2 * frames.shape[0] - 1} frames")
new_frames = []
num_pairs = frames.shape[0] - 1
pairs_since_clear = 0
@@ -820,6 +841,18 @@ class EMAVFIInterpolate:
num_passes = {2: 1, 4: 2, 8: 3}[multiplier]
mult = multiplier
N = images.shape[0]
expected = mult * (N - 1) + 1
if use_target_fps:
if num_passes == 0:
expected = int(math.floor((N - 1) / source_fps * target_fps)) + 1
logger.info(f"EMA-VFI: {N} frames, {source_fps}fps -> {target_fps}fps (downsampling), expected output: {expected} frames")
else:
expected_target = int(math.floor((N - 1) / source_fps * target_fps)) + 1
logger.info(f"EMA-VFI: interpolating {N} frames, {source_fps}fps -> {target_fps}fps (oversample {mult}x, {num_passes} pass(es)), expected output: {expected_target} frames")
else:
logger.info(f"EMA-VFI: interpolating {N} frames, {mult}x ({num_passes} pass(es)), expected output: {expected} frames")
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if all_on_gpu:
@@ -844,6 +877,9 @@ class EMAVFIInterpolate:
if end == total_input:
break
if len(chunks) > 1:
logger.info(f"EMA-VFI: processing in {len(chunks)} chunk(s)")
# Calculate total progress steps across all chunks
total_steps = sum(self._count_steps(ce - cs, num_passes) for cs, ce in chunks)
pbar = ProgressBar(total_steps)
@@ -883,6 +919,7 @@ class EMAVFIInterpolate:
# Convert back to ComfyUI [B, H, W, C], on CPU
result = result.cpu().permute(0, 2, 3, 1)
logger.info(f"EMA-VFI: done, {result.shape[0]} output frames")
return (result, oversampled)
@@ -930,6 +967,7 @@ class EMAVFISegmentInterpolate(EMAVFIInterpolate):
return (images[:1], model)
segment_images = images[start:end]
logger.info(f"EMA-VFI segment {segment_index}: input frames [{start}:{end}] of {total_input}")
if use_target_fps:
num_passes, mult = _compute_target_fps_params(source_fps, target_fps)
@@ -948,6 +986,8 @@ class EMAVFISegmentInterpolate(EMAVFIInterpolate):
if j_start > j_end:
return (images[:1], model)
logger.info(f"EMA-VFI segment {segment_index}: target fps output j=[{j_start}..{j_end}]")
if num_passes == 0:
oversampled_fps = source_fps * mult
all_seg = segment_images.permute(0, 3, 1, 2)
@@ -1144,6 +1184,7 @@ class SGMVFIInterpolate:
clear_cache_after_n_frames, pbar, step_ref):
"""Run all interpolation passes on a chunk of frames."""
for pass_idx in range(num_passes):
logger.info(f"SGM-VFI: pass {pass_idx + 1}/{num_passes}, {frames.shape[0]} -> {2 * frames.shape[0] - 1} frames")
new_frames = []
num_pairs = frames.shape[0] - 1
pairs_since_clear = 0
@@ -1214,6 +1255,18 @@ class SGMVFIInterpolate:
num_passes = {2: 1, 4: 2, 8: 3}[multiplier]
mult = multiplier
N = images.shape[0]
expected = mult * (N - 1) + 1
if use_target_fps:
if num_passes == 0:
expected = int(math.floor((N - 1) / source_fps * target_fps)) + 1
logger.info(f"SGM-VFI: {N} frames, {source_fps}fps -> {target_fps}fps (downsampling), expected output: {expected} frames")
else:
expected_target = int(math.floor((N - 1) / source_fps * target_fps)) + 1
logger.info(f"SGM-VFI: interpolating {N} frames, {source_fps}fps -> {target_fps}fps (oversample {mult}x, {num_passes} pass(es)), expected output: {expected_target} frames")
else:
logger.info(f"SGM-VFI: interpolating {N} frames, {mult}x ({num_passes} pass(es)), expected output: {expected} frames")
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if all_on_gpu:
@@ -1238,6 +1291,9 @@ class SGMVFIInterpolate:
if end == total_input:
break
if len(chunks) > 1:
logger.info(f"SGM-VFI: processing in {len(chunks)} chunk(s)")
# Calculate total progress steps across all chunks
total_steps = sum(self._count_steps(ce - cs, num_passes) for cs, ce in chunks)
pbar = ProgressBar(total_steps)
@@ -1277,6 +1333,7 @@ class SGMVFIInterpolate:
# Convert back to ComfyUI [B, H, W, C], on CPU
result = result.cpu().permute(0, 2, 3, 1)
logger.info(f"SGM-VFI: done, {result.shape[0]} output frames")
return (result, oversampled)
@@ -1324,6 +1381,7 @@ class SGMVFISegmentInterpolate(SGMVFIInterpolate):
return (images[:1], model)
segment_images = images[start:end]
logger.info(f"SGM-VFI segment {segment_index}: input frames [{start}:{end}] of {total_input}")
if use_target_fps:
num_passes, mult = _compute_target_fps_params(source_fps, target_fps)
@@ -1342,6 +1400,8 @@ class SGMVFISegmentInterpolate(SGMVFIInterpolate):
if j_start > j_end:
return (images[:1], model)
logger.info(f"SGM-VFI segment {segment_index}: target fps output j=[{j_start}..{j_end}]")
if num_passes == 0:
oversampled_fps = source_fps * mult
all_seg = segment_images.permute(0, 3, 1, 2)
@@ -1555,6 +1615,7 @@ class GIMMVFIInterpolate:
clear_cache_after_n_frames, pbar, step_ref):
"""Single-pass interpolation using GIMM-VFI's arbitrary timestep capability."""
num_intermediates = multiplier - 1
logger.info(f"GIMM-VFI: single-pass {multiplier}x, {frames.shape[0]} input frames, {num_intermediates} intermediates/pair")
new_frames = []
num_pairs = frames.shape[0] - 1
pairs_since_clear = 0
@@ -1599,6 +1660,7 @@ class GIMMVFIInterpolate:
clear_cache_after_n_frames, pbar, step_ref):
"""Recursive 2x interpolation (standard approach, same as other models)."""
for pass_idx in range(num_passes):
logger.info(f"GIMM-VFI: pass {pass_idx + 1}/{num_passes}, {frames.shape[0]} -> {2 * frames.shape[0] - 1} frames")
new_frames = []
num_pairs = frames.shape[0] - 1
pairs_since_clear = 0
@@ -1671,6 +1733,18 @@ class GIMMVFIInterpolate:
else:
mult = multiplier
N = images.shape[0]
expected = mult * (N - 1) + 1
if use_target_fps:
if num_passes == 0:
expected = int(math.floor((N - 1) / source_fps * target_fps)) + 1
logger.info(f"GIMM-VFI: {N} frames, {source_fps}fps -> {target_fps}fps (downsampling), expected output: {expected} frames")
else:
expected_target = int(math.floor((N - 1) / source_fps * target_fps)) + 1
logger.info(f"GIMM-VFI: interpolating {N} frames, {source_fps}fps -> {target_fps}fps (oversample {mult}x, {num_passes} pass(es)), expected output: {expected_target} frames")
else:
logger.info(f"GIMM-VFI: interpolating {N} frames, {mult}x ({num_passes if not single_pass else 'single-pass'}), expected output: {expected} frames")
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if not single_pass or use_target_fps:
@@ -1701,6 +1775,9 @@ class GIMMVFIInterpolate:
if end == total_input:
break
if len(chunks) > 1:
logger.info(f"GIMM-VFI: processing in {len(chunks)} chunk(s)")
# Calculate total progress steps across all chunks
if single_pass:
total_steps = sum(ce - cs - 1 for cs, ce in chunks)
@@ -1750,6 +1827,7 @@ class GIMMVFIInterpolate:
# Convert back to ComfyUI [B, H, W, C], on CPU
result = result.cpu().permute(0, 2, 3, 1)
logger.info(f"GIMM-VFI: done, {result.shape[0]} output frames")
return (result, oversampled)
@@ -1797,6 +1875,7 @@ class GIMMVFISegmentInterpolate(GIMMVFIInterpolate):
return (images[:1], model)
segment_images = images[start:end]
logger.info(f"GIMM-VFI segment {segment_index}: input frames [{start}:{end}] of {total_input}")
if use_target_fps:
num_passes, mult = _compute_target_fps_params(source_fps, target_fps)
@@ -1815,6 +1894,8 @@ class GIMMVFISegmentInterpolate(GIMMVFIInterpolate):
if j_start > j_end:
return (images[:1], model)
logger.info(f"GIMM-VFI segment {segment_index}: target fps output j=[{j_start}..{j_end}]")
if num_passes == 0:
oversampled_fps = source_fps * mult
all_seg = segment_images.permute(0, 3, 1, 2)