feat(ml): comfyui_build_img2vid_workflow builder img2vid SVD (API format)
Builder puro que construye el dict de un workflow ComfyUI img2vid (Stable Video Diffusion) en API format a partir de una imagen estatica. Cadena de 7 nodos: ImageOnlyCheckpointLoader(svd.safetensors, todo-en-uno) + LoadImage -> SVD_img2vid_Conditioning -> VideoLinearCFGGuidance -> KSampler(denoise 1.0) -> VAEDecode -> SaveAnimatedWEBP. SVD condiciona por CLIP_VISION de la imagen (sin prompt de texto); movimiento via motion_bucket_id. class_type/inputs verificados contra /object_info del servidor vivo. Validacion estructural con comfyui_validate_workflow: 0 errores. 4 tests verdes. Sin submit de generacion (GPU en uso por otro agente). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -98,6 +98,7 @@ canónica). El resultado es un `.mp4` vía `CreateVideo → SaveVideo`.
|
|||||||
| ID | Firma corta | Qué hace |
|
| ID | Firma corta | Qué hace |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| [comfyui_build_video_workflow_py_ml](../../python/functions/ml/comfyui_build_video_workflow.md) | `build_video_workflow(prompt, *, model='ltx', negative='', width=512, height=320, num_frames=65, steps=20, seed=0, fps=24) -> dict` | Builder txt2video para LTX-Video 2B (`model='ltx'`, 12 nodos LTXV*) o Wan2.1 1.3B (`model='wan'`, UNETLoader+VAELoader+ModelSamplingSD3). Nombres de modelo reales, defaults conservadores 8 GB. **Pura**. |
|
| [comfyui_build_video_workflow_py_ml](../../python/functions/ml/comfyui_build_video_workflow.md) | `build_video_workflow(prompt, *, model='ltx', negative='', width=512, height=320, num_frames=65, steps=20, seed=0, fps=24) -> dict` | Builder txt2video para LTX-Video 2B (`model='ltx'`, 12 nodos LTXV*) o Wan2.1 1.3B (`model='wan'`, UNETLoader+VAELoader+ModelSamplingSD3). Nombres de modelo reales, defaults conservadores 8 GB. **Pura**. |
|
||||||
|
| [comfyui_build_img2vid_workflow_py_ml](../../python/functions/ml/comfyui_build_img2vid_workflow.md) | `build_img2vid_workflow(image, *, ckpt='svd.safetensors', width=1024, height=576, video_frames=14, motion_bucket_id=127, fps=6, augmentation_level=0.0, steps=20, cfg=2.5, min_cfg=1.0, seed=0, sampler_name='euler', scheduler='karras', filename_prefix='comfy_svd') -> dict` | Builder img2vid (Stable Video Diffusion): anima una imagen estática a clip corto. ImageOnlyCheckpointLoader(`svd.safetensors`, todo-en-uno) + LoadImage → SVD_img2vid_Conditioning → VideoLinearCFGGuidance → KSampler (denoise 1.0) → VAEDecode → SaveAnimatedWEBP. SVD no usa prompt de texto: condiciona por CLIP_VISION de la imagen; movimiento vía `motion_bucket_id`. **Pura**. |
|
||||||
|
|
||||||
### Imagen → 3D (Hunyuan3D-2 nativo) — dominio `ml` + `pipelines` (tag `img-to-3d`)
|
### Imagen → 3D (Hunyuan3D-2 nativo) — dominio `ml` + `pipelines` (tag `img-to-3d`)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
---
|
||||||
|
name: comfyui_build_img2vid_workflow
|
||||||
|
kind: function
|
||||||
|
lang: py
|
||||||
|
domain: ml
|
||||||
|
version: "1.0.0"
|
||||||
|
purity: pure
|
||||||
|
signature: "def comfyui_build_img2vid_workflow(image: str, *, ckpt: str = \"svd.safetensors\", width: int = 1024, height: int = 576, video_frames: int = 14, motion_bucket_id: int = 127, fps: int = 6, augmentation_level: float = 0.0, steps: int = 20, cfg: float = 2.5, min_cfg: float = 1.0, seed: int = 0, sampler_name: str = \"euler\", scheduler: str = \"karras\", filename_prefix: str = \"comfy_svd\") -> dict"
|
||||||
|
description: "Construye el dict de un workflow ComfyUI img2vid (Stable Video Diffusion) en API format a partir de una imagen estatica. Cadena: ImageOnlyCheckpointLoader(svd.safetensors -> MODEL, CLIP_VISION, VAE) + LoadImage -> SVD_img2vid_Conditioning(positive, negative, latent) -> VideoLinearCFGGuidance -> KSampler(denoise 1.0) -> VAEDecode -> SaveAnimatedWEBP. SVD no usa prompt de texto: el condicionamiento sale de la imagen via CLIP_VISION del checkpoint todo-en-uno. Movimiento via motion_bucket_id y fps. Pura, sin red ni I/O. Hermana de comfyui_build_video_workflow (txt2video LTX/Wan)."
|
||||||
|
tags: [comfyui, svd, img2vid, video, ml, workflow]
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
returns: []
|
||||||
|
returns_optional: false
|
||||||
|
error_type: ""
|
||||||
|
imports: []
|
||||||
|
params:
|
||||||
|
- name: image
|
||||||
|
desc: "Nombre del archivo de imagen base en la carpeta input/ del servidor ComfyUI (lo que carga LoadImage). Es el frame inicial del que SVD deriva el clip."
|
||||||
|
- name: ckpt
|
||||||
|
desc: "Nombre del checkpoint SVD tal como lo ve el servidor. Por defecto 'svd.safetensors' (todo-en-uno: UNet + VAE + CLIP image encoder). keyword-only."
|
||||||
|
- name: width
|
||||||
|
desc: "Ancho del video en px (multiplo de 8; SVD base entrena a 1024). keyword-only."
|
||||||
|
- name: height
|
||||||
|
desc: "Alto del video en px (multiplo de 8; SVD base entrena a 576). keyword-only."
|
||||||
|
- name: video_frames
|
||||||
|
desc: "Numero de frames del clip. svd.safetensors es el modelo de 14 frames; la variante xt llega a 25. keyword-only."
|
||||||
|
- name: motion_bucket_id
|
||||||
|
desc: "Intensidad de movimiento (1-255 util; 127 por defecto). Mas alto = mas movimiento. keyword-only."
|
||||||
|
- name: fps
|
||||||
|
desc: "Frames por segundo con que se condiciona (SVD_img2vid_Conditioning) y se guarda el clip (SaveAnimatedWEBP, alli como float). keyword-only."
|
||||||
|
- name: augmentation_level
|
||||||
|
desc: "Ruido anadido a la imagen base (0.0 = fiel; subirlo da mas libertad/movimiento a costa de fidelidad). keyword-only."
|
||||||
|
- name: steps
|
||||||
|
desc: "Pasos de sampling del KSampler. keyword-only."
|
||||||
|
- name: cfg
|
||||||
|
desc: "Guidance scale del ultimo frame (VideoLinearCFGGuidance interpola de min_cfg al primero hasta cfg al ultimo). SVD usa cfg baja (~2.5). keyword-only."
|
||||||
|
- name: min_cfg
|
||||||
|
desc: "Guidance scale del primer frame para VideoLinearCFGGuidance. keyword-only."
|
||||||
|
- name: seed
|
||||||
|
desc: "Semilla del sampler. 0 es determinista; cambiar para variar el clip. keyword-only."
|
||||||
|
- name: sampler_name
|
||||||
|
desc: "Algoritmo del KSampler. Por defecto 'euler'. keyword-only."
|
||||||
|
- name: scheduler
|
||||||
|
desc: "Scheduler del KSampler. Por defecto 'karras'. keyword-only."
|
||||||
|
- name: filename_prefix
|
||||||
|
desc: "Prefijo del archivo de salida (.webp animado de SaveAnimatedWEBP). keyword-only."
|
||||||
|
output: "dict en API format listo para comfyui_submit_workflow. node_ids string; cada valor con class_type + inputs. Devuelve 7 nodos: ImageOnlyCheckpointLoader, LoadImage, SVD_img2vid_Conditioning, VideoLinearCFGGuidance, KSampler, VAEDecode y SaveAnimatedWEBP. El denoise del KSampler se fija a 1.0 (genera desde el latente condicionado, no es img2img)."
|
||||||
|
tested: true
|
||||||
|
tests: ["estructura: 7 nodos SVD presentes + ckpt svd.safetensors + image en LoadImage", "cableado: clip_vision/vae [15,1]/[15,2], cond->KSampler 0/1/2, model post VideoLinearCFGGuidance, denoise 1.0", "params reflejados (width/height/video_frames/motion_bucket_id/fps/augmentation_level/steps/cfg/min_cfg/seed/filename_prefix) + fps float en SaveAnimatedWEBP", "determinismo: misma entrada -> mismo dict (builder puro)"]
|
||||||
|
test_file_path: "python/functions/ml/tests/test_comfyui_build_img2vid_workflow.py"
|
||||||
|
file_path: "python/functions/ml/comfyui_build_img2vid_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_img2vid_workflow import comfyui_build_img2vid_workflow
|
||||||
|
|
||||||
|
wf = comfyui_build_img2vid_workflow(
|
||||||
|
"example.png",
|
||||||
|
width=1024, height=576, video_frames=14,
|
||||||
|
motion_bucket_id=127, fps=6, steps=20, seed=42,
|
||||||
|
)
|
||||||
|
# wf["12"]["class_type"] == "SVD_img2vid_Conditioning"
|
||||||
|
# wf["30"]["class_type"] == "SaveAnimatedWEBP"
|
||||||
|
# -> comfyui_submit_workflow(wf) para encolar el clip (necesita GPU)
|
||||||
|
```
|
||||||
|
|
||||||
|
O lanzable directo con: `./fn run comfyui_build_img2vid_workflow` (imprime el JSON del workflow SVD de ejemplo).
|
||||||
|
|
||||||
|
## Cuando usarla
|
||||||
|
|
||||||
|
Antes de enviar una generacion de video img2vid (animar una imagen estatica) a
|
||||||
|
ComfyUI: construye aqui el dict del workflow SVD y pasalo a
|
||||||
|
`comfyui_submit_workflow`. Usala cuando partes de UNA imagen y quieres un clip
|
||||||
|
corto derivado de ella (SVD no toma prompt de texto). Para texto -> video usa la
|
||||||
|
hermana `comfyui_build_video_workflow` (LTX/Wan). Verifica el workflow contra el
|
||||||
|
servidor con `comfyui_validate_workflow` antes de encolar.
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- Es API format (nodos numerados), NO el formato de la UI de ComfyUI. Es lo que
|
||||||
|
acepta POST /prompt.
|
||||||
|
- SVD NO usa prompts de texto. El condicionamiento sale de la imagen base via el
|
||||||
|
CLIP_VISION del checkpoint todo-en-uno; por eso no hay nodos CLIPTextEncode.
|
||||||
|
- El checkpoint `svd.safetensors` debe existir y ser visible para el servidor
|
||||||
|
(carpeta de checkpoints o extra_model_paths) o ComfyUI rechaza el workflow con
|
||||||
|
HTTP 400 al enviarlo. Esta funcion es pura y no valida contra el servidor.
|
||||||
|
- La imagen `image` debe estar en la carpeta input/ del servidor (subela antes con
|
||||||
|
el endpoint de upload o el nodo LoadImage de la UI). El validador estructural NO
|
||||||
|
comprueba la existencia de la imagen (image no es un input de modelo).
|
||||||
|
- VRAM 8GB: SVD es pesado. Con los defaults (1024x576, 14 frames) el modelo base
|
||||||
|
puede acercarse al techo de 8GB. Si da OOM, bajar resolucion (768x448) o
|
||||||
|
video_frames. La generacion real (submit) es un paso posterior con GPU; este
|
||||||
|
builder solo arma el dict y se valida de forma estructural (offline).
|
||||||
|
- `svd.safetensors` es el modelo de 14 frames. La variante `svd_xt` admite 25;
|
||||||
|
con el base, video_frames > 14 puede degradar el clip.
|
||||||
|
- motion_bucket_id alto = mas movimiento (y mas artefactos). 127 es el centro
|
||||||
|
recomendado por Stability.
|
||||||
|
- cfg se mantiene baja (~2.5) y se interpola con VideoLinearCFGGuidance (min_cfg en
|
||||||
|
el primer frame -> cfg en el ultimo). Subir cfg degrada el video.
|
||||||
|
- SaveAnimatedWEBP declara `fps` como FLOAT en /object_info: el builder pasa
|
||||||
|
`float(fps)` para no provocar HTTP 400. El nodo VHS_VideoCombine NO esta instalado
|
||||||
|
en este servidor; por eso el guardado usa el SaveAnimatedWEBP nativo.
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
"""Construye un workflow ComfyUI img2vid (SVD) en "API format" (dict de nodos numerados).
|
||||||
|
|
||||||
|
Implementa la plantilla canonica de Stable Video Diffusion de ComfyUI: a partir de
|
||||||
|
una imagen estatica genera un clip corto de video. El checkpoint `svd.safetensors`
|
||||||
|
es todo-en-uno (UNet + VAE + CLIP image encoder), cargado con
|
||||||
|
ImageOnlyCheckpointLoader (da MODEL, CLIP_VISION y VAE de una sola pieza).
|
||||||
|
|
||||||
|
Cadena de nodos:
|
||||||
|
ImageOnlyCheckpointLoader (MODEL, CLIP_VISION, VAE) + LoadImage (imagen base) ->
|
||||||
|
SVD_img2vid_Conditioning (positive, negative, latent) ->
|
||||||
|
VideoLinearCFGGuidance (interpola cfg de min_cfg a cfg a lo largo del clip) ->
|
||||||
|
KSampler (denoise 1.0) -> VAEDecode (secuencia de frames) -> SaveAnimatedWEBP.
|
||||||
|
|
||||||
|
A diferencia de los modelos txt2video (LTX/Wan), SVD no usa prompts de texto: el
|
||||||
|
condicionamiento sale de la imagen via el CLIP_VISION del propio checkpoint. El
|
||||||
|
movimiento se controla con motion_bucket_id (mas alto = mas movimiento) y fps.
|
||||||
|
|
||||||
|
Funcion pura: sin red, sin I/O. Determinista para los mismos argumentos.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def comfyui_build_img2vid_workflow(
|
||||||
|
image: str,
|
||||||
|
*,
|
||||||
|
ckpt: str = "svd.safetensors",
|
||||||
|
width: int = 1024,
|
||||||
|
height: int = 576,
|
||||||
|
video_frames: int = 14,
|
||||||
|
motion_bucket_id: int = 127,
|
||||||
|
fps: int = 6,
|
||||||
|
augmentation_level: float = 0.0,
|
||||||
|
steps: int = 20,
|
||||||
|
cfg: float = 2.5,
|
||||||
|
min_cfg: float = 1.0,
|
||||||
|
seed: int = 0,
|
||||||
|
sampler_name: str = "euler",
|
||||||
|
scheduler: str = "karras",
|
||||||
|
filename_prefix: str = "comfy_svd",
|
||||||
|
) -> dict:
|
||||||
|
"""Construye el dict del workflow img2vid (SVD) para svd.safetensors.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image: nombre del archivo de imagen base dentro de la carpeta input/ del
|
||||||
|
servidor ComfyUI (lo que carga el nodo LoadImage). Es el frame inicial
|
||||||
|
del que SVD deriva el clip.
|
||||||
|
ckpt: nombre del checkpoint SVD tal como lo ve el servidor. Por defecto
|
||||||
|
"svd.safetensors" (todo-en-uno: UNet + VAE + CLIP image encoder).
|
||||||
|
keyword-only.
|
||||||
|
width: ancho del video en px (multiplo de 8; SVD base entrena a 1024).
|
||||||
|
keyword-only.
|
||||||
|
height: alto del video en px (multiplo de 8; SVD base entrena a 576).
|
||||||
|
keyword-only.
|
||||||
|
video_frames: numero de frames del clip. svd.safetensors es el modelo de
|
||||||
|
14 frames; el variante xt llega a 25. keyword-only.
|
||||||
|
motion_bucket_id: intensidad de movimiento (1-255 util; 127 por defecto).
|
||||||
|
Mas alto = mas movimiento. keyword-only.
|
||||||
|
fps: frames por segundo con que se condiciona y se guarda el clip.
|
||||||
|
keyword-only.
|
||||||
|
augmentation_level: ruido anadido a la imagen base (0.0 = fiel a la base;
|
||||||
|
subirlo da mas libertad/movimiento a costa de fidelidad). keyword-only.
|
||||||
|
steps: pasos de sampling del KSampler. keyword-only.
|
||||||
|
cfg: guidance scale del ultimo frame (VideoLinearCFGGuidance interpola de
|
||||||
|
min_cfg al primer frame hasta cfg al ultimo). SVD usa cfg baja (~2.5).
|
||||||
|
keyword-only.
|
||||||
|
min_cfg: guidance scale del primer frame para VideoLinearCFGGuidance.
|
||||||
|
keyword-only.
|
||||||
|
seed: semilla del sampler (0 = determinista; cambiar para variar el clip).
|
||||||
|
keyword-only.
|
||||||
|
sampler_name: algoritmo del KSampler. Por defecto "euler". keyword-only.
|
||||||
|
scheduler: scheduler del KSampler. Por defecto "karras". keyword-only.
|
||||||
|
filename_prefix: prefijo del archivo de salida (.webp animado).
|
||||||
|
keyword-only.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict en API format listo para comfyui_submit_workflow. Las claves son
|
||||||
|
node_ids (string) y cada valor tiene class_type + inputs. Devuelve 7 nodos:
|
||||||
|
ImageOnlyCheckpointLoader, LoadImage, SVD_img2vid_Conditioning,
|
||||||
|
VideoLinearCFGGuidance, KSampler, VAEDecode y SaveAnimatedWEBP. El denoise
|
||||||
|
del KSampler se fija a 1.0 (img2vid genera desde latente vacio condicionado,
|
||||||
|
no es img2img).
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"15": {
|
||||||
|
"class_type": "ImageOnlyCheckpointLoader",
|
||||||
|
"inputs": {"ckpt_name": ckpt},
|
||||||
|
},
|
||||||
|
"23": {
|
||||||
|
"class_type": "LoadImage",
|
||||||
|
"inputs": {"image": image},
|
||||||
|
},
|
||||||
|
"12": {
|
||||||
|
"class_type": "SVD_img2vid_Conditioning",
|
||||||
|
"inputs": {
|
||||||
|
"clip_vision": ["15", 1],
|
||||||
|
"init_image": ["23", 0],
|
||||||
|
"vae": ["15", 2],
|
||||||
|
"width": width,
|
||||||
|
"height": height,
|
||||||
|
"video_frames": video_frames,
|
||||||
|
"motion_bucket_id": motion_bucket_id,
|
||||||
|
"fps": fps,
|
||||||
|
"augmentation_level": augmentation_level,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"14": {
|
||||||
|
"class_type": "VideoLinearCFGGuidance",
|
||||||
|
"inputs": {"model": ["15", 0], "min_cfg": min_cfg},
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"class_type": "KSampler",
|
||||||
|
"inputs": {
|
||||||
|
"seed": seed,
|
||||||
|
"steps": steps,
|
||||||
|
"cfg": cfg,
|
||||||
|
"sampler_name": sampler_name,
|
||||||
|
"scheduler": scheduler,
|
||||||
|
"denoise": 1.0,
|
||||||
|
"model": ["14", 0],
|
||||||
|
"positive": ["12", 0],
|
||||||
|
"negative": ["12", 1],
|
||||||
|
"latent_image": ["12", 2],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"8": {
|
||||||
|
"class_type": "VAEDecode",
|
||||||
|
"inputs": {"samples": ["3", 0], "vae": ["15", 2]},
|
||||||
|
},
|
||||||
|
"30": {
|
||||||
|
"class_type": "SaveAnimatedWEBP",
|
||||||
|
"inputs": {
|
||||||
|
"images": ["8", 0],
|
||||||
|
"filename_prefix": filename_prefix,
|
||||||
|
"fps": float(fps),
|
||||||
|
"lossless": False,
|
||||||
|
"quality": 90,
|
||||||
|
"method": "default",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import json
|
||||||
|
|
||||||
|
wf = comfyui_build_img2vid_workflow(
|
||||||
|
"example.png",
|
||||||
|
motion_bucket_id=127,
|
||||||
|
fps=6,
|
||||||
|
video_frames=14,
|
||||||
|
seed=42,
|
||||||
|
)
|
||||||
|
print(json.dumps(wf, indent=2))
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
"""Tests de estructura para comfyui_build_img2vid_workflow (funcion pura, SVD)."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.dirname(__file__))
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||||
|
|
||||||
|
from ml.comfyui_build_img2vid_workflow import comfyui_build_img2vid_workflow
|
||||||
|
from _comfyui_wf_assert import assert_api_format, class_types, node_by_ct
|
||||||
|
|
||||||
|
|
||||||
|
def test_estructura_y_nodos_svd():
|
||||||
|
wf = comfyui_build_img2vid_workflow("example.png")
|
||||||
|
assert_api_format(wf)
|
||||||
|
cts = class_types(wf)
|
||||||
|
for ct in (
|
||||||
|
"ImageOnlyCheckpointLoader",
|
||||||
|
"LoadImage",
|
||||||
|
"SVD_img2vid_Conditioning",
|
||||||
|
"VideoLinearCFGGuidance",
|
||||||
|
"KSampler",
|
||||||
|
"VAEDecode",
|
||||||
|
"SaveAnimatedWEBP",
|
||||||
|
):
|
||||||
|
assert ct in cts, f"falta {ct} en SVD img2vid"
|
||||||
|
# El checkpoint SVD es todo-en-uno cargado con el loader image-only.
|
||||||
|
assert node_by_ct(wf, "ImageOnlyCheckpointLoader")["inputs"]["ckpt_name"] == (
|
||||||
|
"svd.safetensors"
|
||||||
|
)
|
||||||
|
# La imagen base entra por LoadImage.
|
||||||
|
assert node_by_ct(wf, "LoadImage")["inputs"]["image"] == "example.png"
|
||||||
|
|
||||||
|
|
||||||
|
def test_cableado_de_nodos():
|
||||||
|
wf = comfyui_build_img2vid_workflow("example.png")
|
||||||
|
cond = node_by_ct(wf, "SVD_img2vid_Conditioning")["inputs"]
|
||||||
|
# clip_vision y vae salen del checkpoint image-only (outputs 1 y 2).
|
||||||
|
assert cond["clip_vision"] == ["15", 1]
|
||||||
|
assert cond["vae"] == ["15", 2]
|
||||||
|
assert cond["init_image"] == ["23", 0]
|
||||||
|
ks = node_by_ct(wf, "KSampler")["inputs"]
|
||||||
|
# KSampler usa el MODEL post VideoLinearCFGGuidance y los 3 outputs del cond.
|
||||||
|
assert ks["model"] == ["14", 0]
|
||||||
|
assert ks["positive"] == ["12", 0]
|
||||||
|
assert ks["negative"] == ["12", 1]
|
||||||
|
assert ks["latent_image"] == ["12", 2]
|
||||||
|
assert ks["denoise"] == 1.0
|
||||||
|
# VideoLinearCFGGuidance toma el MODEL crudo del checkpoint.
|
||||||
|
assert node_by_ct(wf, "VideoLinearCFGGuidance")["inputs"]["model"] == ["15", 0]
|
||||||
|
|
||||||
|
|
||||||
|
def test_params_se_reflejan():
|
||||||
|
wf = comfyui_build_img2vid_workflow(
|
||||||
|
"fox_front.png",
|
||||||
|
width=768,
|
||||||
|
height=448,
|
||||||
|
video_frames=25,
|
||||||
|
motion_bucket_id=200,
|
||||||
|
fps=10,
|
||||||
|
augmentation_level=0.2,
|
||||||
|
steps=25,
|
||||||
|
cfg=3.0,
|
||||||
|
min_cfg=1.5,
|
||||||
|
seed=7,
|
||||||
|
filename_prefix="myclip",
|
||||||
|
)
|
||||||
|
cond = node_by_ct(wf, "SVD_img2vid_Conditioning")["inputs"]
|
||||||
|
assert cond["width"] == 768 and cond["height"] == 448
|
||||||
|
assert cond["video_frames"] == 25
|
||||||
|
assert cond["motion_bucket_id"] == 200
|
||||||
|
assert cond["fps"] == 10
|
||||||
|
assert cond["augmentation_level"] == 0.2
|
||||||
|
ks = node_by_ct(wf, "KSampler")["inputs"]
|
||||||
|
assert ks["steps"] == 25 and ks["cfg"] == 3.0 and ks["seed"] == 7
|
||||||
|
assert node_by_ct(wf, "VideoLinearCFGGuidance")["inputs"]["min_cfg"] == 1.5
|
||||||
|
save = node_by_ct(wf, "SaveAnimatedWEBP")["inputs"]
|
||||||
|
assert save["filename_prefix"] == "myclip"
|
||||||
|
# SaveAnimatedWEBP declara fps como FLOAT en /object_info.
|
||||||
|
assert save["fps"] == 10.0
|
||||||
|
assert isinstance(save["fps"], float)
|
||||||
|
|
||||||
|
|
||||||
|
def test_determinista():
|
||||||
|
a = comfyui_build_img2vid_workflow("example.png", seed=7)
|
||||||
|
b = comfyui_build_img2vid_workflow("example.png", seed=7)
|
||||||
|
assert a == b
|
||||||
Reference in New Issue
Block a user