Merge pull request #67 from Meisoftcoltd/fix-silence-and-transparency-11065722630316388106

fix: Silence YOLO outputs and improve transparency in calculators
This commit is contained in:
Meisoft
2026-04-05 19:07:58 +02:00
committed by GitHub
5 changed files with 137 additions and 22 deletions
Binary file not shown.
Binary file not shown.
+14 -4
View File
@@ -97,16 +97,17 @@ class AutoLoopCalculatorLTX:
import math
from . import loop
total_effective_frames = source_frame_count // select_every_nth
potential_effective_frames = source_frame_count // select_every_nth
# Truncar al (8n + 1) más cercano hacia abajo
if total_effective_frames < 9:
safe_effective_frames = total_effective_frames # Too short, bypass
if potential_effective_frames < 9:
safe_effective_frames = 9 # Too short, bypass
else:
safe_effective_frames = ((total_effective_frames - 1) // 8) * 8 + 1
safe_effective_frames = ((potential_effective_frames - 1) // 8) * 8 + 1
safe_source_frame_count = safe_effective_frames * select_every_nth
loop.global_source_frame_count = safe_source_frame_count
effective_loss = potential_effective_frames - safe_effective_frames
# Ajuste proporcional forzando regla 8n + 1
estimated_loops = math.ceil(safe_effective_frames / target_frames_per_loop)
@@ -116,6 +117,15 @@ class AutoLoopCalculatorLTX:
adjusted_target = ((optimal_target - 1 + 7) // 8) * 8 + 1
target_frames_per_loop = adjusted_target
print(f" -> ⚖️ Ajuste Proporcional LTX: Target recalculado a {adjusted_target} frames por ciclo.")
# --- LOGS MEJORADOS Y TRANSPARENTES ---
print(f" -> 🎞️ Capacidad del video: {potential_effective_frames} frames procesables (Nth: {select_every_nth})")
if effective_loss > 0:
print(f" -> 🛡️ Ajuste VAE: Se usarán {safe_effective_frames} frames (Descarte técnico: {effective_loss} frame/s de proceso)")
else:
print(f" -> ✅ Ajuste VAE: Perfecto. Regla 8n+1 detectada.")
print(f" -> 📊 Timeline final: 0 a {safe_source_frame_count} (de {source_frame_count} totales)")
# -------------------------------------------------------------
loop.global_select_every_nth = select_every_nth
+70
View File
@@ -0,0 +1,70 @@
import sys
import types
import os
# Create dummy modules for comfyui dependencies
comfy_module = types.ModuleType("comfy")
comfy_mm_module = types.ModuleType("comfy.model_management")
comfy_module.model_management = comfy_mm_module
sys.modules["comfy"] = comfy_module
sys.modules["comfy.model_management"] = comfy_mm_module
folder_paths_module = types.ModuleType("folder_paths")
sys.modules["folder_paths"] = folder_paths_module
nodes_module = types.ModuleType("nodes")
sys.modules["nodes"] = nodes_module
# Mock torchaudio and torch
sys.modules["torch"] = types.ModuleType("torch")
sys.modules["torchaudio"] = types.ModuleType("torchaudio")
sys.modules["cv2"] = types.ModuleType("cv2")
sys.modules["numpy"] = types.ModuleType("numpy")
sys.modules["tqdm"] = types.ModuleType("tqdm")
def mock_tqdm(iter_obj, *args, **kwargs):
class DummyPbar:
def update(self, *args, **kwargs): pass
def close(self): pass
if isinstance(iter_obj, int):
return DummyPbar()
return iter_obj
sys.modules["tqdm"].tqdm = mock_tqdm
# Mock parent package for relative imports
dummy_pkg = types.ModuleType("dummy_pkg")
def mock_register_node(cls):
return cls
dummy_pkg.register_node = mock_register_node
sys.modules["dummy_pkg"] = dummy_pkg
# Overwrite sys.modules for testing so `from . import register_node` works
# We'll just load the file using importlib
import importlib.util
def load_module(name, path):
spec = importlib.util.spec_from_file_location(name, path)
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
# make it part of dummy_pkg
module.__package__ = "dummy_pkg"
spec.loader.exec_module(module)
return module
load_module("dummy_pkg.loop", "loop.py")
video = load_module("dummy_pkg.video", "video.py")
loop_mod = sys.modules["dummy_pkg.loop"]
# Run tests
calc_base = video.AutoLoopCalculator()
calc_wan = video.AutoLoopCalculatorWan()
calc_ltx = loop_mod.AutoLoopCalculatorLTX()
print("Testing base calculator...")
calc_base.calculate(source_frame_count=876, target_frames_per_loop=50, select_every_nth=8, current_loop_index=0)
print("\nTesting WanVideo calculator...")
calc_wan.calculate(source_frame_count=876, target_frames_per_loop=48, select_every_nth=8, current_loop_index=0)
print("\nTesting LTX calculator...")
calc_ltx.calculate(source_frame_count=876, target_frames_per_loop=81, select_every_nth=8, current_loop_index=0)
print("\nTests passed!")
+53 -18
View File
@@ -1,6 +1,7 @@
import os
import sys
from contextlib import redirect_stdout
import logging
from contextlib import redirect_stdout, redirect_stderr
from tqdm import tqdm
import math
import torch
@@ -141,25 +142,33 @@ class VideoAnalyzerWithAudio:
cap.set(cv2.CAP_PROP_POS_FRAMES, 0) # Volver al inicio
print(f" -> 🤖 Iniciando escaneo de rostros por GPU...")
for idx in tqdm(range(frame_count), desc="🔍 Escaneando frames", unit="frame"):
# Silenciamos el logger de ultralytics antes de empezar
logging.getLogger("ultralytics").setLevel(logging.ERROR)
# Barra de progreso profesional (desc=Descripción, unit=unidad, leave=True para que no desaparezca)
pbar = tqdm(total=frame_count, desc="🔍 Analizando Rostros", unit="frame", dynamic_ncols=True)
for idx in range(frame_count):
ret, frame = cap.read()
if not ret: break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
variance = cv2.Laplacian(gray, cv2.CV_64F).var()
faces_found = False
if variance > blur_threshold:
faces_found = False
if bbox_detector is not None:
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img_tensor = torch.from_numpy(frame_rgb.astype(np.float32) / 255.0).unsqueeze(0).cpu()
try:
# 🔇 SILENCIAMOS EL SPAM INTERNO DE ULTRALYTICS/YOLO
with open(os.devnull, 'w') as devnull, redirect_stdout(devnull):
# ⚠️ CORRECCIÓN: detect devuelve la tupla SEGS directamente
segs = bbox_detector.detect(img_tensor, 0.5, 0, 1.0, 10)
# 🤐 CÁPSULA DE VACÍO: Silenciamos TODO el ruido de la consola
with open(os.devnull, 'w') as fnull:
with redirect_stdout(fnull), redirect_stderr(fnull):
# Inferencia
segs = bbox_detector.detect(img_tensor, 0.5, 0, 1.0, 10)
if segs is not None:
# Formato ImpactPack: (shape, [lista_de_segs])
@@ -169,8 +178,8 @@ class VideoAnalyzerWithAudio:
# Otros formatos directos
elif isinstance(segs, list) and len(segs) > 0:
faces_found = True
except Exception as e:
print(f" -> ⚠️ Error en detector YOLO/ONNX: {e}")
except Exception:
pass # Fallback silencioso si el detector falla
elif HAS_OPENCV and use_face_detector:
# Fallback silencioso a OpenCV si el usuario no conectó el cable ONNX
@@ -180,6 +189,11 @@ class VideoAnalyzerWithAudio:
if faces_found:
safe_faces.append(idx)
# Actualizamos la barra una sola vez por frame
pbar.update(1)
pbar.close() # Cerramos la barra al terminar
print(f" -> ✅ Encontrados {len(safe_faces)} frames nítidos con rostros.")
else:
print(f" -> 🤖 Escaneo de rostros DESACTIVADO.")
@@ -217,14 +231,26 @@ class AutoLoopCalculator:
import math
from . import loop
total_effective_frames = source_frame_count // select_every_nth
safe_source_frame_count = total_effective_frames * select_every_nth
loop.global_source_frame_count = safe_source_frame_count
potential_effective_frames = source_frame_count // select_every_nth
safe_effective_frames = potential_effective_frames # Sin restricciones
estimated_loops = math.ceil(total_effective_frames / target_frames_per_loop)
safe_source_frame_count = safe_effective_frames * select_every_nth
loop.global_source_frame_count = safe_source_frame_count
effective_loss = potential_effective_frames - safe_effective_frames
estimated_loops = math.ceil(safe_effective_frames / target_frames_per_loop)
if estimated_loops > 0:
target_frames_per_loop = math.ceil(total_effective_frames / estimated_loops)
target_frames_per_loop = math.ceil(safe_effective_frames / estimated_loops)
print(f" -> ⚖️ Ajuste Proporcional: Target recalculado a {target_frames_per_loop} frames por ciclo.")
# --- LOGS MEJORADOS Y TRANSPARENTES ---
print(f" -> 🎞️ Capacidad del video: {potential_effective_frames} frames procesables (Nth: {select_every_nth})")
if effective_loss > 0:
print(f" -> 🛡️ Ajuste VAE: Se usarán {safe_effective_frames} frames (Descarte técnico: {effective_loss} frame/s de proceso)")
else:
print(f" -> ✅ Ajuste VAE: Perfecto. Múltiplo de 4 detectado.") # Manteniendo el mismo string por ahora o podemos omitirlo, lo adapto a que es genérico
print(f" -> 📊 Timeline final: 0 a {safe_source_frame_count} (de {source_frame_count} totales)")
# -------------------------------------------------------------
loop.global_select_every_nth = select_every_nth
@@ -343,11 +369,13 @@ class AutoLoopCalculatorWan:
# --- MEISOFT PATCH: Sincronización Matemática y Ajuste Proporcional ---
# 1. Truncado a múltiplo de 4 (Desechamos los 2-3 frames residuales)
total_effective_frames = source_frame_count // select_every_nth
safe_effective_frames = (total_effective_frames // 4) * 4
safe_source_frame_count = safe_effective_frames * select_every_nth
potential_effective_frames = source_frame_count // select_every_nth
safe_effective_frames = (potential_effective_frames // 4) * 4
safe_source_frame_count = safe_effective_frames * select_every_nth
loop.global_source_frame_count = safe_source_frame_count
effective_loss = potential_effective_frames - safe_effective_frames
loop.global_select_every_nth = select_every_nth
# 2. Ajuste Proporcional Real (Evitar micro-ciclos al final)
@@ -361,7 +389,14 @@ class AutoLoopCalculatorWan:
print(f" -> ⚖️ Ajuste Proporcional: Target recalculado de {target_frames_per_loop} a {adjusted_target} frames por ciclo (para {estimated_loops} ciclos)")
target_frames_per_loop = adjusted_target
print(f" -> 📊 Timeline ajustado para VAE: {safe_source_frame_count} / {source_frame_count} (Truncado {source_frame_count - safe_source_frame_count} frames)")
# --- LOGS MEJORADOS Y TRANSPARENTES ---
print(f" -> 🎞️ Capacidad del video: {potential_effective_frames} frames procesables (Nth: {select_every_nth})")
if effective_loss > 0:
print(f" -> 🛡️ Ajuste VAE: Se usarán {safe_effective_frames} frames (Descarte técnico: {effective_loss} frame/s de proceso)")
else:
print(f" -> ✅ Ajuste VAE: Perfecto. Múltiplo de 4 detectado.")
print(f" -> 📊 Timeline final: 0 a {safe_source_frame_count} (de {source_frame_count} totales)")
# -------------------------------------------------------------
current_pos = getattr(loop, 'global_accumulated_frames', 0)