Merge pull request #19 from Meisoftcoltd/fix/simplify-loop-index-reset-9730679421414511812
Simplify flow by using current_loop_index for internal state reset
This commit is contained in:
@@ -74,15 +74,15 @@ Video models produce many frames that can easily exceed 24GB VRAM.
|
||||
- **🎞️ Latent Batch To List**: Splits video latents frame-by-frame for VRAM-safe processing.
|
||||
- **🎞️ Latent List To Batch**: Merges individual frames back into a video latent batch.
|
||||
- **⏳ Progress Bar**: Generates a visual progress indicator.
|
||||
- **📤 Session Image Sender** & **📥 Session Image Receiver**: A powerful Sender/Receiver pattern designed to pass the *last frame* of an image batch into the *first frame* of the next Auto Queue cycle. This avoids ComfyUI's cyclic dependency errors, allowing for infinite, continuous video generation loops.
|
||||
- **📤 Session Image Sender** & **📥 Session Image Receiver**: A powerful Sender/Receiver pattern designed to pass the *last frame* of an image batch into the *first frame* of the next Auto Queue cycle. This avoids ComfyUI's cyclic dependency errors, allowing for infinite, continuous video generation loops. The Receiver now accepts the `current_loop_index` and automatically clears its session memory when the loop resets to `0`.
|
||||
|
||||
### 🎞️ Video Category (`🔁 Sequential Batcher/Video`)
|
||||
- **🛡️ Wan Frame Validator**: Ensures video frame counts comply with Wan's strict 4k+1 architecture to prevent skipped or duplicated keyframes.
|
||||
- **🎞️ FFmpeg Video Stitcher**: Final node in a video loop. Waits for the entire sequential batch to finish and stitches the video chunks together using FFmpeg without re-encoding.
|
||||
- *Input*: `video_paths` (List of VHS_FILENAMES), `output_filename` (String).
|
||||
- *Output*: `final_video_path` (Path to the stitched video).
|
||||
- **🎞️ Incremental Auto-Stitcher**: Incremental stitching node designed specifically for Auto Queue cycles. It runs immediately after each chunk is saved and extracts the `.mp4` absolute paths strictly from the `VHS_FILENAMES` output JSON. It maintains an active session memory (which clears on ComfyUI restart) to stitch *only* the videos generated during the current session, guaranteeing immunity to old/garbage files in the output directory.
|
||||
- *Input*: `trigger` (VHS_FILENAMES list/JSON), `output_filename` (String), `reset_list` (Boolean: toggle True once to manually flush the session memory and start a fresh video).
|
||||
- **🎞️ Incremental Auto-Stitcher**: Incremental stitching node designed specifically for Auto Queue cycles. It runs immediately after each chunk is saved and extracts the `.mp4` absolute paths strictly from the `VHS_FILENAMES` output JSON. It maintains an active session memory to stitch *only* the videos generated during the current loop cycle, guaranteeing immunity to old/garbage files in the output directory.
|
||||
- *Input*: `trigger` (VHS_FILENAMES list/JSON), `output_filename` (String), `current_loop_index` (Integer: connects to the loop index to automatically flush the session memory on the first cycle).
|
||||
- *Output*: `final_video_path` (Path to the incrementally stitched final video).
|
||||
|
||||
---
|
||||
|
||||
+3
-3
@@ -74,15 +74,15 @@ Los modelos de vídeo generan muchos fotogramas que pueden superar fácilmente l
|
||||
- **🎞️ Latent Batch To List**: Divide latentes de vídeo fotograma a fotograma para un procesamiento seguro en VRAM.
|
||||
- **🎞️ Latent List To Batch**: Une fotogramas individuales de nuevo en un lote latente de vídeo.
|
||||
- **⏳ Progress Bar**: Genera un indicador visual de progreso.
|
||||
- **📤 Session Image Sender** y **📥 Session Image Receiver**: Un patrón Emisor/Receptor diseñado para enviar el *último fotograma* de un lote como el *primer fotograma* del siguiente ciclo de Auto Queue. Esto evita los errores de dependencias cíclicas en ComfyUI y permite bucles de generación de vídeo continuos e infinitos.
|
||||
- **📤 Session Image Sender** y **📥 Session Image Receiver**: Un patrón Emisor/Receptor diseñado para enviar el *último fotograma* de un lote como el *primer fotograma* del siguiente ciclo de Auto Queue. Esto evita los errores de dependencias cíclicas en ComfyUI y permite bucles de generación de vídeo continuos e infinitos. El Receiver ahora acepta el `current_loop_index` y vacía automáticamente su memoria de sesión cuando el bucle vuelve a `0`.
|
||||
|
||||
### 🎞️ Categoría Vídeo (`🔁 Sequential Batcher/Video`)
|
||||
- **🛡️ Wan Frame Validator**: Garantiza que el recuento de fotogramas de vídeo cumpla estrictamente con la arquitectura 4k+1 de Wan, evitando fotogramas clave omitidos o duplicados.
|
||||
- **🎞️ FFmpeg Video Stitcher**: Nodo final en un bucle de vídeo. Espera a que termine todo el lote secuencial y une los fragmentos de vídeo utilizando FFmpeg sin recodificar.
|
||||
- *Entrada*: `video_paths` (Lista de VHS_FILENAMES), `output_filename` (Cadena de texto).
|
||||
- *Salida*: `final_video_path` (Ruta del vídeo ensamblado).
|
||||
- **🎞️ Incremental Auto-Stitcher**: Nodo de ensamblaje incremental diseñado específicamente para ciclos de Auto Queue. Se ejecuta inmediatamente después de que cada fragmento es guardado y extrae de manera estricta las rutas `.mp4` del JSON de salida que genera `VHS_FILENAMES`. Mantiene una lista en la memoria de la sesión activa (que se vacía automáticamente al reiniciar ComfyUI) para ensamblar *únicamente* los vídeos generados durante la sesión actual, garantizando inmunidad a archivos viejos o "basura" en el directorio de salida.
|
||||
- *Entrada*: `trigger` (JSON/lista de VHS_FILENAMES), `output_filename` (Cadena de texto), `reset_list` (Booleano: actívalo a True en un ciclo para vaciar manualmente la memoria de la sesión y empezar un vídeo nuevo).
|
||||
- **🎞️ Incremental Auto-Stitcher**: Nodo de ensamblaje incremental diseñado específicamente para ciclos de Auto Queue. Se ejecuta inmediatamente después de que cada fragmento es guardado y extrae de manera estricta las rutas `.mp4` del JSON de salida que genera `VHS_FILENAMES`. Mantiene una lista en la memoria de la sesión activa para ensamblar *únicamente* los vídeos generados durante el ciclo de bucle actual, garantizando inmunidad a archivos viejos o "basura" en el directorio de salida.
|
||||
- *Entrada*: `trigger` (JSON/lista de VHS_FILENAMES), `output_filename` (Cadena de texto), `current_loop_index` (Entero: conéctalo al índice del bucle para vaciar automáticamente la memoria de la sesión en el primer ciclo).
|
||||
- *Salida*: `final_video_path` (Ruta del vídeo ensamblado incremental).
|
||||
|
||||
---
|
||||
|
||||
@@ -279,19 +279,19 @@ def tensor_to_temp_image(tensor_image, prefix="session_img"):
|
||||
|
||||
@register_node
|
||||
class SessionImageReceiver:
|
||||
"""Proporciona y MUESTRA la imagen inicial o la última generada del ciclo anterior."""
|
||||
"""Proporciona la imagen inicial o la última generada, detectando el inicio automáticamente."""
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"initial_image": ("IMAGE",),
|
||||
"reset_session": ("BOOLEAN", {"default": False}),
|
||||
"current_loop_index": ("INT", {"default": 0, "min": 0, "max": 10000, "step": 1}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("current_image",)
|
||||
OUTPUT_NODE = True # Necesario para que la UI se actualice
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "get_image"
|
||||
CATEGORY = "🔁 Sequential Batcher/Image"
|
||||
|
||||
@@ -299,19 +299,22 @@ class SessionImageReceiver:
|
||||
def IS_CHANGED(cls, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
def get_image(self, initial_image, reset_session):
|
||||
def get_image(self, initial_image, current_loop_index):
|
||||
global global_session_image
|
||||
|
||||
if reset_session or global_session_image is None:
|
||||
# Extracción segura por si en el futuro se usa INPUT_IS_LIST
|
||||
loop_idx = current_loop_index[0] if isinstance(current_loop_index, list) else current_loop_index
|
||||
|
||||
# LÓGICA NATIVA: Si es el primer ciclo (index 0), reiniciamos
|
||||
is_first_cycle = (loop_idx == 0)
|
||||
|
||||
if is_first_cycle or global_session_image is None:
|
||||
global_session_image = initial_image
|
||||
print("[Sequential Batcher] Receiver: Iniciando sesión con la imagen original.")
|
||||
print(f"[Sequential Batcher] Receiver: Ciclo {loop_idx}. Iniciando sesión con la imagen original.")
|
||||
else:
|
||||
print("[Sequential Batcher] Receiver: Usando el último fotograma del ciclo anterior.")
|
||||
print(f"[Sequential Batcher] Receiver: Ciclo {loop_idx}. Usando el último fotograma del ciclo anterior.")
|
||||
|
||||
# Generar vista previa para la UI
|
||||
ui_image = tensor_to_temp_image(global_session_image, "receiver")
|
||||
|
||||
# Devolver el diccionario con la actualización de la UI y el resultado real
|
||||
return {"ui": {"images": [ui_image]}, "result": (global_session_image, )}
|
||||
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ class IncrementalVideoStitcher:
|
||||
# Recibe la lista/JSON de VHS_VideoCombine
|
||||
"trigger": ("VHS_FILENAMES", ),
|
||||
"output_filename": ("STRING", {"default": "Pelicula_Final_Sesion.mp4"}),
|
||||
"reset_list": ("BOOLEAN", {"default": False}),
|
||||
"current_loop_index": ("INT", {"default": 0, "min": 0, "max": 10000, "step": 1}),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -151,23 +151,26 @@ class IncrementalVideoStitcher:
|
||||
FUNCTION = "stitch_incremental"
|
||||
CATEGORY = "🔁 Sequential Batcher/Video"
|
||||
|
||||
def stitch_incremental(self, trigger, output_filename, reset_list):
|
||||
def stitch_incremental(self, trigger, output_filename, current_loop_index):
|
||||
global session_video_list
|
||||
|
||||
# Extraer variables si llegan en lista por INPUT_IS_LIST=True
|
||||
do_reset = reset_list[0] if isinstance(reset_list, list) else reset_list
|
||||
|
||||
if do_reset:
|
||||
session_video_list.clear()
|
||||
print("[Sequential Batcher] Memoria de sesión vaciada (reset_list=True).")
|
||||
|
||||
if not shutil.which("ffmpeg"):
|
||||
print("[Sequential Batcher] Error: FFmpeg no está instalado en el sistema.")
|
||||
print("[Sequential Batcher] Error de FFmpeg: No está instalado.")
|
||||
return ("", )
|
||||
|
||||
out_dir = folder_paths.get_output_directory()
|
||||
out_name = output_filename[0] if isinstance(output_filename, list) else output_filename
|
||||
|
||||
# Extracción segura obligatoria por INPUT_IS_LIST = True
|
||||
loop_idx = current_loop_index[0] if isinstance(current_loop_index, list) else current_loop_index
|
||||
|
||||
# LÓGICA NATIVA: Si es el primer ciclo, vaciamos la lista
|
||||
is_first_cycle = (loop_idx == 0)
|
||||
|
||||
if is_first_cycle:
|
||||
print(f"[Sequential Batcher] Auto-Stitcher: Ciclo {loop_idx}. Vaciando memoria de la sesión.")
|
||||
session_video_list.clear()
|
||||
|
||||
# 1. Extracción recursiva: buscar cualquier archivo .mp4 dentro del JSON/lista recibido
|
||||
current_mp4s = []
|
||||
def extract_mp4s(data):
|
||||
|
||||
Reference in New Issue
Block a user