---
name: comfyui_build_walk_cycle_workflow
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: pure
signature: "def comfyui_build_walk_cycle_workflow(subject: str, pose_skeletons: list, *, ckpt_name: str = \"IMG_dreamshaper_8.safetensors\", char_lora: str | None = None, lora_strength: float = 1.0, controlnet_name: str = \"control_v11p_sd15_openpose_fp16.safetensors\", controlnet_strength: float = 0.7, controlnet_start: float = 0.0, controlnet_end: float = 0.8, transparent: bool = True, rembg_model: str = \"u2net\", negative: str = \"blurry, lowres, extra limbs, deformed\", width: int = 512, height: int = 768, steps: int = 24, cfg: float = 7.0, seed: int = 0, sampler_name: str = \"dpmpp_2m\", scheduler: str = \"karras\", fps: int = 8, filename_prefix: str = \"walk_cycle\") -> dict"
description: "Construye el dict (API format) del workflow de un WALK CYCLE animado: genera N frames de un personaje en N poses OpenPose con la MISMA seed (identidad consistente), los combina en un batch encadenando ImageBatch, recorta el fondo a alpha con Rembg y los exporta como WEBP animado con SaveAnimatedWEBP. Caso 1 del report 0217 (animacion de sprite frame-by-frame pose-driven). Hermano animado de comfyui_build_sprite_sheet_workflow (frame estatico) y de comfyui_build_directional_sprite_workflow (rotacion 3D). Pura, sin red ni I/O. class_types e inputs verificados contra /object_info."
tags: [gamedev-2d, comfyui, sprite, animation, walk-cycle, controlnet, openpose]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
params:
  - name: subject
    desc: "Descripcion del personaje (ej. 'pixel art knight'). Se completa con ', full body, game sprite, simple background, walking'. No puede estar vacio."
  - name: pose_skeletons
    desc: "Lista (no vacia) de nombres de archivo de esqueletos OpenPose en el dir input/ del servidor, uno por frame del ciclo en orden de animacion. Cada uno debe ser string no vacio. La lista no se muta."
  - name: ckpt_name
    desc: "Checkpoint SD1.5 (OpenPose solo instalado en SD1.5; default 'IMG_dreamshaper_8.safetensors'). keyword-only."
  - name: char_lora
    desc: "LoRA de personaje/estilo opcional en models/loras (refuerza consistencia de ropa/cuerpo entre frames). None = sin LoRA. keyword-only."
  - name: lora_strength
    desc: "Fuerza del char_lora sobre model y clip. keyword-only."
  - name: controlnet_name
    desc: "ControlNet OpenPose (default SD1.5 'control_v11p_sd15_openpose_fp16.safetensors'). keyword-only."
  - name: controlnet_strength
    desc: "Fuerza del OpenPose (default 0.7). keyword-only."
  - name: controlnet_start
    desc: "Inicio de aplicacion del OpenPose (fraccion 0..1). keyword-only."
  - name: controlnet_end
    desc: "Fin de aplicacion del OpenPose (end<1.0 deja libres los ultimos pasos para pelo/ropa; default 0.8). keyword-only."
  - name: transparent
    desc: "Si True inyecta Rembg para alpha (recomendado para sprites de juego). False = fondo opaco. keyword-only."
  - name: rembg_model
    desc: "Modelo Rembg ('u2net' general, 'isnet-anime' para anime). keyword-only."
  - name: negative
    desc: "Prompt negativo. keyword-only."
  - name: width
    desc: "Ancho en px (512). keyword-only."
  - name: height
    desc: "Alto en px (768, vertical, encuadra cuerpo entero). keyword-only."
  - name: steps
    desc: "Pasos del KSampler. keyword-only."
  - name: cfg
    desc: "CFG del KSampler. keyword-only."
  - name: seed
    desc: "Semilla del KSampler, FIJA e identica para todos los frames (identidad consistente). keyword-only."
  - name: sampler_name
    desc: "Sampler del KSampler (default 'dpmpp_2m'). keyword-only."
  - name: scheduler
    desc: "Scheduler del KSampler (default 'karras'). keyword-only."
  - name: fps
    desc: "Frames por segundo del WEBP animado (default 8). keyword-only."
  - name: filename_prefix
    desc: "Prefijo del archivo WEBP en output/ (default 'walk_cycle'). keyword-only."
output: "dict en API format listo para comfyui_submit_workflow. Claves = node_ids (string); cada valor tiene class_type + inputs. Estructura: CheckpointLoaderSimple (+ LoraLoader si char_lora) + 2x CLIPTextEncode + ControlNetLoader compartido + N x (LoadImage + ControlNetApplyAdvanced + EmptyLatentImage + KSampler + VAEDecode) + cadena de ImageBatch que une los N frames + Rembg (si transparent) + SaveAnimatedWEBP."
tested: false
tests: []
test_file_path: ""
file_path: "python/functions/ml/comfyui_build_walk_cycle_workflow.py"
---

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_build_walk_cycle_workflow import comfyui_build_walk_cycle_workflow

# Ciclo de andar de 4 frames: 4 esqueletos OpenPose (en input/ del servidor),
# misma seed -> el mismo personaje caminando, no 4 personajes distintos.
wf = comfyui_build_walk_cycle_workflow(
    "pixel art knight",
    pose_skeletons=[
        "walk_pose_00.png",
        "walk_pose_01.png",
        "walk_pose_02.png",
        "walk_pose_03.png",
    ],
    transparent=True,
    fps=8,
    seed=0,
)
# wf es API format -> comfyui_submit_workflow(wf) genera el WEBP animado en output/.
```

O lanzable directo con: `./fn run comfyui_build_walk_cycle_workflow` (imprime nodos + class_types del ejemplo).

## Cuando usarla

Cuando necesites una **animacion** de un sprite de personaje 2D (no un frame suelto):
ciclo de andar, correr, atacar, idle... — cualquier secuencia donde el personaje conserva
su identidad y solo cambia la postura. Dibuja los N esqueletos OpenPose de la secuencia,
pasalos en orden, fija la `seed` y obtienes un WEBP animado de una sola pasada. Para UN
frame estatico usa `comfyui_build_sprite_sheet_workflow`; para rotar el personaje en 3D
(vistas direccionales) usa `comfyui_build_directional_sprite_workflow`.

## Gotchas

- **Solo SD1.5 hoy**: el ControlNet OpenPose esta instalado solo en SD1.5. Usa
  `IMG_dreamshaper_8` u otro checkpoint SD1.5.
- **`pose_skeletons` son nombres de archivo en el dir `input/` del servidor**, no rutas
  locales. Subelas antes (cada LoadImage las lee de ahi). El orden de la lista = el orden
  de los frames de la animacion.
- **La `seed` es FIJA para todos los frames a proposito**: compartir seed + prompt +
  checkpoint y variar solo el OpenPose es lo que mantiene al mismo personaje entre
  fotogramas. Una seed por frame haria "parpadear" la identidad (cara/ropa/paleta derivan).
- **`ControlNetApplyAdvanced` con `end_percent` 0.8** deja los ultimos pasos libres para
  que pelo/ropa no queden aplastados contra el esqueleto.
- **El batch se construye encadenando `ImageBatch`** (toma 2 imagenes): para N frames hay
  N-1 nodos ImageBatch. Con N=1 no hay ImageBatch (el unico frame va directo al Save).
- `Image Rembg` da matting binario (silueta solida) — ideal para personajes, NO para
  efectos translucidos (humo/fuego). Con `transparent=False` se omite (fondo opaco).
- **El WEBP animado** usa `lossless=True`, `quality=90`, `method="default"`; sube/baja
  `fps` para la velocidad del ciclo. Verificado que `method` admite `default/fastest/slowest`.
- Funcion pura: construye el grafo, NO valida contra el server ni envia nada. El coste GPU
  esta al enviar con `comfyui_submit_workflow`.
