---
name: comfyui_build_video_workflow
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: pure
signature: "def comfyui_build_video_workflow(prompt: str, *, model: str = \"ltx\", negative: str = \"\", width: int = 512, height: int = 320, num_frames: int = 65, steps: int = 20, seed: int = 0, fps: int = 24) -> dict"
description: "Construye el dict de un workflow ComfyUI txt2video en API format para LTX-Video 2B v0.9.5 (model='ltx') o Wan2.1 T2V 1.3B (model='wan'), con los nombres de modelo reales. LTX: CLIPLoader(ltxv)+CheckpointLoaderSimple -> CLIPTextEncode x2 -> LTXVConditioning+EmptyLTXVLatentVideo+LTXVScheduler+KSamplerSelect -> SamplerCustom -> VAEDecode -> CreateVideo -> SaveVideo. Wan: UNETLoader+CLIPLoader(wan)+VAELoader+ModelSamplingSD3 -> CLIPTextEncode x2+EmptyHunyuanLatentVideo -> KSampler(uni_pc/simple) -> VAEDecode -> CreateVideo -> SaveVideo. Defaults conservadores para 8GB. Pura, sin red ni I/O. Hermana de comfyui_build_txt2img_workflow."
tags: [comfyui, ml, video-generation, txt2video, ltx-video, wan, workflow]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
params:
  - name: prompt
    desc: "Prompt positivo: lo que se quiere ver en el clip de video."
  - name: model
    desc: "'ltx' (LTX-Video 2B v0.9.5, todo-en-uno) o 'wan' (Wan2.1 T2V 1.3B, diffusion+vae aparte). Cualquier otro valor lanza ValueError. keyword-only."
  - name: negative
    desc: "Prompt negativo: lo que se quiere evitar. Por defecto cadena vacia. keyword-only."
  - name: width
    desc: "Ancho del video en px (multiplo de 32 recomendado). keyword-only."
  - name: height
    desc: "Alto del video en px (multiplo de 32 recomendado). keyword-only."
  - name: num_frames
    desc: "Numero de frames del clip (longitud temporal del latente de video). keyword-only."
  - name: steps
    desc: "Pasos de sampling: LTXVScheduler para ltx, KSampler para wan. keyword-only."
  - name: seed
    desc: "Semilla del sampler. 0 es determinista; cambiar para variar el clip. keyword-only."
  - name: fps
    desc: "Frames por segundo del video (CreateVideo). En LTX se usa tambien como frame_rate del LTXVConditioning. keyword-only."
output: "dict en API format listo para comfyui_submit_workflow. node_ids string; cada valor con class_type + inputs. LTX devuelve 12 nodos; Wan 11. La cfg/sampler/scheduler se fijan internamente segun el modelo (LTX: cfg 3.0, euler; Wan: cfg 6.0, uni_pc/simple, shift 8.0)."
tested: true
tests: ["LTX: nodos LTXV* presentes + t5xxl fp8 + ckpt real", "Wan: UNETLoader/VAELoader/ModelSamplingSD3 + umt5 + wan_2.1_vae", "params reflejados (width/height/num_frames/steps/seed/fps)", "model invalido lanza ValueError", "determinismo: misma entrada -> mismo dict (builder puro)"]
test_file_path: "python/functions/ml/tests/test_comfyui_build_video_workflow.py"
file_path: "python/functions/ml/comfyui_build_video_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_video_workflow import comfyui_build_video_workflow

wf = comfyui_build_video_workflow(
    "A red fox runs through a sunlit autumn forest, cinematic, shallow depth of field",
    model="ltx",
    negative="low quality, worst quality, deformed, motion smear",
    width=512, height=320, num_frames=65, steps=25, seed=42, fps=24,
)
# wf["72"]["class_type"] == "SamplerCustom"   (camino LTX)
# wf["79"]["class_type"] == "SaveVideo"
# -> comfyui_submit_workflow(wf) para encolar el clip
```

O lanzable directo con: `./fn run comfyui_build_video_workflow` (imprime el JSON del workflow LTX de ejemplo).

## Cuando usarla

Antes de enviar una generacion de video txt2video a ComfyUI: construye aqui el
dict del workflow y pasalo a `comfyui_submit_workflow`. Usa `model="ltx"` por
defecto (cupo en 8GB confirmado, scheduler y VAE temporales propios); `model="wan"`
si quieres el camino Wan2.1 1.3B (umt5 + vae aparte). Hermana de
`comfyui_build_txt2img_workflow` para imagen estatica.

## Gotchas

- Es API format (nodos numerados), NO el formato de la UI de ComfyUI. Es lo que
  acepta POST /prompt.
- Los nombres de modelo estan fijados a los reales del equipo
  (`ltx-video-2b-v0.9.5.safetensors` + `t5xxl_fp8_e4m3fn_scaled.safetensors`;
  `wan2.1_t2v_1.3B_fp16.safetensors` + `umt5_xxl_fp8_e4m3fn_scaled.safetensors` +
  `wan_2.1_vae.safetensors`). Deben existir y ser visibles para el servidor o
  ComfyUI rechaza el workflow con HTTP 400 al enviarlo (esta funcion es pura y no
  valida contra el servidor).
- Cupo 8GB: con los defaults (512x320, 65 frames) LTX pico ~7.7 GB en el report
  0084 sin OOM. Subir resolucion o num_frames acerca el techo. Si da OOM, bajar a
  512x288 / 49 frames.
- El camino LTX esta validado de extremo a extremo (report 0084: clip real de 65
  frames). El camino Wan modela la plantilla nativa canonica de ComfyUI pero NO se
  ejecuto en esa sesion; verificar nombres de modelo antes de tirar de el.
- LTX usa cfg baja (3.0). Subirla degrada el video. Por eso la cfg no es parametro:
  se fija segun el modelo.
- `SaveVideo` necesita `format`/`codec` (aqui "auto"/"auto"); sin ellos ComfyUI
  responde HTTP 400 (gotcha del importador, report 0084). Este builder ya los pone.
