Files
Meisoftcoltd-comfyui-sequen…/loop.py
T
Meisoftcoltd 9939314b2f Fix loop reverse cache with payload mutation and add debug logic
Replaced loop.py and image.py, and updated video.py to fix the 'reverse cache'
issue by injecting the new index directly into the ComfyUI API JSON payload.
Added large debug banners in Spanish, PNG keyframe extraction, and progressive MP4 saving.
2026-03-23 19:55:57 +00:00

114 lines
4.0 KiB
Python

import random
import time
import urllib.request
import json
from . import register_node
global_loop_index = 0
@register_node
class SequentialLoopStart:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"reset_loop": ("BOOLEAN", {"default": False}),
"loop_idx": ("INT", {"default": 0, "min": 0, "max": 10000}), # Inyectado por el Trigger
}
}
RETURN_TYPES = ("INT",)
RETURN_NAMES = ("current_loop_index",)
FUNCTION = "get_index"
CATEGORY = "🔁 Sequential Batcher/Loop"
@classmethod
def IS_CHANGED(cls, **kwargs):
return time.time()
def get_index(self, reset_loop, loop_idx):
global global_loop_index
print(f"\n{'='*50}")
print(f"🚀 [DEBUG] NODO: Loop Start")
print(f" -> Input loop_idx (UI/Trigger): {loop_idx}")
print(f" -> Input reset_loop: {reset_loop}")
is_reset = str(reset_loop).lower() in ['true', '1', 't', 'y']
if is_reset:
global_loop_index = 0
print(" -> 🔄 Bucle reiniciado a 0 manualmente.")
else:
global_loop_index = loop_idx
print(f" -> 📤 OUTPUT current_loop_index: {global_loop_index}")
print(f"{'='*50}\n")
return (global_loop_index, )
@register_node
class SequentialLoopTrigger:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"trigger_dependency": ("*", ),
"target_loops": ("INT", {"default": 4, "min": 1, "max": 1000}),
"port": ("INT", {"default": 8188, "min": 1000, "max": 9999}),
},
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"}
}
RETURN_TYPES = ()
RETURN_NAMES = ()
OUTPUT_NODE = True
FUNCTION = "trigger_next"
CATEGORY = "🔁 Sequential Batcher/Loop"
@classmethod
def IS_CHANGED(cls, **kwargs):
return time.time()
def trigger_next(self, trigger_dependency, target_loops, port, prompt=None, extra_pnginfo=None):
global global_loop_index
next_loop = global_loop_index + 1
print(f"\n{'='*50}")
print(f"🎯 [DEBUG] NODO: Loop Trigger")
print(f" -> Ciclo terminado: {global_loop_index} | Target: {target_loops}")
if next_loop < target_loops:
print(f" -> ⚙️ Preparando Ciclo {next_loop}...")
if prompt is not None:
m_seeds = 0
for node_id, node_data in prompt.items():
inputs = node_data.get("inputs", {})
# Mutar Semillas
for key in ["seed", "noise_seed"]:
if key in inputs and isinstance(inputs[key], (int, float)):
inputs[key] = random.randint(1, 0xffffffff)
m_seeds += 1
# 💥 INYECCIÓN ANTI-CACHÉ: Forzar a Loop Start a leer el nuevo índice
if node_data.get("class_type") == "SequentialLoopStart":
inputs["loop_idx"] = next_loop
inputs["reset_loop"] = False
print(f" -> 💉 Inyectado loop_idx={next_loop} en LoopStart (Nodo {node_id})")
print(f" -> 🎲 Semillas mutadas: {m_seeds}")
p = {"prompt": prompt}
if extra_pnginfo:
p["extra_data"] = {"extra_pnginfo": extra_pnginfo}
data = json.dumps(p).encode('utf-8')
req = urllib.request.Request(f"http://127.0.0.1:{port}/prompt", data=data, headers={'Content-Type': 'application/json'})
try:
urllib.request.urlopen(req, timeout=5)
print(f" -> ✅ Ciclo {next_loop} inyectado en la cola.")
except Exception as e:
print(f" -> ❌ Error HTTP: {e}")
else:
print(f" -> 🏁 ¡Generación finalizada! ({target_loops} ciclos)")
global_loop_index = 0
print(f"{'='*50}\n")
return ()