--- name: comfyui_walk_cycle_oneshot kind: pipeline lang: py domain: pipelines version: "1.0.0" purity: impure signature: "def comfyui_walk_cycle_oneshot(character: str, *, frames: int = 4, size: int = 32, colors: int = 16, fps: int = 8, checkpoint: str = 'IMG_dreamshaper_8.safetensors', ref_image: str | None = None, server: str = '127.0.0.1:8188', dest_dir: str = '~/ComfyUI/output', seed: int = 0, pose_method: str = 'auto', controlnet_strength: float = 0.7, engine: str = 'pixeloe', palette=None, fmt: str = 'webp', **gen_kwargs) -> dict" description: "Pipeline one-shot: de un prompt de personaje a una animacion de walk cycle en pixel-art (sprite sheet + GIF/WEBP en loop). Genera N frames frame-by-frame dirigidos por pose (ControlNet OpenPose con esqueletos del walk cycle, o fase del paso por prompt como fallback), con seed fija para identidad consistente y Rembg para alpha, y pixeliza cada frame a un grid duro size x size RGBA. Materializa el caso 1 de la investigacion de animacion de sprites (report 0217): personaje = frame-by-frame pose-driven, NUNCA modelos de video. Compone render_openpose_walk_skeletons + comfyui_build_sprite_sheet_workflow + submit/wait/fetch + comfyui_pixelize_sprite_png + assemble_animated_sprite. Impuro: red + GPU + disco. No-throw, salta frames que fallan." tags: [gamedev-2d, comfyui, pixelart, sprite, animation, walk-cycle, controlnet, openpose, launcher] uses_functions: ["render_openpose_walk_skeletons_py_ml", "comfyui_build_sprite_sheet_workflow_py_ml", "comfyui_submit_workflow_py_ml", "comfyui_wait_result_py_ml", "comfyui_fetch_output_image_py_ml", "comfyui_pixelize_sprite_png_py_ml", "assemble_animated_sprite_py_ml"] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: ["os", "sys"] params: - name: character desc: "Prompt del personaje (ej. 'pixel art knight, full body, side view'). No vacio. La identidad se mantiene entre frames con seed fija." - name: frames desc: "Numero de frames del ciclo (>=2, recomendado 4-8). 4 = las 4 fases canonicas contact-L / passing / contact-R / passing." - name: size desc: "Lado del grid pixel-art final por frame en pixeles (32 sprites pequenos, 64 personajes con mas detalle)." - name: colors desc: "Numero de colores de la paleta libre por frame (cuantizacion MEDIANCUT) cuando palette es None." - name: fps desc: "Cadencia de la animacion en frames por segundo (duration = 1000/fps ms por frame)." - name: checkpoint desc: "Checkpoint SD1.5 (ControlNet OpenPose + IPAdapter-FaceID solo instalados en SD1.5; default 'IMG_dreamshaper_8.safetensors')." - name: ref_image desc: "Imagen de cara de referencia en el input/ del servidor para IPAdapter-FaceID (segunda ancla de identidad). None = solo seed + prompt." - name: server desc: "host:port del servidor ComfyUI (sin esquema). Default 127.0.0.1:8188." - name: dest_dir desc: "Directorio donde guardar frames + sprite sheet + animacion (se expande ~)." - name: seed desc: "Semilla FIJA del KSampler para TODOS los frames (identidad estable entre poses)." - name: pose_method desc: "'openpose' (esqueletos OpenPose -> ControlNet, control exacto), 'prompt' (fase del paso descrita en el prompt, sin esqueletos) o 'auto' (intenta openpose, cae a prompt si el render falla)." - name: controlnet_strength desc: "Fuerza del ControlNet OpenPose (0.7 da buen control sin aplastar el estilo). Solo aplica en modo openpose." - name: engine desc: "Motor de downscale del pixelizado: 'pixeloe' (contrast-aware, conserva silueta) o 'nearest'." - name: palette desc: "None (paleta libre a colors), nombre builtin ('pico-8','nes','game-boy') o lista de hex. Fija ignora colors." - name: fmt desc: "Formato de la animacion: 'webp' (recomendado, alpha real) o 'gif' (alpha binario)." output: "dict {ok, frames:[paths], spritesheet_path, animation_path, size, n_frames, seed, pose_method_used, skipped:[idx], error}. ok=True si se produjo la animacion con >=1 frame. n_frames puede ser < frames si alguno fallo (se salta y se sigue)." tested: false tests: [] test_file_path: "" file_path: "python/functions/pipelines/comfyui_walk_cycle_oneshot.py" --- ## Ejemplo ```python import sys, os sys.path.insert(0, os.path.join("python", "functions")) from pipelines.comfyui_walk_cycle_oneshot import comfyui_walk_cycle_oneshot # Requiere el servidor ComfyUI vivo en 127.0.0.1:8188 (GPU). res = comfyui_walk_cycle_oneshot( "pixel art knight, full body, side view", frames=4, size=32, colors=16, fps=8, seed=42, dest_dir="/tmp/comfy_walk_cycle", ) print(res["ok"], res["n_frames"], res["animation_path"], res["pose_method_used"]) # -> True 4 /tmp/comfy_walk_cycle/walk_cycle.webp openpose ``` ## Cuando usarla Cuando quieras una animacion de un personaje en pixel-art (caminar, correr) lista para un juego 2D, en un solo paso: das el prompt del personaje y recibes el sprite sheet + el GIF/WEBP en loop. Es la promocion a pipeline (issue 0087) de la receta del caso 1 del report 0217 — el camino correcto para sprites limpios de personaje con alpha, frente a AnimateDiff o modelos de video (que ensucian el alpha y no clavan la pose). Para una sola pose estatica usa `comfyui_pixelart_real_oneshot`; para varias vistas direccionales (8-way) usa `comfyui_build_directional_sprite_workflow`. ## Gotchas - **Server vivo + GPU**: requiere ComfyUI en `server` con la GPU libre. El report recomienda `POST /free` antes de cargas pesadas de modelo. Cada frame reusa el mismo checkpoint, asi que el modelo solo se carga una vez. - **Poses OpenPose**: en modo `openpose` los esqueletos se escriben en el `input/` del servidor (asume server local; para un server remoto haria falta subirlos con `POST /upload/image`). Si el ControlNet no produce variacion de piernas reconocible, usa `pose_method="prompt"`: a 32x32 el detalle de pose se simplifica y la fase del paso por prompt + seed fija da un walk reconocible. - **Identidad**: la `seed` es FIJA para todos los frames — esa es la ancla de identidad. Cambiar la seed entre frames rompe la consistencia del personaje. `ref_image` (IPAdapter-FaceID) es una segunda ancla opcional; sobre un sprite de cuerpo entero pequeno aporta sobre todo paleta/ropa (ver report 0217). - **No-throw, salta frames**: si un frame falla (red, GPU, build) se anade a `skipped` y la animacion se monta con los que queden. ok=False solo si NINGUN frame sale. - **Loop suave**: con `frames=4` el ciclo (contact-L, passing, contact-R, passing) ya cierra el bucle — el frame siguiente al ultimo vuelve a la primera fase. - **WEBP vs GIF**: `fmt="webp"` conserva alpha real (lossless); `fmt="gif"` solo tiene alpha binario (1 bit). Para sprites con transparencia, usa WEBP. ## Capability growth log - v1.0.0 (2026-06-28) — version inicial. Caso 1 del report 0217 promovido a pipeline one-shot: walk cycle pixel-art con poses OpenPose (o fallback prompt), seed fija para identidad, Rembg para alpha, pixelizado a NxN RGBA, sprite sheet + WEBP/GIF en loop.