signsur4739379373 commited on
Commit
8ed76e5
·
0 Parent(s):
Files changed (5) hide show
  1. .gitattributes +35 -0
  2. README.md +19 -0
  3. app.py +1104 -0
  4. bernini_r2v_base.json +1 -0
  5. requirements.txt +20 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Bernini-R Wan 2.2 R2V Lightning
3
+ emoji: 🎬
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: gradio
7
+ sdk_version: 6.15.0
8
+ app_file: app.py
9
+ pinned: false
10
+ python_version: "3.10"
11
+ ---
12
+
13
+ # Bernini-R Wan 2.2 R2V Lightning
14
+
15
+ Reference to video generation with Bernini-R.
16
+
17
+ - **Paper**: [arXiv 2605.22344](https://arxiv.org/abs/2605.22344)
18
+ - **Model weights**: [Comfy-Org/Bernini-R](https://huggingface.co/Comfy-Org/Bernini-R)
19
+ - **Code**: [github.com/bytedance/Bernini](https://github.com/bytedance/Bernini)
app.py ADDED
@@ -0,0 +1,1104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import json
5
+ import os
6
+ import pathlib
7
+ import random
8
+ import re
9
+ import shutil
10
+ import subprocess
11
+ import sys
12
+ import tempfile
13
+ import time
14
+ import uuid
15
+ from typing import Any
16
+
17
+ from PIL import Image as _PILImage
18
+
19
+ _TARGET_MP = 848 * 480
20
+
21
+ ASPECT_PRESETS: dict[str, tuple[int, int]] = {
22
+ "16:9": (848, 480),
23
+ "9:16": (480, 848),
24
+ "1:1": (640, 640),
25
+ "4:3": (736, 560),
26
+ "3:4": (560, 736),
27
+ }
28
+
29
+
30
+ def _compute_dims(aspect_ratio: str, first_image_path: str | None, use_ref: bool) -> tuple[int, int]:
31
+ if use_ref and first_image_path and os.path.exists(first_image_path):
32
+ try:
33
+ with _PILImage.open(first_image_path) as im:
34
+ iw, ih = im.size
35
+ ratio = iw / ih
36
+ h = round((_TARGET_MP / ratio) ** 0.5 / 16) * 16
37
+ w = round((_TARGET_MP / h / 16)) * 16
38
+ h = max(16, h)
39
+ w = max(16, w)
40
+ return w, h
41
+ except Exception:
42
+ pass
43
+ return ASPECT_PRESETS.get(aspect_ratio, (848, 480))
44
+
45
+ def _setup_cuda_lib_path() -> None:
46
+ candidates = [
47
+ "/cuda-image/usr/local/cuda-13.0/targets/x86_64-linux/lib",
48
+ "/cuda-image/usr/local/cuda-13.0/lib64",
49
+ "/usr/local/cuda-13.0/targets/x86_64-linux/lib",
50
+ "/usr/local/cuda-13.0/lib64",
51
+ "/usr/local/cuda/targets/x86_64-linux/lib",
52
+ "/usr/local/cuda/lib64",
53
+ ]
54
+ for base in ("/cuda-image/usr/local", "/usr/local"):
55
+ bp = pathlib.Path(base)
56
+ if bp.exists():
57
+ for found in bp.rglob("libcudart.so.13*"):
58
+ candidates.insert(0, str(found.parent))
59
+ break
60
+ for p in candidates:
61
+ if pathlib.Path(p).is_dir():
62
+ cur = os.environ.get("LD_LIBRARY_PATH", "")
63
+ os.environ["LD_LIBRARY_PATH"] = f"{p}:{cur}"
64
+ print(f"[cuda] LD_LIBRARY_PATH set to include {p}", flush=True)
65
+ return
66
+ print("[cuda] WARNING: could not find libcudart.so.13 directory", flush=True)
67
+
68
+ _setup_cuda_lib_path()
69
+
70
+ import gradio as gr
71
+ import spaces
72
+ import torch
73
+
74
+ ROOT = pathlib.Path(__file__).resolve().parent
75
+ COMFY = ROOT / "ComfyUI"
76
+ MODELS = COMFY / "models"
77
+ INPUT = COMFY / "input"
78
+ OUTPUT = COMFY / "output"
79
+
80
+ WORKFLOW_FILE = "bernini_r2v_base.json"
81
+
82
+ COMFY_COMMIT = "4e1f7cb1db1c26bb9ee61cf1875776517e2abae8"
83
+
84
+ CUSTOM_NODES = [
85
+ ("ComfyUI-WanVideoWrapper", "https://github.com/kijai/ComfyUI-WanVideoWrapper.git"),
86
+ ("ComfyUI-KJNodes", "https://github.com/kijai/ComfyUI-KJNodes.git"),
87
+ ("ComfyUI-RH-Bernini", "https://github.com/RH-RunningHub/ComfyUI-RH-Bernini.git"),
88
+ ("ComfyUI-VideoHelperSuite", "https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git"),
89
+ ("ComfyUI-Frame-Interpolation", "https://github.com/Fannovel16/ComfyUI-Frame-Interpolation.git"),
90
+ ]
91
+
92
+ DOWNLOADS = [
93
+ {
94
+ "repo": "Comfy-Org/Bernini-R",
95
+ "file": "diffusion_models/wan2.2_bernini_r_high_noise_fp8_scaled.safetensors",
96
+ "dest": MODELS / "diffusion_models" / "Wan22_Bernini_HIGH_fp8_e4m3fn_scaled.safetensors",
97
+ "label": "bernini HIGH fp8",
98
+ },
99
+ {
100
+ "repo": "Comfy-Org/Bernini-R",
101
+ "file": "diffusion_models/wan2.2_bernini_r_low_noise_fp8_scaled.safetensors",
102
+ "dest": MODELS / "diffusion_models" / "Wan22_Bernini_LOW_fp8_e4m3fn_scaled.safetensors",
103
+ "label": "bernini LOW fp8",
104
+ },
105
+ {
106
+ "repo": "Osrivers/nsfw_wan_umt5-xxl_fp8_scaled.safetensors",
107
+ "file": "nsfw_wan_umt5-xxl_fp8_scaled.safetensors",
108
+ "dest": MODELS / "text_encoders" / "umt5_xxl_fp8_e4m3fn_scaled.safetensors",
109
+ "label": "t5 text encoder fp8",
110
+ },
111
+ {
112
+ "repo": "Comfy-Org/Wan_2.1_ComfyUI_repackaged",
113
+ "file": "split_files/vae/wan_2.1_vae.safetensors",
114
+ "dest": MODELS / "vae" / "wan_2.1_vae.safetensors",
115
+ "label": "wan vae",
116
+ },
117
+ {
118
+ "repo": "Kijai/WanVideo_comfy",
119
+ "file": "Lightx2v/lightx2v_T2V_14B_cfg_step_distill_v2_lora_rank64_bf16.safetensors",
120
+ "dest": MODELS / "loras" / "lightx2v_T2V_14B_cfg_step_distill_v2_lora_rank64_bf16.safetensors",
121
+ "label": "lightx2v lora",
122
+ },
123
+ {
124
+ "repo": "Comfy-Org/Wan_2.1_ComfyUI_repackaged",
125
+ "file": "split_files/clip_vision/clip_vision_h.safetensors",
126
+ "dest": MODELS / "clip_vision" / "clip_vision_h.safetensors",
127
+ "label": "clip vision h",
128
+ },
129
+ {
130
+ "repo": "signsur4739379373/archive",
131
+ "file": "wan22/wamu_v3_lightning_lora_high_noise_r128.safetensors",
132
+ "dest": MODELS / "loras" / "wamu_v3_lora_high_noise_r128.safetensors",
133
+ "label": "wamu high lora",
134
+ },
135
+ {
136
+ "repo": "signsur4739379373/archive",
137
+ "file": "wan22/wamu_v3_lightning_lora_low_noise_r128.safetensors",
138
+ "dest": MODELS / "loras" / "wamu_v3_lora_low_noise_r128.safetensors",
139
+ "label": "wamu low lora",
140
+ },
141
+ {
142
+ "repo": "Kijai/WanVideo_comfy",
143
+ "file": "Lightx2v/lightx2v_I2V_14B_480p_cfg_step_distill_rank128_bf16.safetensors",
144
+ "dest": MODELS / "loras" / "lightx2v_I2V_14B_480p_cfg_step_distill_rank128_bf16.safetensors",
145
+ "label": "lightx2v I2V lora",
146
+ },
147
+ {
148
+ "repo": "yeqiu168182/DR34ML4Y_I2V_14B_HIGH",
149
+ "file": "DR34ML4Y_I2V_14B_HIGH.safetensors",
150
+ "dest": MODELS / "loras" / "DR34ML4Y_I2V_14B_HIGH.safetensors",
151
+ "label": "dreamly high lora",
152
+ },
153
+ {
154
+ "repo": "yeqiu168182/DR34ML4Y_I2V_14B_LOW",
155
+ "file": "DR34ML4Y_I2V_14B_LOW.safetensors",
156
+ "dest": MODELS / "loras" / "DR34ML4Y_I2V_14B_LOW.safetensors",
157
+ "label": "dreamly low lora",
158
+ },
159
+ {
160
+ "repo": "signsur4739379373/ipnc_antiloras_archive",
161
+ "file": "Wan22_BerniniR_DR34ML4Y_HIGH_Rank1_IPNC.safetensors",
162
+ "dest": MODELS / "loras" / "Wan22_BerniniR_DR34ML4Y_HIGH_Rank1_IPNC.safetensors",
163
+ "label": "dreamly high IPNC",
164
+ },
165
+ {
166
+ "repo": "signsur4739379373/ipnc_antiloras_archive",
167
+ "file": "Wan22_BerniniR_DR34ML4Y_LOW_Rank1_IPNC.safetensors",
168
+ "dest": MODELS / "loras" / "Wan22_BerniniR_DR34ML4Y_LOW_Rank1_IPNC.safetensors",
169
+ "label": "dreamly low IPNC",
170
+ },
171
+ {
172
+ "repo": "signsur4739379373/ipnc_antiloras_archive",
173
+ "file": "Wan22_BerniniR_wamu_v3_HIGH_Rank1_IPNC.safetensors",
174
+ "dest": MODELS / "loras" / "Wan22_BerniniR_wamu_v3_HIGH_Rank1_IPNC.safetensors",
175
+ "label": "wamu high IPNC",
176
+ },
177
+ {
178
+ "repo": "signsur4739379373/ipnc_antiloras_archive",
179
+ "file": "Wan22_BerniniR_wamu_v3_LOW_Rank1_IPNC.safetensors",
180
+ "dest": MODELS / "loras" / "Wan22_BerniniR_wamu_v3_LOW_Rank1_IPNC.safetensors",
181
+ "label": "wamu low IPNC",
182
+ },
183
+ {
184
+ "repo": "signsur4739379373/archive",
185
+ "file": "wan22/nsfwsvicamera_lora_high_r128.safetensors",
186
+ "dest": MODELS / "loras" / "nsfwsvicamera_lora_high_r128.safetensors",
187
+ "label": "svicamera high lora",
188
+ },
189
+ {
190
+ "repo": "signsur4739379373/archive",
191
+ "file": "wan22/nsfwsvicamera_lora_low_r128.safetensors",
192
+ "dest": MODELS / "loras" / "nsfwsvicamera_lora_low_r128.safetensors",
193
+ "label": "svicamera low lora",
194
+ },
195
+ {
196
+ "repo": "signsur4739379373/ipnc_antiloras_archive",
197
+ "file": "Wan22_BerniniR_nsfwsvicamera_HIGH_Rank1_IPNC.safetensors",
198
+ "dest": MODELS / "loras" / "Wan22_BerniniR_nsfwsvicamera_HIGH_Rank1_IPNC.safetensors",
199
+ "label": "svicamera high IPNC",
200
+ },
201
+ {
202
+ "repo": "signsur4739379373/ipnc_antiloras_archive",
203
+ "file": "Wan22_BerniniR_nsfwsvicamera_LOW_Rank1_IPNC.safetensors",
204
+ "dest": MODELS / "loras" / "Wan22_BerniniR_nsfwsvicamera_LOW_Rank1_IPNC.safetensors",
205
+ "label": "svicamera low IPNC",
206
+ },
207
+ {
208
+ "repo": "VMTamashii/rife49",
209
+ "file": "rife49.pth",
210
+ "dest": COMFY / "custom_nodes" / "ComfyUI-Frame-Interpolation" / "ckpts" / "rife" / "rife49.pth",
211
+ "label": "rife49 model",
212
+ },
213
+ ]
214
+
215
+ SAVE_BASE = tempfile.mkdtemp(prefix="bernini_comfy_")
216
+ os.makedirs(SAVE_BASE, exist_ok=True)
217
+
218
+ MAX_SEED = 2_147_483_647
219
+
220
+ _comfy_ready = False
221
+ _nodes_ready = False
222
+ _models_ready = False
223
+
224
+ def _run(cmd: list[str], cwd: pathlib.Path | None = None, check: bool = True) -> subprocess.CompletedProcess:
225
+ print("[setup]", " ".join(str(x) for x in cmd), flush=True)
226
+ return subprocess.run(cmd, cwd=str(cwd) if cwd else None, check=check)
227
+
228
+ def _pip_install(args: list[str], check: bool = True) -> None:
229
+ _run([sys.executable, "-m", "pip", "install", "--no-cache-dir", *args], check=check)
230
+
231
+ def _install_filtered_requirements(req_path: pathlib.Path) -> None:
232
+ if not req_path.exists():
233
+ return
234
+ blocked = {"torch", "torchvision", "torchaudio", "transformers", "huggingface-hub", "accelerate"}
235
+ safe: list[str] = []
236
+ for line in req_path.read_text(encoding="utf-8", errors="ignore").splitlines():
237
+ item = line.strip()
238
+ if not item or item.startswith("#"):
239
+ continue
240
+ low = item.lower().replace("_", "-")
241
+ package = re.split(r"[<>=!~;\[\s]", low, maxsplit=1)[0]
242
+ if package in blocked:
243
+ continue
244
+ safe.append(item)
245
+ if safe:
246
+ _pip_install(safe, check=False)
247
+
248
+ def _ensure_repo(path: pathlib.Path, url: str, commit: str | None = None) -> None:
249
+ if not path.exists():
250
+ _run(["git", "clone", "--depth", "1", url, str(path)])
251
+ if commit:
252
+ _run(["git", "fetch", "--depth", "1", "origin", commit], cwd=path, check=False)
253
+ _run(["git", "checkout", commit], cwd=path, check=False)
254
+
255
+ def _apply_comfy_utils_namespace_fix() -> None:
256
+ utils_path = COMFY / "utils"
257
+ utilities_path = COMFY / "utilities"
258
+ if utils_path.exists() and not utilities_path.exists():
259
+ utils_path.rename(utilities_path)
260
+ replacements = [
261
+ (re.compile(r"(^|\n)(\s*)from utils(\s|\.)"), r"\1\2from utilities\3"),
262
+ (re.compile(r"(^|\n)(\s*)import utils(\s|\.|$)"), r"\1\2import utilities\3"),
263
+ ]
264
+ for path in COMFY.rglob("*.py"):
265
+ if "__pycache__" in path.parts:
266
+ continue
267
+ try:
268
+ text = path.read_text(encoding="utf-8")
269
+ except UnicodeDecodeError:
270
+ continue
271
+ updated = text
272
+ for pattern, repl in replacements:
273
+ updated = pattern.sub(repl, updated)
274
+ updated = updated.replace("from utils import", "from utilities import")
275
+ if updated != text:
276
+ path.write_text(updated, encoding="utf-8")
277
+
278
+ def _download_to_dest(repo: str, file: str, dest: pathlib.Path, token: str | None = None) -> None:
279
+ from huggingface_hub import hf_hub_download
280
+ dest.parent.mkdir(parents=True, exist_ok=True)
281
+ downloaded = hf_hub_download(repo_id=repo, filename=file, token=token)
282
+ if not dest.exists():
283
+ shutil.copy2(downloaded, dest)
284
+
285
+ def _ensure_comfy() -> None:
286
+ global _comfy_ready
287
+ if _comfy_ready:
288
+ return
289
+
290
+ _ensure_repo(COMFY, "https://github.com/Comfy-Org/ComfyUI.git", commit=COMFY_COMMIT)
291
+ _install_filtered_requirements(COMFY / "requirements.txt")
292
+
293
+ custom_root = COMFY / "custom_nodes"
294
+ custom_root.mkdir(parents=True, exist_ok=True)
295
+ for name, url in CUSTOM_NODES:
296
+ node_path = custom_root / name
297
+ _ensure_repo(node_path, url)
298
+ _install_filtered_requirements(node_path / "requirements.txt")
299
+
300
+ _apply_comfy_utils_namespace_fix()
301
+ _comfy_ready = True
302
+ print("[startup] ComfyUI + custom nodes ready.", flush=True)
303
+
304
+ def _ensure_models() -> None:
305
+ global _models_ready
306
+ if _models_ready:
307
+ return
308
+
309
+ token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGINGFACE_HUB_TOKEN")
310
+ for item in DOWNLOADS:
311
+ dest = pathlib.Path(item["dest"])
312
+ if dest.exists():
313
+ continue
314
+ print(f"[startup] downloading {item['label']}...", flush=True)
315
+ _download_to_dest(item["repo"], item["file"], dest, token)
316
+
317
+ _models_ready = True
318
+ print("[startup] all models ready.", flush=True)
319
+
320
+ def _init_comfy_nodes() -> None:
321
+ global _nodes_ready
322
+ if _nodes_ready:
323
+ return
324
+
325
+ comfy_path = str(COMFY)
326
+ sys.path = [p for p in sys.path if p != comfy_path]
327
+ sys.path.insert(0, comfy_path)
328
+ for module_name in list(sys.modules):
329
+ if module_name == "utils" or module_name.startswith("utils."):
330
+ del sys.modules[module_name]
331
+ os.chdir(COMFY)
332
+
333
+ import types as _types, importlib.util as _ilu
334
+ _ta = _types.ModuleType("torchaudio")
335
+ _ta.__spec__ = _ilu.spec_from_loader("torchaudio", loader=None)
336
+ _ta.__version__ = "0.0.0"
337
+ sys.modules.setdefault("torchaudio", _ta)
338
+ for _sub in ["torchaudio.functional", "torchaudio.transforms", "torchaudio._extension"]:
339
+ _m = _types.ModuleType(_sub)
340
+ _m.__spec__ = _ilu.spec_from_loader(_sub, loader=None)
341
+ sys.modules.setdefault(_sub, _m)
342
+
343
+ import execution
344
+ import nodes
345
+ import server
346
+
347
+
348
+ loop = asyncio.new_event_loop()
349
+ asyncio.set_event_loop(loop)
350
+ server_instance = server.PromptServer(loop)
351
+ execution.PromptQueue(server_instance)
352
+ loop.run_until_complete(nodes.init_extra_nodes())
353
+ _nodes_ready = True
354
+ print("[startup] ComfyUI nodes initialized.", flush=True)
355
+
356
+ import numpy as _np
357
+
358
+ def _compute_split(total_steps, flow_shift=3.0, boundary_ratio=0.9, num_train_timesteps=1000):
359
+ sigmas = _np.linspace(1, 0, total_steps + 1)[:-1]
360
+ sigma_shifted = flow_shift * sigmas / (1 + (flow_shift - 1) * sigmas)
361
+ timesteps = sigma_shifted * (num_train_timesteps - 1)
362
+ n_above = int(_np.sum(timesteps >= boundary_ratio * num_train_timesteps))
363
+ return total_steps - n_above
364
+
365
+
366
+ DEFAULT_NEGATIVE = (
367
+ "色调艳丽,过曝,静态,场景切换,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,"
368
+ "最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,"
369
+ "畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走"
370
+ )
371
+
372
+
373
+ R2V_TEMPLATE = """You are an expert at writing subject-driven video generation prompts. I'm providing you with:
374
+ 1. {image_num} reference image(s) of the subject(s) that will appear in the video (referred to as image0, image1, image2, ... in order).
375
+ 2. An original video description text.
376
+
377
+ Your task is to rewrite the original description into a new format with TWO parts concatenated together:
378
+
379
+ **Part 1 - Short instruction**: A concise sentence describing who the subject(s) from the reference image(s) are, what they look like briefly, where they are, and what key action/motion they perform. Reference the subject(s) using "image0", "image1", etc. to link them to the provided reference images.
380
+
381
+ **Part 2 - Long instruction**: A detailed "Generate a video where..." paragraph that describes:
382
+ - The subject(s) from the reference image(s) with detailed appearance (hair, clothing, accessories, expression, etc.), referencing them as "the person/man/woman from image0" etc.
383
+ - The scene/environment in detail (background, lighting, objects, atmosphere).
384
+ - The motion and actions in a step-by-step temporal sequence (at the start..., then..., after that...).
385
+ - The motion should remain natural and realistic.
386
+
387
+ Requirements:
388
+ - You MUST reference each subject using "image0", "image1", "image2", etc. to correspond to the provided reference images in order.
389
+ - The appearance description of each subject must be based on what you actually see in the reference image(s). Do NOT hallucinate details not visible in the images.
390
+ - The scene, actions, and motion should be derived from the original description text, but rewritten to be more detailed and vivid.
391
+ - The output must be entirely in English.
392
+ - Return ONLY a JSON object with one key: "rewritten_text". The value should be the full rewritten text (short instruction + long instruction concatenated as one string). No extra text.
393
+
394
+ Original description:
395
+ {original_text}
396
+ """
397
+
398
+
399
+ def _enhance_prompt_r2v(prompt: str, image_paths: list[str]) -> str | None:
400
+ """Call grok-4.3 via xAI API to enhance prompt for r2v. Returns None on failure."""
401
+ api_key = os.environ.get("XAI_API_KEY")
402
+ if not api_key:
403
+ print("[enhancer] XAI_API_KEY not set, skipping enhancement", flush=True)
404
+ return None
405
+ try:
406
+ import base64
407
+ import json as _json
408
+ from openai import OpenAI
409
+ client = OpenAI(api_key=api_key, base_url="https://api.x.ai/v1")
410
+ image_num = len(image_paths)
411
+ user_text = R2V_TEMPLATE.format(image_num=max(image_num, 1), original_text=prompt)
412
+ content: list = [{"type": "text", "text": user_text}]
413
+ for i, path in enumerate(image_paths):
414
+ if not path or not os.path.exists(path):
415
+ continue
416
+ with open(path, "rb") as f:
417
+ b64 = base64.b64encode(f.read()).decode("utf-8")
418
+ content.append({"type": "text", "text": f"\n[Image {i}]:"})
419
+ content.append({"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64}"}})
420
+ messages = [
421
+ {"role": "system", "content": "You are a helpful assistant."},
422
+ {"role": "user", "content": content},
423
+ ]
424
+ resp = client.chat.completions.create(
425
+ model="grok-4.3",
426
+ messages=messages,
427
+ max_completion_tokens=8192,
428
+ response_format={"type": "json_object"},
429
+ )
430
+ text = resp.choices[0].message.content or ""
431
+ enhanced = _json.loads(text).get("rewritten_text", "").strip()
432
+ if enhanced:
433
+ print(f"[enhancer] enhanced prompt ({len(enhanced)} chars)", flush=True)
434
+ return enhanced
435
+ return None
436
+ except Exception as e:
437
+ print(f"[enhancer] failed: {e}", flush=True)
438
+ return None
439
+
440
+ def _load_workflow() -> dict[str, Any]:
441
+ wf_path = ROOT / WORKFLOW_FILE
442
+ return json.loads(wf_path.read_text(encoding="utf-8"))
443
+
444
+ NODE_OUTPUT = 67
445
+
446
+ def _convert_visual_to_api(visual: dict) -> dict[str, Any]:
447
+ import nodes as comfy_nodes
448
+
449
+ link_map: dict[int, Any] = {}
450
+ for link in visual.get("links", []):
451
+ link_id, src_node, src_slot, *_ = link
452
+ link_map[int(link_id)] = [str(src_node), src_slot]
453
+
454
+ BYPASS_TYPES = {"PathchSageAttentionKJ"}
455
+ for node in visual.get("nodes", []):
456
+ if node.get("type") not in BYPASS_TYPES:
457
+ continue
458
+ src_ref = None
459
+ for inp in node.get("inputs") or []:
460
+ lid = inp.get("link")
461
+ if lid is not None and lid in link_map:
462
+ src_ref = link_map[lid]
463
+ break
464
+ if src_ref is None:
465
+ continue
466
+ for out in node.get("outputs") or []:
467
+ for out_lid in (out.get("links") or []):
468
+ if out_lid in link_map:
469
+ link_map[out_lid] = list(src_ref)
470
+
471
+ set_sources: dict[str, Any] = {}
472
+ set_node_sources: dict[int, Any] = {}
473
+ for node in visual.get("nodes", []):
474
+ if node.get("type") not in {"SetNode", "SetNodeAny"}:
475
+ continue
476
+ name = (node.get("widgets_values") or [""])[0]
477
+ for inp in node.get("inputs") or []:
478
+ lid = inp.get("link")
479
+ if lid in link_map:
480
+ set_sources[name] = link_map[lid]
481
+ set_node_sources[int(node["id"])] = link_map[lid]
482
+
483
+ changed = True
484
+ while changed:
485
+ changed = False
486
+ for lid, src in list(link_map.items()):
487
+ if isinstance(src, list):
488
+ try:
489
+ sid = int(src[0])
490
+ except (ValueError, TypeError):
491
+ continue
492
+ if sid in set_node_sources:
493
+ rep = set_node_sources[sid]
494
+ if link_map[lid] != rep:
495
+ link_map[lid] = rep
496
+ changed = True
497
+ for node in visual.get("nodes", []):
498
+ if node.get("type") not in {"GetNode", "GetNodeAny"}:
499
+ continue
500
+ name = (node.get("widgets_values") or [""])[0]
501
+ if name not in set_sources:
502
+ continue
503
+ for lid, src in list(link_map.items()):
504
+ if isinstance(src, list) and src[0] == str(node["id"]):
505
+ rep = set_sources[name]
506
+ if link_map[lid] != rep:
507
+ link_map[lid] = rep
508
+ changed = True
509
+
510
+ skip_types = {"Note", "NoteNode", "MarkdownNote", "GetNode", "GetNodeAny", "SetNode", "SetNodeAny",
511
+ "PathchSageAttentionKJ"}
512
+ MUTED_MODE = 4
513
+ api: dict[str, Any] = {}
514
+
515
+ for node in visual.get("nodes", []):
516
+ node_id = int(node["id"])
517
+ class_type = node.get("type", "")
518
+ if class_type in skip_types:
519
+ continue
520
+ if node.get("mode") == MUTED_MODE:
521
+ print(f"[workflow] skipping muted node {class_type} id={node_id}", flush=True)
522
+ continue
523
+ if class_type not in comfy_nodes.NODE_CLASS_MAPPINGS:
524
+ print(f"[workflow] skipping unknown node {class_type} id={node_id}", flush=True)
525
+ continue
526
+
527
+ inputs: dict[str, Any] = {}
528
+ for inp in node.get("inputs") or []:
529
+ lid = inp.get("link")
530
+ if lid is not None and lid in link_map:
531
+ inputs[inp["name"]] = link_map[lid]
532
+
533
+ widgets = node.get("widgets_values") or []
534
+ if widgets:
535
+ if isinstance(widgets, dict):
536
+
537
+ for k, v in widgets.items():
538
+ if k != "videopreview":
539
+ inputs.setdefault(k, v)
540
+ else:
541
+
542
+ param_names = [
543
+ inp["name"]
544
+ for inp in node.get("inputs") or []
545
+ if isinstance(inp.get("widget"), dict) and inp["widget"].get("name")
546
+ ]
547
+ if not param_names:
548
+
549
+ cls = comfy_nodes.NODE_CLASS_MAPPINGS[class_type]
550
+ try:
551
+ cls_inp = cls.INPUT_TYPES()
552
+ for grp in ("required", "optional"):
553
+ for pname, spec in cls_inp.get(grp, {}).items():
554
+ typ = spec[0] if isinstance(spec, (tuple, list)) and spec else spec
555
+ if isinstance(typ, (list, tuple)) or str(typ).upper() in {"FLOAT", "INT", "STRING", "BOOLEAN", "COMBO"}:
556
+ param_names.append(pname)
557
+ except Exception:
558
+ pass
559
+
560
+ CTRL = {'randomize', 'fixed', 'increment', 'decrement'}
561
+ wi = 0
562
+ for pname in param_names:
563
+ if wi >= len(widgets):
564
+ break
565
+ inputs.setdefault(pname, widgets[wi])
566
+ wi += 1
567
+ if wi < len(widgets) and isinstance(widgets[wi], str) and widgets[wi] in CTRL:
568
+ wi += 1
569
+
570
+ api[str(node_id)] = {"class_type": class_type, "inputs": inputs}
571
+
572
+ return api
573
+
574
+ _LORA_CHAIN = [
575
+ {
576
+ "id": 2003,
577
+ "chain": "high",
578
+ "file": "DR34ML4Y_I2V_14B_HIGH.safetensors",
579
+ "default": 0.3,
580
+ },
581
+ {
582
+ "id": 2001,
583
+ "chain": "high",
584
+ "file": "wamu_v3_lora_high_noise_r128.safetensors",
585
+ "default": 1.0,
586
+ },
587
+ {
588
+ "id": 2002,
589
+ "chain": "high",
590
+ "file": "lightx2v_I2V_14B_480p_cfg_step_distill_rank128_bf16.safetensors",
591
+ "default": -1.0,
592
+ },
593
+ {
594
+ "id": 2004,
595
+ "chain": "low",
596
+ "file": "wamu_v3_lora_low_noise_r128.safetensors",
597
+ "default": 0.5,
598
+ },
599
+ {
600
+ "id": 2005,
601
+ "chain": "low",
602
+ "file": "lightx2v_I2V_14B_480p_cfg_step_distill_rank128_bf16.safetensors",
603
+ "default": -1.0,
604
+ },
605
+ {
606
+ "id": 2006,
607
+ "chain": "low",
608
+ "file": "DR34ML4Y_I2V_14B_LOW.safetensors",
609
+ "default": 0.5,
610
+ },
611
+ ]
612
+
613
+ LORA_DEFAULTS = {l["id"]: l["default"] for l in _LORA_CHAIN}
614
+
615
+
616
+ RIFE_MULTIPLIERS = {"no rife": 1, "2x rife": 2, "4x rife": 4}
617
+
618
+
619
+ def _patch_api_workflow(
620
+ api: dict[str, Any],
621
+ prompt: str,
622
+ negative: str,
623
+ image_names: list[str],
624
+ seed: int,
625
+ width: int,
626
+ height: int,
627
+ num_steps: int = 6,
628
+ num_frames: int = 145,
629
+ sampler_name: str = "uni_pc",
630
+ base_fps: int = 15,
631
+ rife_mode: str = "no rife",
632
+ loras_enabled: bool = False,
633
+ lora_strengths: dict[int, float] | None = None,
634
+ ipnc_enabled: bool = False,
635
+ ipnc_strengths: dict[str, float] | None = None,
636
+ ) -> dict[str, Any]:
637
+ if ipnc_strengths is None:
638
+ ipnc_strengths = {"wamu_h": 100, "dreamly_h": 100, "wamu_l": 100, "dreamly_l": 100, "svicamera_h": 100, "svicamera_l": 100}
639
+
640
+ def _set(node_id: int, key: str, val: Any) -> None:
641
+ k = str(node_id)
642
+ if k in api:
643
+ api[k]["inputs"][key] = val
644
+
645
+ _set(6, "text", f"You are a helpful assistant specialized in subject-to-video generation. {prompt}")
646
+ _set(7, "text", negative)
647
+ _set(112, "value", width)
648
+ _set(114, "value", height)
649
+ _set(128, "value", seed)
650
+ _set(57, "noise_seed", seed)
651
+ _set(58, "noise_seed", 0)
652
+ _set(132, "height", height)
653
+ _set(132, "width", width)
654
+ _set(132, "length", num_frames)
655
+
656
+ _set(119, "image", image_names[0])
657
+
658
+ split = _compute_split(num_steps)
659
+ _set(57, "steps", num_steps)
660
+ _set(57, "start_at_step", 0)
661
+ _set(57, "end_at_step", split)
662
+ _set(57, "sampler_name", sampler_name)
663
+ _set(58, "steps", num_steps)
664
+ _set(58, "start_at_step", split)
665
+ _set(58, "end_at_step", num_steps)
666
+ _set(58, "sampler_name", sampler_name)
667
+
668
+ for i, name in enumerate(image_names[1:], 1):
669
+ nid = 5000 + i
670
+ api[str(nid)] = {
671
+ "class_type": "LoadImage",
672
+ "inputs": {"image": name, "upload": "image"},
673
+ }
674
+ api["136"]["inputs"][f"images.image{i}"] = [str(nid), 0]
675
+
676
+ if loras_enabled:
677
+ strengths = lora_strengths or LORA_DEFAULTS
678
+ high_src = ["71", 0]
679
+ low_src = ["56", 0]
680
+
681
+ # IDs 2001-2006: main loras (existing)
682
+ # IDs 2011-2014: IPNC loras injected after specific mains
683
+ # Chain HIGH:
684
+ # DR34ML4Y(2003) -> DR34ML4Y_IPNC(2011) -> wamu(2001) ->
685
+ # lightx2v_I2V(2002) -> wamu_IPNC(2012) -> lightx2v_T2V(baked)
686
+ # Chain LOW:
687
+ # wamu(2004) -> lightx2v_I2V(2005) -> wamu_IPNC(2013) ->
688
+ # lightx2v_T2V(baked) -> DR34ML4Y(2006) -> DR34ML4Y_IPNC(2014)
689
+
690
+ s_wamu_h_val = strengths.get(2001, 1.0)
691
+ s_dreamly_h_val = strengths.get(2003, 0.3)
692
+ s_wamu_l_val = strengths.get(2004, 0.5)
693
+ s_dreamly_l_val = strengths.get(2006, 0.5)
694
+ s_svicamera_h_val = strengths.get(2021, 0.0)
695
+ s_svicamera_l_val = strengths.get(2023, 0.0)
696
+
697
+ def _add_lora(nid, src, fname, strength):
698
+ api[str(nid)] = {
699
+ "class_type": "LoraLoaderModelOnly",
700
+ "inputs": {"model": src, "lora_name": fname,
701
+ "strength_model": strength},
702
+ }
703
+ return [str(nid), 0]
704
+
705
+ # ── HIGH chain ──────────────────────────────────────────────
706
+ # DR34ML4Y HIGH
707
+ high_src = _add_lora(2003, high_src,
708
+ "DR34ML4Y_I2V_14B_HIGH.safetensors", s_dreamly_h_val)
709
+ # DR34ML4Y_IPNC HIGH
710
+ if ipnc_enabled and ipnc_strengths.get("dreamly_h", 0) > 0:
711
+ ipnc_s = s_dreamly_h_val * ipnc_strengths["dreamly_h"] / 100.0
712
+ high_src = _add_lora(2011, high_src,
713
+ "Wan22_BerniniR_DR34ML4Y_HIGH_Rank1_IPNC.safetensors", ipnc_s)
714
+ # wamu HIGH
715
+ high_src = _add_lora(2001, high_src,
716
+ "wamu_v3_lora_high_noise_r128.safetensors", s_wamu_h_val)
717
+ # lightx2v_I2V HIGH (negation)
718
+ high_src = _add_lora(2002, high_src,
719
+ "lightx2v_I2V_14B_480p_cfg_step_distill_rank128_bf16.safetensors",
720
+ -s_wamu_h_val)
721
+ # wamu_IPNC HIGH (after lightx2v_I2V negation)
722
+ if ipnc_enabled and ipnc_strengths.get("wamu_h", 0) > 0:
723
+ ipnc_s = s_wamu_h_val * ipnc_strengths["wamu_h"] / 100.0
724
+ high_src = _add_lora(2012, high_src,
725
+ "Wan22_BerniniR_wamu_v3_HIGH_Rank1_IPNC.safetensors", ipnc_s)
726
+ # svicamera HIGH
727
+ high_src = _add_lora(2021, high_src, "nsfwsvicamera_lora_high_r128.safetensors",
728
+ s_svicamera_h_val)
729
+ # svicamera_IPNC HIGH
730
+ if ipnc_enabled and ipnc_strengths.get("svicamera_h", 0) > 0:
731
+ ipnc_s = s_svicamera_h_val * ipnc_strengths["svicamera_h"] / 100.0
732
+ high_src = _add_lora(2022, high_src,
733
+ "Wan22_BerniniR_nsfwsvicamera_HIGH_Rank1_IPNC.safetensors", ipnc_s)
734
+
735
+ # ── LOW chain ───────────────────────────────────────────────
736
+ # wamu LOW
737
+ low_src = _add_lora(2004, low_src,
738
+ "wamu_v3_lora_low_noise_r128.safetensors", s_wamu_l_val)
739
+ # lightx2v_I2V LOW (negation)
740
+ low_src = _add_lora(2005, low_src,
741
+ "lightx2v_I2V_14B_480p_cfg_step_distill_rank128_bf16.safetensors",
742
+ -s_wamu_l_val)
743
+ # wamu_IPNC LOW (after lightx2v_I2V negation)
744
+ if ipnc_enabled and ipnc_strengths.get("wamu_l", 0) > 0:
745
+ ipnc_s = s_wamu_l_val * ipnc_strengths["wamu_l"] / 100.0
746
+ low_src = _add_lora(2013, low_src,
747
+ "Wan22_BerniniR_wamu_v3_LOW_Rank1_IPNC.safetensors", ipnc_s)
748
+ # DR34ML4Y LOW
749
+ low_src = _add_lora(2006, low_src,
750
+ "DR34ML4Y_I2V_14B_LOW.safetensors", s_dreamly_l_val)
751
+ # DR34ML4Y_IPNC LOW
752
+ if ipnc_enabled and ipnc_strengths.get("dreamly_l", 0) > 0:
753
+ ipnc_s = s_dreamly_l_val * ipnc_strengths["dreamly_l"] / 100.0
754
+ low_src = _add_lora(2014, low_src,
755
+ "Wan22_BerniniR_DR34ML4Y_LOW_Rank1_IPNC.safetensors", ipnc_s)
756
+ # svicamera LOW
757
+ low_src = _add_lora(2023, low_src, "nsfwsvicamera_lora_low_r128.safetensors",
758
+ s_svicamera_l_val)
759
+ # svicamera_IPNC LOW
760
+ if ipnc_enabled and ipnc_strengths.get("svicamera_l", 0) > 0:
761
+ ipnc_s = s_svicamera_l_val * ipnc_strengths["svicamera_l"] / 100.0
762
+ low_src = _add_lora(2024, low_src,
763
+ "Wan22_BerniniR_nsfwsvicamera_LOW_Rank1_IPNC.safetensors", ipnc_s)
764
+
765
+ api["63"]["inputs"]["model"] = high_src
766
+ api["64"]["inputs"]["model"] = low_src
767
+
768
+ multiplier = RIFE_MULTIPLIERS.get(rife_mode, 1)
769
+ output_fps = base_fps * multiplier
770
+
771
+ if multiplier > 1:
772
+ api["3001"] = {
773
+ "class_type": "RIFE VFI",
774
+ "inputs": {
775
+ "frames": ["8", 0],
776
+ "ckpt_name": "rife49.pth",
777
+ "clear_cache_after_n_frames": 10,
778
+ "multiplier": multiplier,
779
+ "fast_mode": True,
780
+ "ensemble": True,
781
+ "scale_factor": 1,
782
+ "dtype": "float32",
783
+ "torch_compile": False,
784
+ "batch_size": 1,
785
+ },
786
+ }
787
+ api["67"]["inputs"]["images"] = ["3001", 0]
788
+
789
+ if "67" in api and isinstance(api["67"]["inputs"].get("frame_rate"), (int, float)):
790
+ api["67"]["inputs"]["frame_rate"] = output_fps
791
+
792
+ return api
793
+
794
+ def _execute_workflow(api: dict[str, Any]) -> str:
795
+ import execution, server as comfy_server
796
+
797
+ loop = asyncio.new_event_loop()
798
+ asyncio.set_event_loop(loop)
799
+ srv = comfy_server.PromptServer(loop)
800
+
801
+ try:
802
+ executor = execution.PromptExecutor(
803
+ srv,
804
+ cache_type=execution.CacheType.RAM_PRESSURE,
805
+ cache_args={"lru": 0, "ram": 2.0, "ram_inactive": 8.0},
806
+ )
807
+ except Exception:
808
+ executor = execution.PromptExecutor(srv)
809
+
810
+ prompt_id = str(uuid.uuid4())
811
+ loop.run_until_complete(executor.execute_async(api, prompt_id, extra_data={}, execute_outputs=[str(NODE_OUTPUT)]))
812
+
813
+ if not getattr(executor, "success", True):
814
+ msgs = getattr(executor, "status_messages", [])
815
+ msg = msgs[-1] if msgs else "comfy execution failed"
816
+ raise RuntimeError(str(msg))
817
+
818
+ for output in (executor.history_result or {}).get("outputs", {}).values():
819
+ for items in output.values():
820
+ if not isinstance(items, list):
821
+ continue
822
+ for item in items:
823
+ fname = item.get("filename") if isinstance(item, dict) else None
824
+ if not fname:
825
+ continue
826
+ subfolder = item.get("subfolder", "")
827
+ kind = item.get("type", "output")
828
+ base = OUTPUT if kind == "output" else COMFY / kind
829
+ candidate = base / subfolder / fname if subfolder else base / fname
830
+ if candidate.exists():
831
+ return str(candidate)
832
+
833
+ raise RuntimeError("ComfyUI finished but no output video found")
834
+
835
+ def _estimate_duration(num_steps, duration_secs, base_fps, aspect_ratio, use_ref_aspect, rife_mode):
836
+ BASE_FRAMES = 45
837
+ BASE_STEP_S = 5.3
838
+ STEP_EXP = 1.2
839
+ n_frames = max(1, round(float(duration_secs) * int(base_fps)))
840
+ gen_w, gen_h = ASPECT_PRESETS.get(str(aspect_ratio), (848, 480))
841
+ frame_factor = (n_frames * gen_w * gen_h) / (BASE_FRAMES * 848 * 480)
842
+ step_time = BASE_STEP_S * frame_factor ** STEP_EXP
843
+ sampler_t = int(num_steps) * step_time
844
+ swap_t = 12 + 6 * frame_factor ** 0.5
845
+ overhead_t = 20 + 8 * max(0, frame_factor - 1)
846
+ rife_mult = {"2x rife": 2, "4x rife": 4}.get(str(rife_mode), 1)
847
+ rife_t = n_frames * (rife_mult - 1) * 0.05 if rife_mult > 1 else 0
848
+ total = (sampler_t + swap_t + overhead_t + rife_t) * 1.05
849
+ return max(30, int(total))
850
+
851
+
852
+ def _get_duration(
853
+ prompt, negative, image_input, seed, aspect_ratio, use_ref_aspect,
854
+ gpu_budget, num_steps, duration_secs, sampler_name, base_fps, rife_mode, *args, **kwargs,
855
+ ):
856
+ if gpu_budget and int(gpu_budget) > 0:
857
+ return int(gpu_budget)
858
+ return _estimate_duration(num_steps, duration_secs, base_fps, aspect_ratio, use_ref_aspect, rife_mode)
859
+
860
+ @spaces.GPU(duration=_get_duration)
861
+ def generate_handler(
862
+ prompt: str,
863
+ negative: str,
864
+ image_input: Any,
865
+ seed: int,
866
+ aspect_ratio: str = "16:9",
867
+ use_ref_aspect: bool = False,
868
+ gpu_budget: int = 0, # 0 = auto-estimate
869
+ num_steps: int = 6,
870
+ duration_secs: float = 10.0,
871
+ sampler_name: str = "uni_pc",
872
+ base_fps: int = 15,
873
+ rife_mode: str = "no rife",
874
+ loras_enabled: bool = False,
875
+ s_wamu_h: float = 1.0,
876
+ s_dreamly_h: float = 0.3,
877
+ s_wamu_l: float = 0.5,
878
+ s_dreamly_l: float = 0.5,
879
+ enhance_prompt: bool = False,
880
+ ipnc_enabled: bool = False,
881
+ ipnc_wamu_h: float = 100.0,
882
+ ipnc_dreamly_h: float = 100.0,
883
+ ipnc_wamu_l: float = 100.0,
884
+ ipnc_dreamly_l: float = 100.0,
885
+ s_svicamera_h: float = 0.0,
886
+ s_svicamera_l: float = 0.0,
887
+ ipnc_svicamera_h: float = 100.0,
888
+ ipnc_svicamera_l: float = 100.0,
889
+ progress=gr.Progress(track_tqdm=True),
890
+ ):
891
+ import traceback as _tb
892
+ try:
893
+ if not (prompt or "").strip():
894
+ return None, "enter a prompt"
895
+
896
+ final_seed = int(seed) if seed else random.randint(0, MAX_SEED)
897
+ negative = negative or DEFAULT_NEGATIVE
898
+
899
+ def _coerce_gallery(g):
900
+ paths = []
901
+ for item in (g or []):
902
+ if isinstance(item, str):
903
+ paths.append(item)
904
+ elif isinstance(item, dict):
905
+ p = item.get("path") or item.get("name")
906
+ if p: paths.append(p)
907
+ elif isinstance(item, (list, tuple)) and item:
908
+ p = item[0]
909
+ if isinstance(p, str): paths.append(p)
910
+ elif isinstance(p, dict): paths.append(p.get("path",""))
911
+ return [p for p in paths if p and os.path.exists(p)][:5]
912
+
913
+ image_paths = _coerce_gallery(image_input)
914
+ if not image_paths:
915
+ return None, "upload at least one reference image"
916
+
917
+ INPUT.mkdir(parents=True, exist_ok=True)
918
+ dest_names = []
919
+ for p in image_paths:
920
+ dn = f"ref_{uuid.uuid4().hex[:8]}_{os.path.basename(p)}"
921
+ shutil.copy2(p, INPUT / dn)
922
+ dest_names.append(dn)
923
+
924
+ gen_w, gen_h = _compute_dims(str(aspect_ratio), image_paths[0], bool(use_ref_aspect))
925
+
926
+ enhanced_prompt_text = None
927
+ if enhance_prompt:
928
+ progress(0.05, desc="enhancing prompt...")
929
+ enhanced_prompt_text = _enhance_prompt_r2v(prompt, image_paths)
930
+ if enhanced_prompt_text:
931
+ prompt = enhanced_prompt_text
932
+
933
+ progress(0.1, desc="building workflow...")
934
+ visual_wf = _load_workflow()
935
+ api_wf = _convert_visual_to_api(visual_wf)
936
+ api_wf = _patch_api_workflow(
937
+ api_wf, prompt, negative,
938
+ dest_names,
939
+ final_seed, gen_w, gen_h,
940
+ num_steps=int(num_steps),
941
+ num_frames=max(1, round(float(duration_secs) * int(base_fps))),
942
+ sampler_name=str(sampler_name),
943
+ base_fps=int(base_fps),
944
+ rife_mode=str(rife_mode),
945
+ loras_enabled=bool(loras_enabled),
946
+ lora_strengths={
947
+ 2001: float(s_wamu_h),
948
+ 2002: -float(s_wamu_h),
949
+ 2003: float(s_dreamly_h),
950
+ 2004: float(s_wamu_l),
951
+ 2005: -float(s_wamu_l),
952
+ 2006: float(s_dreamly_l),
953
+ 2021: float(s_svicamera_h),
954
+ 2023: float(s_svicamera_l),
955
+ },
956
+ ipnc_enabled=bool(ipnc_enabled),
957
+ ipnc_strengths={
958
+ "wamu_h": float(ipnc_wamu_h),
959
+ "dreamly_h": float(ipnc_dreamly_h),
960
+ "wamu_l": float(ipnc_wamu_l),
961
+ "dreamly_l": float(ipnc_dreamly_l),
962
+ "svicamera_h": float(ipnc_svicamera_h),
963
+ "svicamera_l": float(ipnc_svicamera_l),
964
+ },
965
+ )
966
+
967
+ progress(0.3, desc="generating...")
968
+ output_video = _execute_workflow(api_wf)
969
+ except Exception as e:
970
+ tb = _tb.format_exc()
971
+ print(f"[generate] EXCEPTION: {tb}", flush=True)
972
+ return None, f"Generation failed: {type(e).__name__}: {e}"
973
+
974
+ ts = time.strftime("%Y%m%d_%H%M%S")
975
+ out_path = os.path.join(SAVE_BASE, f"r2v_{ts}.mp4")
976
+ shutil.copy2(output_video, out_path)
977
+
978
+ status = f"Done: {out_path}"
979
+ if enhanced_prompt_text:
980
+ status += f"\n\n--- Enhanced prompt ---\n{enhanced_prompt_text}"
981
+ return out_path, status
982
+
983
+ with gr.Blocks(title="Bernini-R Wan 2.2 R2V Lightning") as demo:
984
+ gr.Markdown("# Bernini-R Wan 2.2 R2V Lightning")
985
+
986
+ with gr.Row():
987
+ with gr.Column(scale=1):
988
+ image_input = gr.Gallery(
989
+ label="Reference images (up to 5)",
990
+ columns=5,
991
+ type="filepath",
992
+ height=160,
993
+ )
994
+ prompt = gr.Textbox(
995
+ label="Prompt",
996
+ lines=3,
997
+ placeholder="Describe the subject's action in detail. Reference uploaded images by name (e.g. image0, image1). Example: the person in image0, wearing the outfit from image1, walks confidently through a busy train station.",
998
+ value="Keeping the exact identity and appearance the same as in image0, the person in image0 dances in a supermarket.",
999
+ )
1000
+ with gr.Accordion("Negative prompt", open=False):
1001
+ negative = gr.Textbox(
1002
+ label="",
1003
+ lines=2,
1004
+ value=DEFAULT_NEGATIVE,
1005
+ )
1006
+ with gr.Group():
1007
+ aspect_ratio = gr.Radio(
1008
+ choices=list(ASPECT_PRESETS.keys()),
1009
+ value="16:9",
1010
+ label="Aspect ratio",
1011
+ )
1012
+ use_ref_aspect = gr.Checkbox(
1013
+ label="use first reference image aspect ratio",
1014
+ value=False,
1015
+ )
1016
+
1017
+ with gr.Group(elem_id="loras_9999"):
1018
+ loras_enabled = gr.Checkbox(label="optional loras", value=False)
1019
+ with gr.Column(visible=False) as loras_section:
1020
+ with gr.Accordion("loras", open=True):
1021
+ with gr.Group():
1022
+ gr.Markdown("<div style='padding-left:8px'>High</div>")
1023
+ with gr.Row():
1024
+ s_wamu_h = gr.Slider(-2, 2, value=0.9, step=0.05, label="wamu")
1025
+ s_dreamly_h = gr.Slider(-2, 2, value=0.9, step=0.05, label="dreamly")
1026
+ s_svicamera_h = gr.Slider(-2, 2, value=0.0, step=0.05, label="svicamera")
1027
+ with gr.Group():
1028
+ gr.Markdown("<div style='padding-left:8px'>Low</div>")
1029
+ with gr.Row():
1030
+ s_wamu_l = gr.Slider(-2, 2, value=0.5, step=0.05, label="wamu")
1031
+ s_dreamly_l = gr.Slider(-2, 2, value=0.7, step=0.05, label="dreamly")
1032
+ s_svicamera_l = gr.Slider(-2, 2, value=0.0, step=0.05, label="svicamera")
1033
+ gr.Markdown("<hr style='margin:8px 0'>")
1034
+ ipnc_enabled = gr.Checkbox(label="IPNC", value=False)
1035
+ with gr.Column(visible=False) as ipnc_section:
1036
+ with gr.Group():
1037
+ gr.Markdown("<div style='padding-left:8px'>High</div>")
1038
+ with gr.Row():
1039
+ ipnc_wamu_h = gr.Slider(0, 200, value=100, step=1, label="wamu")
1040
+ ipnc_dreamly_h = gr.Slider(0, 200, value=100, step=1, label="dreamly")
1041
+ ipnc_svicamera_h = gr.Slider(0, 200, value=100, step=1, label="svicamera")
1042
+ with gr.Group():
1043
+ gr.Markdown("<div style='padding-left:8px'>Low</div>")
1044
+ with gr.Row():
1045
+ ipnc_wamu_l = gr.Slider(0, 200, value=100, step=1, label="wamu")
1046
+ ipnc_dreamly_l = gr.Slider(0, 200, value=100, step=1, label="dreamly")
1047
+ ipnc_svicamera_l = gr.Slider(0, 200, value=100, step=1, label="svicamera")
1048
+
1049
+ loras_enabled.change(
1050
+ fn=lambda x: gr.update(visible=x),
1051
+ inputs=loras_enabled,
1052
+ outputs=loras_section,
1053
+ )
1054
+
1055
+ ipnc_enabled.change(
1056
+ fn=lambda x: gr.update(visible=x),
1057
+ inputs=ipnc_enabled,
1058
+ outputs=ipnc_section,
1059
+ )
1060
+
1061
+ with gr.Row():
1062
+ seed = gr.Number(value=0, precision=0, label="Seed (0=random)")
1063
+ gpu_budget = gr.Slider(0, 540, value=0, step=10, label="ZeroGPU budget (0=auto)")
1064
+ with gr.Row():
1065
+ num_steps = gr.Slider(4, 20, value=6, step=1, label="Steps")
1066
+ duration_secs = gr.Slider(1, 15, value=5, step=0.5, label="Duration (s)")
1067
+ sampler_name = gr.Dropdown(choices=["uni_pc", "lcm"], value="lcm", label="Sampler")
1068
+ base_fps = gr.Number(value=15, precision=0, label="Combine FPS")
1069
+ rife_mode = gr.Dropdown(
1070
+ choices=["no rife", "2x rife", "4x rife"],
1071
+ value="no rife",
1072
+ label="RIFE interpolation",
1073
+ )
1074
+
1075
+ enhance_prompt = gr.Checkbox(label="enhance prompt", value=False)
1076
+ generate_btn = gr.Button("Generate", variant="primary", size="lg")
1077
+
1078
+ with gr.Column(scale=1):
1079
+ output_video = gr.Video(label="Generated video")
1080
+ output_status = gr.Textbox(label="Status", interactive=False)
1081
+
1082
+ generate_btn.click(
1083
+ fn=generate_handler,
1084
+ inputs=[
1085
+ prompt, negative, image_input, seed, aspect_ratio, use_ref_aspect, gpu_budget,
1086
+ num_steps, duration_secs, sampler_name, base_fps, rife_mode,
1087
+ loras_enabled,
1088
+ s_wamu_h, s_dreamly_h,
1089
+ s_wamu_l, s_dreamly_l,
1090
+ enhance_prompt,
1091
+ ipnc_enabled,
1092
+ ipnc_wamu_h, ipnc_dreamly_h,
1093
+ ipnc_wamu_l, ipnc_dreamly_l,
1094
+ s_svicamera_h, s_svicamera_l,
1095
+ ipnc_svicamera_h, ipnc_svicamera_l,
1096
+ ],
1097
+ outputs=[output_video, output_status],
1098
+ )
1099
+
1100
+ if __name__ == "__main__":
1101
+ _ensure_comfy()
1102
+ _ensure_models()
1103
+ _init_comfy_nodes()
1104
+ demo.queue().launch()
bernini_r2v_base.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"id": "ec7da562-7e21-4dac-a0d2-f4441e1efd3b", "revision": 0, "last_node_id": 137, "last_link_id": 250, "nodes": [{"id": 70, "type": "CFGZeroStar", "pos": [91.64471435546875, -914.7239379882812], "size": [265.08551025390625, 26], "flags": {}, "order": 43, "mode": 0, "inputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "link": 223}], "outputs": [{"label": "patched_model", "localized_name": "patched_model", "name": "patched_model", "type": "MODEL", "links": [155]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.48", "Node name for S&R": "CFGZeroStar", "widget_ue_connectable": {}}, "widgets_values": []}, {"id": 75, "type": "SetNode", "pos": [99.88265991210938, -827.1892700195312], "size": [254.6003875732422, 61.11500549316406], "flags": {}, "order": 51, "mode": 0, "inputs": [{"label": "MODEL", "name": "MODEL", "type": "MODEL", "link": 155}], "outputs": [{"label": "*", "name": "*", "type": "*"}], "title": "Set_high_model", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "high_model", "widget_ue_connectable": {}}, "widgets_values": ["high_model"], "color": "#223", "bgcolor": "#335"}, {"id": 38, "type": "CLIPLoader", "pos": [-366.0155944824219, -378.3727111816406], "size": [346.391845703125, 106], "flags": {}, "order": 0, "mode": 0, "inputs": [{"label": "clip_name", "localized_name": "clip_name", "name": "clip_name", "type": "COMBO", "widget": {"name": "clip_name"}}, {"label": "type", "localized_name": "type", "name": "type", "type": "COMBO", "widget": {"name": "type"}}, {"label": "device", "localized_name": "device", "name": "device", "shape": 7, "type": "COMBO", "widget": {"name": "device"}}], "outputs": [{"label": "CLIP", "localized_name": "CLIP", "name": "CLIP", "type": "CLIP", "slot_index": 0, "links": [156]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "CLIPLoader", "models": [{"directory_invalid": true, "name": "umt5_xxl_fp8_e4m3fn_scaled.safetensors", "directory": "text_encoders", "url": "https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/text_encoders/umt5_xxl_fp8_e4m3fn_scaled.safetensors"}], "widget_ue_connectable": {}}, "widgets_values": ["umt5_xxl_fp8_e4m3fn_scaled.safetensors", "wan", "default"]}, {"id": 83, "type": "GetNode", "pos": [457.47674560546875, -280.5387878417969], "size": [210, 60], "flags": {}, "order": 1, "mode": 0, "inputs": [], "outputs": [{"label": "MODEL", "name": "MODEL", "type": "MODEL", "links": [163]}], "title": "Get_high_model", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["high_model"], "color": "#223", "bgcolor": "#335"}, {"id": 78, "type": "SetNode", "pos": [98.8753890991211, -195.62353515625], "size": [268.01397705078125, 58], "flags": {}, "order": 29, "mode": 0, "inputs": [{"label": "VAE", "name": "VAE", "type": "VAE", "link": 157}], "outputs": [{"label": "*", "name": "*", "type": "*"}], "title": "Set_vae", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "vae", "widget_ue_connectable": {}}, "widgets_values": ["vae"], "color": "#322", "bgcolor": "#533"}, {"id": 77, "type": "SetNode", "pos": [105.33979034423828, -374.97235107421875], "size": [263.9664611816406, 67.4441909790039], "flags": {}, "order": 25, "mode": 0, "inputs": [{"label": "CLIP", "name": "CLIP", "type": "CLIP", "link": 156}], "outputs": [{"label": "*", "name": "*", "type": "*"}], "title": "Set_clip", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "clip", "widget_ue_connectable": {}}, "widgets_values": ["clip"], "color": "#432", "bgcolor": "#653"}, {"id": 8, "type": "VAEDecode", "pos": [1972.1580810546875, -266.72650146484375], "size": [210, 46], "flags": {}, "order": 55, "mode": 0, "inputs": [{"label": "samples", "localized_name": "samples", "name": "samples", "type": "LATENT", "link": 124}, {"label": "vae", "localized_name": "vae", "name": "vae", "type": "VAE", "link": 160}], "outputs": [{"label": "IMAGE", "localized_name": "IMAGE", "name": "IMAGE", "type": "IMAGE", "slot_index": 0, "links": [182]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "VAEDecode", "widget_ue_connectable": {}}, "widgets_values": []}, {"id": 100, "type": "GetNode", "pos": [1225.3629150390625, -931.2969360351562], "size": [210, 60], "flags": {}, "order": 2, "mode": 0, "inputs": [], "outputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "links": [232]}], "title": "Get_con+", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["con+"], "color": "#332922", "bgcolor": "#593930"}, {"id": 101, "type": "GetNode", "pos": [1226.2900390625, -828.277099609375], "size": [210, 58], "flags": {}, "order": 3, "mode": 0, "inputs": [], "outputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "links": [233]}], "title": "Get_con-", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["con-"], "color": "#332922", "bgcolor": "#593930"}, {"id": 84, "type": "GetNode", "pos": [460.0235290527344, -173.7384490966797], "size": [210, 58], "flags": {}, "order": 4, "mode": 0, "inputs": [], "outputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "links": [164, 168, 170]}], "title": "Get_con1-", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["con1-"], "color": "#332922", "bgcolor": "#593930"}, {"id": 80, "type": "GetNode", "pos": [467.8817138671875, 44.29520797729492], "size": [210, 58], "flags": {}, "order": 5, "mode": 0, "inputs": [], "outputs": [{"label": "VAE", "name": "VAE", "type": "VAE", "links": [160]}], "title": "Get_vae", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["vae"], "color": "#322", "bgcolor": "#533"}, {"id": 109, "type": "SetNode", "pos": [102.7603530883789, -91.38772583007812], "size": [210, 58], "flags": {}, "order": 30, "mode": 0, "inputs": [{"label": "CLIP_VISION", "name": "CLIP_VISION", "type": "CLIP_VISION", "link": 196}], "outputs": [{"label": "*", "name": "*", "type": "*"}], "title": "Set_clip_h", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "clip_h", "widget_ue_connectable": {}}, "widgets_values": ["clip_h"]}, {"id": 102, "type": "GetNode", "pos": [1224.45263671875, -730.7865600585938], "size": [210, 58], "flags": {}, "order": 6, "mode": 0, "inputs": [], "outputs": [{"label": "VAE", "name": "VAE", "type": "VAE", "links": [234]}], "title": "Get_vae", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["vae"], "color": "#322", "bgcolor": "#533"}, {"id": 79, "type": "GetNode", "pos": [466.0031433105469, -903.6583251953125], "size": [210, 60], "flags": {"collapsed": true}, "order": 7, "mode": 0, "inputs": [], "outputs": [{"label": "CLIP", "name": "CLIP", "type": "CLIP", "links": [158, 159]}], "title": "Get_clip", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["clip"], "color": "#432", "bgcolor": "#653"}, {"id": 82, "type": "SetNode", "pos": [724.476318359375, -467.92950439453125], "size": [210, 58], "flags": {}, "order": 42, "mode": 0, "inputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "link": 162}], "outputs": [{"label": "*", "name": "*", "type": "*"}], "title": "Set_con-", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "con-", "widget_ue_connectable": {}}, "widgets_values": ["con-"], "color": "#332922", "bgcolor": "#593930"}, {"id": 81, "type": "SetNode", "pos": [948.0673217773438, -463.03466796875], "size": [210, 60], "flags": {}, "order": 41, "mode": 0, "inputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "link": 161}], "outputs": [{"label": "*", "name": "*", "type": "*"}], "title": "Set_con+", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "con+", "widget_ue_connectable": {}}, "widgets_values": ["con+"], "color": "#332922", "bgcolor": "#593930"}, {"id": 7, "type": "CLIPTextEncode", "pos": [715.5911254882812, -705.5069580078125], "size": [425.27801513671875, 180.6060791015625], "flags": {}, "order": 28, "mode": 0, "inputs": [{"label": "clip", "localized_name": "clip", "name": "clip", "type": "CLIP", "link": 159}, {"label": "text", "localized_name": "text", "name": "text", "type": "STRING", "widget": {"name": "text"}}], "outputs": [{"label": "CONDITIONING", "localized_name": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "slot_index": 0, "links": [162]}], "title": "CLIP Text Encode (Negative Prompt)", "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "CLIPTextEncode", "widget_ue_connectable": {}}, "widgets_values": ["placeholder prompt"], "color": "#322", "bgcolor": "#533"}, {"id": 39, "type": "VAELoader", "pos": [-365.962158203125, -219.44821166992188], "size": [344.731689453125, 59.98149108886719], "flags": {}, "order": 8, "mode": 0, "inputs": [{"label": "vae_name", "localized_name": "vae_name", "name": "vae_name", "type": "COMBO", "widget": {"name": "vae_name"}}], "outputs": [{"label": "VAE", "localized_name": "VAE", "name": "VAE", "type": "VAE", "slot_index": 0, "links": [157]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "VAELoader", "models": [{"name": "wan_2.1_vae.safetensors", "directory": "vae", "url": "https://huggingface.co/Comfy-Org/Wan_2.2_ComfyUI_Repackaged/resolve/main/split_files/vae/wan_2.1_vae.safetensors"}], "widget_ue_connectable": {}}, "widgets_values": ["wan_2.1_vae.safetensors"]}, {"id": 108, "type": "CLIPVisionLoader", "pos": [-330.003662109375, -99.01641845703125], "size": [300.462646484375, 58], "flags": {}, "order": 9, "mode": 0, "inputs": [{"label": "clip_name", "localized_name": "clip_name", "name": "clip_name", "type": "COMBO", "widget": {"name": "clip_name"}}], "outputs": [{"label": "CLIP_VISION", "localized_name": "CLIP_VISION", "name": "CLIP_VISION", "type": "CLIP_VISION", "links": [196]}], "properties": {"cnr_id": "comfy-core", "ver": "0.22.2", "Node name for S&R": "CLIPVisionLoader", "widget_ue_connectable": {}}, "widgets_values": ["clip_vision_h.safetensors"]}, {"id": 55, "type": "ModelSamplingSD3", "pos": [1034.045654296875, -126.17032623291016], "size": [249.24838256835938, 60.89899444580078], "flags": {}, "order": 33, "mode": 0, "inputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "link": 166}, {"label": "shift", "localized_name": "shift", "name": "shift", "type": "FLOAT", "widget": {"name": "shift"}}], "outputs": [{"label": "MODEL", "localized_name": "MODEL", "name": "MODEL", "type": "MODEL", "slot_index": 0, "links": [123]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "ModelSamplingSD3", "widget_ue_connectable": {}}, "widgets_values": [8]}, {"id": 54, "type": "ModelSamplingSD3", "pos": [1022.064208984375, -292.55487060546875], "size": [248.53526306152344, 75.91676330566406], "flags": {}, "order": 40, "mode": 0, "inputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "link": 165}, {"label": "shift", "localized_name": "shift", "name": "shift", "type": "FLOAT", "widget": {"name": "shift"}}], "outputs": [{"label": "MODEL", "localized_name": "MODEL", "name": "MODEL", "type": "MODEL", "slot_index": 0, "links": [125]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "ModelSamplingSD3", "widget_ue_connectable": {}}, "widgets_values": [8.000000000000002]}, {"id": 57, "type": "KSamplerAdvanced", "pos": [1307.48974609375, -283.14453125], "size": [315.8980407714844, 362.9902648925781], "flags": {}, "order": 50, "mode": 0, "inputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "link": 125}, {"label": "positive", "localized_name": "positive", "name": "positive", "type": "CONDITIONING", "link": 167}, {"label": "negative", "localized_name": "negative", "name": "negative", "type": "CONDITIONING", "link": 168}, {"label": "latent_image", "localized_name": "latent_image", "name": "latent_image", "type": "LATENT", "link": 195}, {"label": "add_noise", "localized_name": "add_noise", "name": "add_noise", "type": "COMBO", "widget": {"name": "add_noise"}}, {"label": "noise_seed", "localized_name": "noise_seed", "name": "noise_seed", "type": "INT", "widget": {"name": "noise_seed"}}, {"label": "steps", "localized_name": "steps", "name": "steps", "type": "INT", "widget": {"name": "steps"}}, {"label": "cfg", "localized_name": "cfg", "name": "cfg", "type": "FLOAT", "widget": {"name": "cfg"}}, {"label": "sampler_name", "localized_name": "sampler_name", "name": "sampler_name", "type": "COMBO", "widget": {"name": "sampler_name"}}, {"label": "scheduler", "localized_name": "scheduler", "name": "scheduler", "type": "COMBO", "widget": {"name": "scheduler"}}, {"label": "start_at_step", "localized_name": "start_at_step", "name": "start_at_step", "type": "INT", "widget": {"name": "start_at_step"}}, {"label": "end_at_step", "localized_name": "end_at_step", "name": "end_at_step", "type": "INT", "widget": {"name": "end_at_step"}}, {"label": "return_with_leftover_noise", "localized_name": "return_with_leftover_noise", "name": "return_with_leftover_noise", "type": "COMBO", "widget": {"name": "return_with_leftover_noise"}}], "outputs": [{"label": "LATENT", "localized_name": "LATENT", "name": "LATENT", "type": "LATENT", "links": [113]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "KSamplerAdvanced", "widget_ue_connectable": {}}, "widgets_values": ["enable", 821316597305245, "randomize", 6, 1, "uni_pc", "simple", 0, 3, "enable"]}, {"id": 71, "type": "UNETLoader", "pos": [-369.1159362792969, -923.2352905273438], "size": [445.2359619140625, 82], "flags": {}, "order": 10, "mode": 0, "inputs": [{"label": "unet_name", "localized_name": "unet_name", "name": "unet_name", "type": "COMBO", "widget": {"name": "unet_name"}}, {"label": "weight_dtype", "localized_name": "weight_dtype", "name": "weight_dtype", "type": "COMBO", "widget": {"name": "weight_dtype"}}], "outputs": [{"label": "MODEL", "localized_name": "MODEL", "name": "MODEL", "type": "MODEL", "slot_index": 0, "links": [146]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "UNETLoader", "models": [{"name": "wan2.2_t2v_low_noise_14B_fp8_scaled.safetensors", "directory": "diffusion_models", "url": "https://huggingface.co/Comfy-Org/Wan_2.2_ComfyUI_Repackaged/resolve/main/split_files/diffusion_models/wan2.2_t2v_low_noise_14B_fp8_scaled.safetensors"}], "widget_ue_connectable": {}}, "widgets_values": ["Wan22_Bernini_HIGH_fp8_e4m3fn_scaled.safetensors", "fp8_e4m3fn_fast"]}, {"id": 56, "type": "UNETLoader", "pos": [-364.36297607421875, -652.0966796875], "size": [396.564453125, 82], "flags": {}, "order": 11, "mode": 0, "inputs": [{"label": "unet_name", "localized_name": "unet_name", "name": "unet_name", "type": "COMBO", "widget": {"name": "unet_name"}}, {"label": "weight_dtype", "localized_name": "weight_dtype", "name": "weight_dtype", "type": "COMBO", "widget": {"name": "weight_dtype"}}], "outputs": [{"label": "MODEL", "localized_name": "MODEL", "name": "MODEL", "type": "MODEL", "slot_index": 0, "links": [135]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "UNETLoader", "models": [{"name": "wan2.2_t2v_low_noise_14B_fp8_scaled.safetensors", "directory": "diffusion_models", "url": "https://huggingface.co/Comfy-Org/Wan_2.2_ComfyUI_Repackaged/resolve/main/split_files/diffusion_models/wan2.2_t2v_low_noise_14B_fp8_scaled.safetensors"}], "widget_ue_connectable": {}}, "widgets_values": ["Wan22_Bernini_LOW_fp8_e4m3fn_scaled.safetensors", "fp8_e4m3fn_fast"]}, {"id": 63, "type": "LoraLoaderModelOnly", "pos": [-351.3344421386719, -794.1530151367188], "size": [387.144775390625, 82], "flags": {}, "order": 31, "mode": 0, "inputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "link": 146}, {"label": "lora_name", "localized_name": "lora_name", "name": "lora_name", "type": "COMBO", "widget": {"name": "lora_name"}}, {"label": "strength_model", "localized_name": "strength_model", "name": "strength_model", "type": "FLOAT", "widget": {"name": "strength_model"}}], "outputs": [{"label": "MODEL", "localized_name": "MODEL", "name": "MODEL", "type": "MODEL", "links": [223]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.48", "Node name for S&R": "LoraLoaderModelOnly", "widget_ue_connectable": {}}, "widgets_values": ["lightx2v_T2V_14B_cfg_step_distill_v2_lora_rank64_bf16.safetensors", 3.0000000000000004]}, {"id": 64, "type": "LoraLoaderModelOnly", "pos": [-368.6878967285156, -509.2392883300781], "size": [210, 82], "flags": {}, "order": 32, "mode": 0, "inputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "link": 135}, {"label": "lora_name", "localized_name": "lora_name", "name": "lora_name", "type": "COMBO", "widget": {"name": "lora_name"}}, {"label": "strength_model", "localized_name": "strength_model", "name": "strength_model", "type": "FLOAT", "widget": {"name": "strength_model"}}], "outputs": [{"label": "MODEL", "localized_name": "MODEL", "name": "MODEL", "type": "MODEL", "links": [224]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.48", "Node name for S&R": "LoraLoaderModelOnly", "widget_ue_connectable": {}}, "widgets_values": ["lightx2v_T2V_14B_cfg_step_distill_v2_lora_rank64_bf16.safetensors", 1.5000000000000002]}, {"id": 68, "type": "PathchSageAttentionKJ", "pos": [89.24598693847656, -712.0321044921875], "size": [270, 82], "flags": {}, "order": 44, "mode": 0, "inputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "link": 224}, {"label": "sage_attention", "localized_name": "sage_attention", "name": "sage_attention", "type": "COMBO", "widget": {"name": "sage_attention"}}, {"label": "allow_compile", "localized_name": "allow_compile", "name": "allow_compile", "shape": 7, "type": "BOOLEAN", "widget": {"name": "allow_compile"}}], "outputs": [{"label": "MODEL", "localized_name": "MODEL", "name": "MODEL", "type": "MODEL", "links": [153]}], "properties": {"cnr_id": "comfyui-kjnodes", "ver": "a6b867b63a29ca48ddb15c589e17a9f2d8530d57", "Node name for S&R": "PathchSageAttentionKJ", "widget_ue_connectable": {}}, "widgets_values": ["auto", false]}, {"id": 76, "type": "SetNode", "pos": [92.06655883789062, -580.8369140625], "size": [266.865478515625, 64.69011688232422], "flags": {}, "order": 52, "mode": 0, "inputs": [{"label": "MODEL", "name": "MODEL", "type": "MODEL", "link": 153}], "outputs": [{"label": "*", "name": "*", "type": "*"}], "title": "Set_lowmodel", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "lowmodel", "widget_ue_connectable": {}}, "widgets_values": ["lowmodel"], "color": "#223", "bgcolor": "#335"}, {"id": 58, "type": "KSamplerAdvanced", "pos": [1642.402587890625, -284.73388671875], "size": [301.8984375, 367.3834228515625], "flags": {}, "order": 54, "mode": 0, "inputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "link": 123}, {"label": "positive", "localized_name": "positive", "name": "positive", "type": "CONDITIONING", "link": 169}, {"label": "negative", "localized_name": "negative", "name": "negative", "type": "CONDITIONING", "link": 170}, {"label": "latent_image", "localized_name": "latent_image", "name": "latent_image", "type": "LATENT", "link": 113}, {"label": "add_noise", "localized_name": "add_noise", "name": "add_noise", "type": "COMBO", "widget": {"name": "add_noise"}}, {"label": "noise_seed", "localized_name": "noise_seed", "name": "noise_seed", "type": "INT", "widget": {"name": "noise_seed"}}, {"label": "steps", "localized_name": "steps", "name": "steps", "type": "INT", "widget": {"name": "steps"}}, {"label": "cfg", "localized_name": "cfg", "name": "cfg", "type": "FLOAT", "widget": {"name": "cfg"}}, {"label": "sampler_name", "localized_name": "sampler_name", "name": "sampler_name", "type": "COMBO", "widget": {"name": "sampler_name"}}, {"label": "scheduler", "localized_name": "scheduler", "name": "scheduler", "type": "COMBO", "widget": {"name": "scheduler"}}, {"label": "start_at_step", "localized_name": "start_at_step", "name": "start_at_step", "type": "INT", "widget": {"name": "start_at_step"}}, {"label": "end_at_step", "localized_name": "end_at_step", "name": "end_at_step", "type": "INT", "widget": {"name": "end_at_step"}}, {"label": "return_with_leftover_noise", "localized_name": "return_with_leftover_noise", "name": "return_with_leftover_noise", "type": "COMBO", "widget": {"name": "return_with_leftover_noise"}}], "outputs": [{"label": "LATENT", "localized_name": "LATENT", "name": "LATENT", "type": "LATENT", "links": [124]}], "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "KSamplerAdvanced", "widget_ue_connectable": {}}, "widgets_values": ["disable", 0, "fixed", 6, 1, "uni_pc", "simple", 3, 10000, "disable"]}, {"id": 69, "type": "WanVideoNAG", "pos": [735.56396484375, -263.28887939453125], "size": [315.380615234375, 160.342529296875], "flags": {"collapsed": true}, "order": 26, "mode": 0, "inputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "link": 163}, {"label": "conditioning", "localized_name": "conditioning", "name": "conditioning", "type": "CONDITIONING", "link": 164}, {"label": "nag_scale", "localized_name": "nag_scale", "name": "nag_scale", "type": "FLOAT", "widget": {"name": "nag_scale"}}, {"label": "nag_alpha", "localized_name": "nag_alpha", "name": "nag_alpha", "type": "FLOAT", "widget": {"name": "nag_alpha"}}, {"label": "nag_tau", "localized_name": "nag_tau", "name": "nag_tau", "type": "FLOAT", "widget": {"name": "nag_tau"}}, {"label": "input_type", "localized_name": "input_type", "name": "input_type", "shape": 7, "type": "COMBO", "widget": {"name": "input_type"}}, {"label": "inplace", "localized_name": "inplace", "name": "inplace", "shape": 7, "type": "BOOLEAN", "widget": {"name": "inplace"}}], "outputs": [{"label": "model", "localized_name": "model", "name": "model", "type": "MODEL", "links": [165]}], "properties": {"cnr_id": "comfyui-kjnodes", "ver": "a6b867b63a29ca48ddb15c589e17a9f2d8530d57", "Node name for S&R": "WanVideoNAG", "widget_ue_connectable": {}}, "widgets_values": [11, 0.25, 2.5, "default", false]}, {"id": 113, "type": "SetNode", "pos": [-694.3751831054688, -517.255126953125], "size": [211.458984375, 60], "flags": {}, "order": 37, "mode": 0, "inputs": [{"label": "INT", "name": "INT", "type": "INT", "link": 200}], "outputs": [{"label": "*", "name": "*", "type": "*"}], "title": "Set_width", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "width", "widget_ue_connectable": {}}, "widgets_values": ["width"], "color": "#1b4669", "bgcolor": "#29699c"}, {"id": 115, "type": "SetNode", "pos": [-698.3495483398438, -394.216064453125], "size": [211.458984375, 58], "flags": {}, "order": 38, "mode": 0, "inputs": [{"label": "INT", "name": "INT", "type": "INT", "link": 201}], "outputs": [{"label": "*", "name": "*", "type": "*"}], "title": "Set_height", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "height", "widget_ue_connectable": {}}, "widgets_values": ["height"], "color": "#1b4669", "bgcolor": "#29699c"}, {"id": 129, "type": "SetNode", "pos": [-704.6587524414062, -268.58404541015625], "size": [210, 58], "flags": {}, "order": 35, "mode": 0, "inputs": [{"label": "INT", "name": "INT", "type": "INT", "link": 225}], "outputs": [{"label": "INT", "name": "INT", "type": "INT"}], "title": "Set_frames", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "frames", "widget_ue_connectable": {}}, "widgets_values": ["frames"], "color": "#1b4669", "bgcolor": "#29699c"}, {"id": 130, "type": "ImageResizeKJv2", "pos": [-1000.8086547851562, -158.05226135253906], "size": [270, 336], "flags": {}, "order": 48, "mode": 4, "inputs": [{"label": "image", "localized_name": "image", "name": "image", "type": "IMAGE", "link": 230}, {"label": "mask", "localized_name": "mask", "name": "mask", "shape": 7, "type": "MASK"}, {"label": "width", "localized_name": "width", "name": "width", "type": "INT", "widget": {"name": "width"}, "link": 228}, {"label": "height", "localized_name": "height", "name": "height", "type": "INT", "widget": {"name": "height"}, "link": 229}, {"label": "upscale_method", "localized_name": "upscale_method", "name": "upscale_method", "type": "COMBO", "widget": {"name": "upscale_method"}}, {"label": "keep_proportion", "localized_name": "keep_proportion", "name": "keep_proportion", "type": "COMBO", "widget": {"name": "keep_proportion"}}, {"label": "pad_color", "localized_name": "pad_color", "name": "pad_color", "type": "STRING", "widget": {"name": "pad_color"}}, {"label": "crop_position", "localized_name": "crop_position", "name": "crop_position", "type": "COMBO", "widget": {"name": "crop_position"}}, {"label": "divisible_by", "localized_name": "divisible_by", "name": "divisible_by", "type": "INT", "widget": {"name": "divisible_by"}}, {"label": "device", "localized_name": "device", "name": "device", "shape": 7, "type": "COMBO", "widget": {"name": "device"}}], "outputs": [{"label": "IMAGE", "localized_name": "IMAGE", "name": "IMAGE", "type": "IMAGE", "links": [231]}, {"label": "width", "localized_name": "width", "name": "width", "type": "INT"}, {"label": "height", "localized_name": "height", "name": "height", "type": "INT"}, {"label": "mask", "localized_name": "mask", "name": "mask", "type": "MASK"}], "properties": {"cnr_id": "comfyui-kjnodes", "ver": "450dc91069e28496bbd67bd657f820ef0cb8d5ba", "Node name for S&R": "ImageResizeKJv2", "widget_ue_connectable": {}}, "widgets_values": [832, 480, "nearest-exact", "crop", "0, 0, 0", "center", 2, "cpu"]}, {"id": 131, "type": "SetNode", "pos": [-697.6787719726562, -148.1199493408203], "size": [210, 60], "flags": {}, "order": 53, "mode": 4, "inputs": [{"label": "IMAGE", "name": "IMAGE", "type": "IMAGE", "link": 231}], "outputs": [{"label": "IMAGE", "name": "IMAGE", "type": "IMAGE"}], "title": "Set_raw_video", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "raw_video", "widget_ue_connectable": {}}, "widgets_values": ["raw_video"], "color": "#2a363b", "bgcolor": "#3f5159"}, {"id": 126, "type": "GetNode", "pos": [1474.7115478515625, -594.903564453125], "size": [210, 58], "flags": {}, "order": 12, "mode": 0, "inputs": [], "outputs": [{"label": "INT", "name": "INT", "type": "INT", "links": [238]}], "title": "Get_width", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["width"], "color": "#1b4669", "bgcolor": "#29699c"}, {"id": 134, "type": "GetNode", "pos": [1474.7354736328125, -695.23046875], "size": [210, 58], "flags": {}, "order": 13, "mode": 0, "inputs": [], "outputs": [{"label": "INT", "name": "INT", "type": "INT", "links": [240]}], "title": "Get_frames", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["frames"], "color": "#1b4669", "bgcolor": "#29699c"}, {"id": 125, "type": "GetNode", "pos": [1469.332763671875, -503.66351318359375], "size": [210, 60], "flags": {}, "order": 14, "mode": 0, "inputs": [], "outputs": [{"label": "INT", "name": "INT", "type": "INT", "links": [239]}], "title": "Get_height", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["height"], "color": "#1b4669", "bgcolor": "#29699c"}, {"id": 85, "type": "GetNode", "pos": [722.484619140625, -199.2343292236328], "size": [210, 58], "flags": {}, "order": 15, "mode": 0, "inputs": [], "outputs": [{"label": "MODEL", "name": "MODEL", "type": "MODEL", "links": [166]}], "title": "Get_lowmodel", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["lowmodel"], "color": "#223", "bgcolor": "#335"}, {"id": 107, "type": "GetNode", "pos": [745.3897705078125, -39.66474914550781], "size": [210, 60], "flags": {}, "order": 16, "mode": 0, "inputs": [], "outputs": [{"label": "LATENT", "name": "LATENT", "type": "LATENT", "links": [195]}], "title": "Get_latent", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["latent"], "color": "#323", "bgcolor": "#535"}, {"id": 86, "type": "GetNode", "pos": [461.6580505371094, -67.22147369384766], "size": [210, 58], "flags": {}, "order": 17, "mode": 0, "inputs": [], "outputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "links": [167, 169]}], "title": "Get_con1+", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["con1+"], "color": "#332922", "bgcolor": "#593930"}, {"id": 103, "type": "GetNode", "pos": [1474.5859375, -802.3353881835938], "size": [210, 58], "flags": {}, "order": 18, "mode": 0, "inputs": [], "outputs": [{"label": "IMAGE", "name": "IMAGE", "type": "IMAGE", "links": [250]}], "title": "Get_refimg", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["refimg"], "color": "#2a363b", "bgcolor": "#3f5159"}, {"id": 105, "type": "SetNode", "pos": [2002.2540283203125, -894.3896484375], "size": [223.53515625, 58], "flags": {}, "order": 46, "mode": 0, "inputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "link": 243}], "outputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING"}], "title": "Set_con1-", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "con1-", "widget_ue_connectable": {}}, "widgets_values": ["con1-"], "color": "#332922", "bgcolor": "#593930"}, {"id": 104, "type": "SetNode", "pos": [1998.2420654296875, -793.7587280273438], "size": [223.53515625, 60], "flags": {}, "order": 45, "mode": 0, "inputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "link": 242}], "outputs": [{"label": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING"}], "title": "Set_con1+", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "con1+", "widget_ue_connectable": {}}, "widgets_values": ["con1+"], "color": "#332922", "bgcolor": "#593930"}, {"id": 106, "type": "SetNode", "pos": [2002.9373779296875, -679.3460693359375], "size": [210, 58], "flags": {}, "order": 47, "mode": 0, "inputs": [{"label": "LATENT", "name": "LATENT", "type": "LATENT", "link": 244}], "outputs": [{"label": "LATENT", "name": "LATENT", "type": "LATENT"}], "title": "Set_latent", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "latent", "widget_ue_connectable": {}}, "widgets_values": ["latent"], "color": "#323", "bgcolor": "#535"}, {"id": 97, "type": "SetNode", "pos": [-753.958251953125, -887.3814086914062], "size": [256.62774658203125, 64.0545654296875], "flags": {"collapsed": true}, "order": 49, "mode": 0, "inputs": [{"label": "IMAGE", "name": "IMAGE", "type": "IMAGE", "link": 249}], "outputs": [{"label": "IMAGE", "name": "IMAGE", "type": "IMAGE", "links": []}], "title": "Set_refimg", "properties": {"Node name for S&R": "SetNode", "aux_id": "kijai/ComfyUI-KJNodes", "previousName": "refimg", "widget_ue_connectable": {}}, "widgets_values": ["refimg"], "color": "#2a363b", "bgcolor": "#3f5159"}, {"id": 136, "type": "BatchImagesNode", "pos": [-972.5608520507812, -913.82470703125], "size": [169.482421875, 66], "flags": {}, "order": 39, "mode": 0, "inputs": [{"label": "images.image0", "localized_name": "images.image0", "name": "images.image0", "type": "IMAGE", "link": 247}, {"label": "image1", "localized_name": "images.image1", "name": "images.image1", "shape": 7, "type": "IMAGE"}], "outputs": [{"label": "IMAGE", "localized_name": "IMAGE", "name": "IMAGE", "type": "IMAGE", "links": [249]}], "properties": {"cnr_id": "comfy-core", "ver": "0.22.2", "Node name for S&R": "BatchImagesNode", "widget_ue_connectable": {}}, "widgets_values": []}, {"id": 67, "type": "VHS_VideoCombine", "pos": [2260.427978515625, -992.9591674804688], "size": [1209.7449951171875, 1034.3913433368389], "flags": {}, "order": 56, "mode": 0, "inputs": [{"label": "images", "localized_name": "images", "name": "images", "type": "IMAGE", "link": 182}, {"label": "audio", "localized_name": "audio", "name": "audio", "shape": 7, "type": "AUDIO"}, {"label": "meta_batch", "localized_name": "meta_batch", "name": "meta_batch", "shape": 7, "type": "VHS_BatchManager"}, {"label": "vae", "localized_name": "vae", "name": "vae", "shape": 7, "type": "VAE"}, {"label": "frame_rate", "localized_name": "frame_rate", "name": "frame_rate", "type": "FLOAT", "widget": {"name": "frame_rate"}}, {"label": "loop_count", "localized_name": "loop_count", "name": "loop_count", "type": "INT", "widget": {"name": "loop_count"}}, {"label": "filename_prefix", "localized_name": "filename_prefix", "name": "filename_prefix", "type": "STRING", "widget": {"name": "filename_prefix"}}, {"label": "format", "localized_name": "format", "name": "format", "type": "COMBO", "widget": {"name": "format"}}, {"label": "pingpong", "localized_name": "pingpong", "name": "pingpong", "type": "BOOLEAN", "widget": {"name": "pingpong"}}, {"label": "save_output", "localized_name": "save_output", "name": "save_output", "type": "BOOLEAN", "widget": {"name": "save_output"}}, {"name": "pix_fmt", "type": ["yuv420p", "yuv420p10le"], "widget": {"name": "pix_fmt"}, "link": null}, {"name": "crf", "type": "INT", "widget": {"name": "crf"}, "link": null}, {"name": "save_metadata", "type": "BOOLEAN", "widget": {"name": "save_metadata"}, "link": null}, {"name": "trim_to_audio", "type": "BOOLEAN", "widget": {"name": "trim_to_audio"}, "link": null}], "outputs": [{"label": "Filenames", "localized_name": "Filenames", "name": "Filenames", "type": "VHS_FILENAMES"}], "properties": {"cnr_id": "comfyui-videohelpersuite", "ver": "1.7.2", "Node name for S&R": "VHS_VideoCombine", "widget_ue_connectable": {}}, "widgets_values": {"frame_rate": 24, "loop_count": 0, "filename_prefix": "AnimateDiff", "format": "video/h264-mp4", "pix_fmt": "yuv420p", "crf": 19, "save_metadata": true, "trim_to_audio": false, "pingpong": false, "save_output": true, "videopreview": {"paused": false, "hidden": false, "params": {"score": "0", "filename": "AnimateDiff_00001.mp4", "cos_url": "https://rh-images.xiaoyaoyou.com//445aa9a89d7fa5567450f91c998092da/output/AnimateDiff_00001_p84_dzvns_1780994695.mp4", "workflow": "AnimateDiff_00001.png", "fullpath": "/tmp/comfy-output/AnimateDiff_00001.mp4", "format": "video/h264-mp4", "subfolder": "", "label": "Normal", "type": "output", "frame_rate": 24}}}}, {"id": 128, "type": "INTConstant", "pos": [-993.2201538085938, -268.245849609375], "size": [210, 58], "flags": {}, "order": 19, "mode": 0, "inputs": [{"label": "value", "localized_name": "value", "name": "value", "type": "INT", "widget": {"name": "value"}}], "outputs": [{"label": "value", "localized_name": "value", "name": "value", "type": "INT", "links": [225, 226]}], "properties": {"cnr_id": "comfyui-kjnodes", "ver": "450dc91069e28496bbd67bd657f820ef0cb8d5ba", "Node name for S&R": "INTConstant", "widget_ue_connectable": {}}, "widgets_values": [145], "color": "#1b4669", "bgcolor": "#29699c"}, {"id": 127, "type": "VHS_LoadVideo", "pos": [-1310.0025634765625, -550.9869384765625], "size": [253.279296875, 310], "flags": {}, "order": 36, "mode": 4, "inputs": [{"label": "meta_batch", "localized_name": "meta_batch", "name": "meta_batch", "shape": 7, "type": "VHS_BatchManager"}, {"label": "vae", "localized_name": "vae", "name": "vae", "shape": 7, "type": "VAE"}, {"label": "video", "localized_name": "video", "name": "video", "type": "COMBO", "widget": {"name": "video"}}, {"label": "force_rate", "localized_name": "force_rate", "name": "force_rate", "type": "FLOAT", "widget": {"name": "force_rate"}}, {"label": "custom_width", "localized_name": "custom_width", "name": "custom_width", "type": "INT", "widget": {"name": "custom_width"}}, {"label": "custom_height", "localized_name": "custom_height", "name": "custom_height", "type": "INT", "widget": {"name": "custom_height"}}, {"label": "frame_load_cap", "localized_name": "frame_load_cap", "name": "frame_load_cap", "type": "INT", "widget": {"name": "frame_load_cap"}, "link": 226}, {"label": "skip_first_frames", "localized_name": "skip_first_frames", "name": "skip_first_frames", "type": "INT", "widget": {"name": "skip_first_frames"}}, {"label": "select_every_nth", "localized_name": "select_every_nth", "name": "select_every_nth", "type": "INT", "widget": {"name": "select_every_nth"}}, {"label": "format", "localized_name": "format", "name": "format", "shape": 7, "type": "COMBO", "widget": {"name": "format"}}], "outputs": [{"label": "IMAGE", "localized_name": "IMAGE", "name": "IMAGE", "type": "IMAGE", "links": [230]}, {"label": "frame_count", "localized_name": "frame_count", "name": "frame_count", "type": "INT"}, {"label": "audio", "localized_name": "audio", "name": "audio", "type": "AUDIO"}, {"label": "video_info", "localized_name": "video_info", "name": "video_info", "type": "VHS_VIDEOINFO"}], "properties": {"cnr_id": "comfyui-videohelpersuite", "ver": "4ee72c065db22c9d96c2427954dc69e7b908444b", "Node name for S&R": "VHS_LoadVideo", "widget_ue_connectable": {}}, "widgets_values": {"video": "fb194d12c7500d6f788d360cc1ad6e7302a4cc293b600763cf7cb170a1053e21.mp4", "force_rate": 0, "custom_width": 0, "custom_height": 0, "frame_load_cap": 0, "skip_first_frames": 0, "select_every_nth": 1, "format": "Wan", "videopreview": {"paused": false, "hidden": false, "params": {"custom_height": 0, "force_rate": 0, "filename": "fb194d12c7500d6f788d360cc1ad6e7302a4cc293b600763cf7cb170a1053e21.mp4", "custom_width": 0, "select_every_nth": 1, "frame_load_cap": 0, "format": "video/mp4", "skip_first_frames": 0, "type": "input"}}}}, {"id": 112, "type": "INTConstant", "pos": [-998.2303466796875, -514.6437377929688], "size": [210, 58], "flags": {}, "order": 20, "mode": 0, "inputs": [{"label": "value", "localized_name": "value", "name": "value", "type": "INT", "widget": {"name": "value"}}], "outputs": [{"label": "value", "localized_name": "value", "name": "value", "type": "INT", "links": [200, 228]}], "properties": {"cnr_id": "comfyui-kjnodes", "ver": "450dc91069e28496bbd67bd657f820ef0cb8d5ba", "Node name for S&R": "INTConstant", "widget_ue_connectable": {}}, "widgets_values": [832], "color": "#1b4669", "bgcolor": "#29699c"}, {"id": 114, "type": "INTConstant", "pos": [-995.2044067382812, -390.86224365234375], "size": [210, 58], "flags": {}, "order": 21, "mode": 0, "inputs": [{"label": "value", "localized_name": "value", "name": "value", "type": "INT", "widget": {"name": "value"}}], "outputs": [{"label": "value", "localized_name": "value", "name": "value", "type": "INT", "links": [201, 229]}], "properties": {"cnr_id": "comfyui-kjnodes", "ver": "450dc91069e28496bbd67bd657f820ef0cb8d5ba", "Node name for S&R": "INTConstant", "widget_ue_connectable": {}}, "widgets_values": [480], "color": "#1b4669", "bgcolor": "#29699c"}, {"id": 133, "type": "GetNode", "pos": [1223.9693603515625, -611.1218872070312], "size": [210, 60], "flags": {}, "order": 22, "mode": 4, "inputs": [], "outputs": [{"label": "IMAGE", "name": "IMAGE", "type": "IMAGE", "links": []}], "title": "Get_raw_video", "properties": {"Node name for S&R": "GetNode", "aux_id": "kijai/ComfyUI-KJNodes", "widget_ue_connectable": {}}, "widgets_values": ["raw_video"], "color": "#2a363b", "bgcolor": "#3f5159"}, {"id": 132, "type": "BerniniConditioning", "pos": [1717.3636474609375, -919.236572265625], "size": [271.8258056640625, 254], "flags": {}, "order": 34, "mode": 0, "inputs": [{"label": "positive", "localized_name": "positive", "name": "positive", "type": "CONDITIONING", "link": 232}, {"label": "negative", "localized_name": "negative", "name": "negative", "type": "CONDITIONING", "link": 233}, {"label": "vae", "localized_name": "vae", "name": "vae", "type": "VAE", "link": 234}, {"label": "source_video", "localized_name": "source_video", "name": "source_video", "shape": 7, "type": "IMAGE"}, {"label": "reference_video", "localized_name": "reference_video", "name": "reference_video", "shape": 7, "type": "IMAGE"}, {"label": "reference_images", "localized_name": "reference_images", "name": "reference_images", "shape": 7, "type": "IMAGE", "link": 250}, {"label": "width", "localized_name": "width", "name": "width", "type": "INT", "widget": {"name": "width"}, "link": 238}, {"label": "height", "localized_name": "height", "name": "height", "type": "INT", "widget": {"name": "height"}, "link": 239}, {"label": "length", "localized_name": "length", "name": "length", "type": "INT", "widget": {"name": "length"}, "link": 240}, {"label": "batch_size", "localized_name": "batch_size", "name": "batch_size", "type": "INT", "widget": {"name": "batch_size"}}, {"label": "ref_max_size", "localized_name": "ref_max_size", "name": "ref_max_size", "shape": 7, "type": "INT", "widget": {"name": "ref_max_size"}}], "outputs": [{"label": "positive", "localized_name": "positive", "name": "positive", "type": "CONDITIONING", "links": [242]}, {"label": "negative", "localized_name": "negative", "name": "negative", "type": "CONDITIONING", "links": [243]}, {"label": "latent", "localized_name": "latent", "name": "latent", "type": "LATENT", "links": [244]}], "properties": {"cnr_id": "comfyui-rh-bernini", "ver": "260603.10.36", "Node name for S&R": "BerniniConditioning", "widget_ue_connectable": {}}, "widgets_values": [480, 832, 145, 1, 848], "color": "#332922", "bgcolor": "#593930"}, {"id": 137, "type": "MarkdownNote", "pos": [-1916.52734375, -921.6448974609375], "size": [477.4400329589844, 395.0406494140625], "flags": {}, "order": 23, "mode": 0, "inputs": [], "outputs": [], "title": "Default prompt prefixes for each trained task", "properties": {"widget_ue_connectable": {}}, "widgets_values": ["| task_type | system prompt (prepended to T5 text) |\n|---|---|\n| `default` | You are a helpful assistant. |\n| `t2i` | You are a helpful assistant specialized in text-to-image generation. |\n| `t2v` | You are a helpful assistant specialized in text-to-video generation. |\n| `i2i` | You are a helpful assistant specialized in image editing. |\n| `r2i` | You are a helpful assistant specialized in subject-to-image generation. |\n| `i2v` | You are a helpful assistant specialized in image-to-video generation. |\n| `v2v` | You are a helpful assistant specialized in video editing. |\n| `r2v` | You are a helpful assistant specialized in subject-to-video generation. |\n| `vi2v` | You are a helpful assistant specialized in video editing on content propagation. |\n| `rv2v` | You are a helpful assistant specialized in video editing with reference. |\n| `ads2v` | You are a helpful assistant specialized in ads insertion. |\n| `vrc2v` | You are a helpful assistant for editing. You may need to adjust the subject's action or position. |\n| `mv2v` | You are a helpful assistant for editing. You might need to adjust the video's style, lighting, colors, textures, and the subject's pose or action. |"], "color": "#432", "bgcolor": "#653"}, {"id": 119, "type": "LoadImage", "pos": [-1328.271728515625, -924.2894287109375], "size": [274.080078125, 314], "flags": {}, "order": 24, "mode": 0, "inputs": [{"label": "image", "localized_name": "image", "name": "image", "type": "COMBO", "widget": {"name": "image"}}, {"label": "upload", "localized_name": "choose file to upload", "name": "upload", "type": "IMAGEUPLOAD", "widget": {"name": "upload"}}], "outputs": [{"label": "IMAGE", "localized_name": "IMAGE", "name": "IMAGE", "type": "IMAGE", "links": [247]}, {"label": "MASK", "localized_name": "MASK", "name": "MASK", "type": "MASK"}], "properties": {"cnr_id": "comfy-core", "ver": "0.22.2", "Node name for S&R": "LoadImage", "widget_ue_connectable": {}}, "widgets_values": ["reference.png", "image"]}, {"id": 6, "type": "CLIPTextEncode", "pos": [712.0286254882812, -915.748046875], "size": [441.5380554199219, 163.74658203125], "flags": {}, "order": 27, "mode": 0, "inputs": [{"label": "clip", "localized_name": "clip", "name": "clip", "type": "CLIP", "link": 158}, {"label": "text", "localized_name": "text", "name": "text", "type": "STRING", "widget": {"name": "text"}}], "outputs": [{"label": "CONDITIONING", "localized_name": "CONDITIONING", "name": "CONDITIONING", "type": "CONDITIONING", "slot_index": 0, "links": [161]}], "title": "CLIP Text Encode (Positive Prompt)", "properties": {"cnr_id": "comfy-core", "ver": "0.3.45", "Node name for S&R": "CLIPTextEncode", "widget_ue_connectable": {}}, "widgets_values": ["placeholder prompt"], "color": "#232", "bgcolor": "#353"}], "links": [[113, 57, 0, 58, 3, "LATENT"], [123, 55, 0, 58, 0, "MODEL"], [124, 58, 0, 8, 0, "LATENT"], [125, 54, 0, 57, 0, "MODEL"], [135, 56, 0, 64, 0, "MODEL"], [146, 71, 0, 63, 0, "MODEL"], [153, 68, 0, 76, 0, "MODEL"], [155, 70, 0, 75, 0, "MODEL"], [156, 38, 0, 77, 0, "*"], [157, 39, 0, 78, 0, "*"], [158, 79, 0, 6, 0, "CLIP"], [159, 79, 0, 7, 0, "CLIP"], [160, 80, 0, 8, 1, "VAE"], [161, 6, 0, 81, 0, "*"], [162, 7, 0, 82, 0, "*"], [163, 83, 0, 69, 0, "MODEL"], [164, 84, 0, 69, 1, "CONDITIONING"], [165, 69, 0, 54, 0, "MODEL"], [166, 85, 0, 55, 0, "MODEL"], [167, 86, 0, 57, 1, "CONDITIONING"], [168, 84, 0, 57, 2, "CONDITIONING"], [169, 86, 0, 58, 1, "CONDITIONING"], [170, 84, 0, 58, 2, "CONDITIONING"], [182, 8, 0, 67, 0, "IMAGE"], [195, 107, 0, 57, 3, "LATENT"], [196, 108, 0, 109, 0, "*"], [200, 112, 0, 113, 0, "*"], [201, 114, 0, 115, 0, "*"], [223, 63, 0, 70, 0, "MODEL"], [224, 64, 0, 68, 0, "MODEL"], [225, 128, 0, 129, 0, "*"], [226, 128, 0, 127, 6, "INT"], [228, 112, 0, 130, 2, "INT"], [229, 114, 0, 130, 3, "INT"], [230, 127, 0, 130, 0, "IMAGE"], [231, 130, 0, 131, 0, "*"], [232, 100, 0, 132, 0, "CONDITIONING"], [233, 101, 0, 132, 1, "CONDITIONING"], [234, 102, 0, 132, 2, "VAE"], [238, 126, 0, 132, 6, "INT"], [239, 125, 0, 132, 7, "INT"], [240, 134, 0, 132, 8, "INT"], [242, 132, 0, 104, 0, "*"], [243, 132, 1, 105, 0, "*"], [244, 132, 2, 106, 0, "*"], [247, 119, 0, 136, 0, "IMAGE"], [249, 136, 0, 97, 0, "*"], [250, 103, 0, 132, 5, "IMAGE"]], "groups": [{"id": 3, "title": "Step3 Prompt", "bounding": [449.6367492675781, -997.9945068359375, 735.690185546875, 600.8460693359375], "color": "#3f789e", "flags": {}}, {"id": 4, "title": "load model", "bounding": [-383.26751708984375, -996.8352661132812, 784.422607421875, 970.070556640625], "color": "#3f789e", "flags": {}}, {"id": 5, "title": "Group", "bounding": [447.47674560546875, -356.31146240234375, 1749.216064453125, 469.1416320800781], "color": "#3f789e", "flags": {}}, {"id": 6, "title": "\u6570\u636e\u5904\u7406", "bounding": [-1017.2520751953125, -996.7771606445312, 598.43017578125, 1222.5125732421875], "color": "#3f789e", "flags": {}}, {"id": 7, "title": "Group", "bounding": [1214.45263671875, -1004.8969116210938, 1013.6437377929688, 625.2843017578125], "color": "#3f789e", "flags": {}}], "config": {}, "extra": {"VHS_KeepIntermediate": true, "links_added_by_ue": [], "VHS_MetadataImage": true, "ue_links": [], "0246.VERSION": [0, 0, 4], "VHS_latentpreviewrate": 0, "frontendVersion": "1.23.4", "VHS_latentpreview": false, "ds": {"scale": 0.3719008264462856, "offset": [-7.688974671843493, 1093.9109658232867]}}, "version": 0.4}
requirements.txt ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch==2.8.0
2
+ torchvision
3
+ diffusers>=0.31.0
4
+ transformers
5
+ accelerate
6
+ safetensors
7
+ einops
8
+ numpy
9
+ Pillow
10
+ tqdm
11
+ ftfy
12
+ ninja
13
+ decord
14
+ imageio
15
+ imageio-ffmpeg
16
+ opencv-python-headless
17
+ spaces
18
+ gradio<7
19
+ huggingface_hub
20
+ openai