Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c8f2abc16 | ||
|
|
c4d1b09a24 | ||
|
|
c70e08a706 | ||
|
|
daf1669e70 | ||
|
|
62df715655 | ||
|
|
04fd08d5ba | ||
|
|
4a8ef7c77c | ||
|
|
5b8dac37fb | ||
|
|
875f7f24d1 | ||
|
|
af0fac7afc |
@@ -7,19 +7,15 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "pyproject.toml"
|
- "pyproject.toml"
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish-node:
|
publish-node:
|
||||||
name: Publish Custom Node to registry
|
name: Publish Custom Node to registry
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.repository_owner == 'BennyKok' }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Publish Custom Node
|
- name: Publish Custom Node
|
||||||
uses: Comfy-Org/publish-node-action@v1
|
uses: Comfy-Org/publish-node-action@main
|
||||||
with:
|
with:
|
||||||
## Add your own personal access token to your Github Repository secrets and reference it here.
|
## Add your own personal access token to your Github Repository secrets and reference it here.
|
||||||
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
|
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
|
||||||
+1
-2
@@ -1,3 +1,2 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
.DS_Store
|
.DS_Store
|
||||||
file-hash-cache.json
|
|
||||||
@@ -2,13 +2,6 @@
|
|||||||
|
|
||||||
Open source comfyui deployment platform, a `vercel` for generative workflow infra. (serverless hosted gpu with vertical intergation with comfyui)
|
Open source comfyui deployment platform, a `vercel` for generative workflow infra. (serverless hosted gpu with vertical intergation with comfyui)
|
||||||
|
|
||||||
Check out our latest lcoal demo -> https://github.com/comfy-deploy/comfyui-api-comfydeploy
|
|
||||||
|
|
||||||
Full backend and frontend is here -> https://github.com/comfy-deploy/comfydeploy
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> Im looking for creative hacker to join ComfyDeploy's core team! DM me on [twitter](https://x.com/BennyKokMusic)
|
|
||||||
|
|
||||||
Join [Discord](https://discord.gg/EEYcQmdYZw) to chat more or visit [Comfy Deploy](https://comfydeploy.com/) to get started!
|
Join [Discord](https://discord.gg/EEYcQmdYZw) to chat more or visit [Comfy Deploy](https://comfydeploy.com/) to get started!
|
||||||
|
|
||||||
Check out our latest [nextjs starter kit](https://github.com/BennyKok/comfyui-deploy-next-example) with Comfy Deploy
|
Check out our latest [nextjs starter kit](https://github.com/BennyKok/comfyui-deploy-next-example) with Comfy Deploy
|
||||||
@@ -100,6 +93,10 @@ Major areas
|
|||||||
|
|
||||||
# Self Hosting with Vercel
|
# Self Hosting with Vercel
|
||||||
|
|
||||||
|
[](https://www.youtube.com/watch?v=hWvsEY1cS2M)
|
||||||
|
Tutorial Created by [Ross](https://github.com/rossman22590) and [Syn](https://github.com/mortlsyn)
|
||||||
|
|
||||||
|
|
||||||
Build command
|
Build command
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
+1
-37
@@ -2,9 +2,8 @@
|
|||||||
@author: BennyKok
|
@author: BennyKok
|
||||||
@title: comfyui-deploy
|
@title: comfyui-deploy
|
||||||
@nickname: Comfy Deploy
|
@nickname: Comfy Deploy
|
||||||
@description:
|
@description:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -18,23 +17,19 @@ import requests
|
|||||||
import folder_paths
|
import folder_paths
|
||||||
from folder_paths import add_model_folder_path, get_filename_list, get_folder_paths
|
from folder_paths import add_model_folder_path, get_filename_list, get_folder_paths
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
import re
|
|
||||||
|
|
||||||
from . import custom_routes
|
from . import custom_routes
|
||||||
# import routes
|
# import routes
|
||||||
|
|
||||||
ag_path = os.path.join(os.path.dirname(__file__))
|
ag_path = os.path.join(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
def get_python_files(path):
|
def get_python_files(path):
|
||||||
return [f[:-3] for f in os.listdir(path) if f.endswith(".py")]
|
return [f[:-3] for f in os.listdir(path) if f.endswith(".py")]
|
||||||
|
|
||||||
|
|
||||||
def append_to_sys_path(path):
|
def append_to_sys_path(path):
|
||||||
if path not in sys.path:
|
if path not in sys.path:
|
||||||
sys.path.append(path)
|
sys.path.append(path)
|
||||||
|
|
||||||
|
|
||||||
paths = ["comfy-nodes"]
|
paths = ["comfy-nodes"]
|
||||||
files = []
|
files = []
|
||||||
|
|
||||||
@@ -46,45 +41,14 @@ for path in paths:
|
|||||||
NODE_CLASS_MAPPINGS = {}
|
NODE_CLASS_MAPPINGS = {}
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {}
|
NODE_DISPLAY_NAME_MAPPINGS = {}
|
||||||
|
|
||||||
|
|
||||||
def split_camel_case(name):
|
|
||||||
# Split on underscores first, then split each part on camelCase
|
|
||||||
parts = []
|
|
||||||
for part in name.split("_"):
|
|
||||||
# Find all camelCase boundaries
|
|
||||||
words = re.findall("[A-Z][^A-Z]*", part)
|
|
||||||
if not words: # If no camelCase found, use the whole part
|
|
||||||
words = [part]
|
|
||||||
parts.extend(words)
|
|
||||||
return parts
|
|
||||||
|
|
||||||
|
|
||||||
# Import all the modules and append their mappings
|
# Import all the modules and append their mappings
|
||||||
for file in files:
|
for file in files:
|
||||||
module = importlib.import_module(file)
|
module = importlib.import_module(file)
|
||||||
|
|
||||||
# Check if the module has explicit mappings
|
|
||||||
if hasattr(module, "NODE_CLASS_MAPPINGS"):
|
if hasattr(module, "NODE_CLASS_MAPPINGS"):
|
||||||
NODE_CLASS_MAPPINGS.update(module.NODE_CLASS_MAPPINGS)
|
NODE_CLASS_MAPPINGS.update(module.NODE_CLASS_MAPPINGS)
|
||||||
if hasattr(module, "NODE_DISPLAY_NAME_MAPPINGS"):
|
if hasattr(module, "NODE_DISPLAY_NAME_MAPPINGS"):
|
||||||
NODE_DISPLAY_NAME_MAPPINGS.update(module.NODE_DISPLAY_NAME_MAPPINGS)
|
NODE_DISPLAY_NAME_MAPPINGS.update(module.NODE_DISPLAY_NAME_MAPPINGS)
|
||||||
|
|
||||||
# Auto-discover classes with ComfyUI node attributes
|
|
||||||
for name, obj in inspect.getmembers(module):
|
|
||||||
# Check if it's a class and has the required ComfyUI node attributes
|
|
||||||
if (
|
|
||||||
inspect.isclass(obj)
|
|
||||||
and hasattr(obj, "INPUT_TYPES")
|
|
||||||
and hasattr(obj, "RETURN_TYPES")
|
|
||||||
):
|
|
||||||
# Use the class name as the key if not already in mappings
|
|
||||||
if name not in NODE_CLASS_MAPPINGS:
|
|
||||||
NODE_CLASS_MAPPINGS[name] = obj
|
|
||||||
# Create a display name by converting camelCase to Title Case with spaces
|
|
||||||
words = split_camel_case(name.replace("ComfyUIDeploy", ""))
|
|
||||||
display_name = " ".join(word.capitalize() for word in words)
|
|
||||||
# print(display_name, name)
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS[name] = display_name
|
|
||||||
|
|
||||||
WEB_DIRECTORY = "web-plugin"
|
WEB_DIRECTORY = "web-plugin"
|
||||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
|
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
import io
|
|
||||||
from folder_paths import get_annotated_filepath
|
|
||||||
|
|
||||||
|
|
||||||
class ComfyUIDeployExternalAudio:
|
|
||||||
RETURN_TYPES = ("AUDIO",)
|
|
||||||
RETURN_NAMES = ("audio",)
|
|
||||||
FUNCTION = "load_audio"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(cls):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"input_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "input_audio"},
|
|
||||||
),
|
|
||||||
"audio_file": ("STRING", {"default": ""}),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"default_value": ("AUDIO",),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def VALIDATE_INPUTS(s, audio_file, **kwargs):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def load_audio(
|
|
||||||
self,
|
|
||||||
input_id,
|
|
||||||
audio_file,
|
|
||||||
default_value=None,
|
|
||||||
display_name=None,
|
|
||||||
description=None,
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
import torchaudio
|
|
||||||
|
|
||||||
if audio_file and audio_file != "":
|
|
||||||
if audio_file.startswith(("http://", "https://")):
|
|
||||||
# Handle URL input
|
|
||||||
try:
|
|
||||||
import requests
|
|
||||||
|
|
||||||
response = requests.get(audio_file)
|
|
||||||
audio_data = io.BytesIO(response.content)
|
|
||||||
waveform, sample_rate = torchaudio.load(audio_data)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error loading audio from URL: {e}")
|
|
||||||
return (default_value,)
|
|
||||||
else:
|
|
||||||
# Handle local file
|
|
||||||
try:
|
|
||||||
audio_path = get_annotated_filepath(audio_file)
|
|
||||||
waveform, sample_rate = torchaudio.load(audio_path)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error loading local audio file: {e}")
|
|
||||||
return (default_value,)
|
|
||||||
|
|
||||||
audio = {"waveform": waveform.unsqueeze(0), "sample_rate": sample_rate}
|
|
||||||
return (audio,)
|
|
||||||
else:
|
|
||||||
return (default_value,)
|
|
||||||
except ImportError as e:
|
|
||||||
print(f"Error: torchaudio not installed or cannot be imported: {e}")
|
|
||||||
return (default_value,)
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalAudio": ComfyUIDeployExternalAudio}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
||||||
"ComfyUIDeployExternalAudio": "External Audio (ComfyUI Deploy)"
|
|
||||||
}
|
|
||||||
@@ -8,26 +8,15 @@ class ComfyUIDeployExternalBoolean:
|
|||||||
{"multiline": False, "default": "input_bool"},
|
{"multiline": False, "default": "input_bool"},
|
||||||
),
|
),
|
||||||
"default_value": ("BOOLEAN", {"default": False})
|
"default_value": ("BOOLEAN", {"default": False})
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("BOOLEAN",)
|
RETURN_TYPES = ("BOOLEAN",)
|
||||||
RETURN_NAMES = ("bool_value",)
|
RETURN_NAMES = ("bool_value",)
|
||||||
|
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, display_name=None, description=None):
|
FUNCTION = "run"
|
||||||
|
|
||||||
|
def run(self, input_id, default_value=None):
|
||||||
print(f"Node '{input_id}' processing with switch set to {default_value}")
|
print(f"Node '{input_id}' processing with switch set to {default_value}")
|
||||||
return [default_value]
|
return [default_value]
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,6 @@ import torch
|
|||||||
import folder_paths
|
import folder_paths
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
class AnyType(str):
|
|
||||||
def __ne__(self, __value: object) -> bool:
|
|
||||||
return False
|
|
||||||
|
|
||||||
WILDCARD = AnyType("*")
|
|
||||||
|
|
||||||
class ComfyUIDeployExternalCheckpoint:
|
class ComfyUIDeployExternalCheckpoint:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
@@ -23,26 +17,17 @@ class ComfyUIDeployExternalCheckpoint:
|
|||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
"default_value": (folder_paths.get_filename_list("checkpoints"), ),
|
"default_value": (folder_paths.get_filename_list("checkpoints"), ),
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = (WILDCARD,)
|
RETURN_TYPES = (folder_paths.get_filename_list("checkpoints"),)
|
||||||
RETURN_NAMES = ("path",)
|
RETURN_NAMES = ("path",)
|
||||||
|
|
||||||
|
|
||||||
FUNCTION = "run"
|
FUNCTION = "run"
|
||||||
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
CATEGORY = "deploy"
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, display_name=None, description=None):
|
def run(self, input_id, default_value=None):
|
||||||
import requests
|
import requests
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
class AnyType(str):
|
|
||||||
def __ne__(self, __value: object) -> bool:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
WILDCARD = AnyType("*")
|
|
||||||
|
|
||||||
class ComfyUIDeployExternalEnum:
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"input_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "input_enum"},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"default_value": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "", "dynamic_enum": True},
|
|
||||||
),
|
|
||||||
"options": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = (WILDCARD,)
|
|
||||||
RETURN_NAMES = ("text",)
|
|
||||||
|
|
||||||
FUNCTION = "run"
|
|
||||||
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(self, input_id, options=None, default_value=None, display_name=None, description=None):
|
|
||||||
return [default_value]
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
import os
|
|
||||||
import io
|
|
||||||
import cv2 as cv
|
|
||||||
import numpy as np
|
|
||||||
import torch
|
|
||||||
import requests
|
|
||||||
from folder_paths import get_annotated_filepath
|
|
||||||
|
|
||||||
class ComfyUIDeployExternalEXR:
|
|
||||||
RETURN_TYPES = ("IMAGE", "MASK")
|
|
||||||
RETURN_NAMES = ("image", "mask")
|
|
||||||
FUNCTION = "load_exr"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(cls):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"input_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "input_exr"},
|
|
||||||
),
|
|
||||||
"exr_file": ("STRING", {"default": ""}),
|
|
||||||
"tonemap": (["linear", "sRGB", "Reinhard"], {"default": "sRGB"}),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"default_image": ("IMAGE",),
|
|
||||||
"default_mask": ("MASK",),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def VALIDATE_INPUTS(s, exr_file, **kwargs):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def sRGBtoLinear(self, npArray):
|
|
||||||
less = npArray <= 0.0404482362771082
|
|
||||||
npArray[less] = npArray[less] / 12.92
|
|
||||||
npArray[~less] = np.power((npArray[~less] + 0.055) / 1.055, 2.4)
|
|
||||||
|
|
||||||
def linearToSRGB(self, npArray):
|
|
||||||
less = npArray <= 0.0031308
|
|
||||||
npArray[less] = npArray[less] * 12.92
|
|
||||||
npArray[~less] = np.power(npArray[~less], 1/2.4) * 1.055 - 0.055
|
|
||||||
|
|
||||||
def load_exr(self, input_id, exr_file, tonemap="sRGB",
|
|
||||||
default_image=None, default_mask=None,
|
|
||||||
display_name=None, description=None):
|
|
||||||
try:
|
|
||||||
if exr_file and exr_file != "":
|
|
||||||
if exr_file.startswith(('http://', 'https://')):
|
|
||||||
# Handle URL input
|
|
||||||
response = requests.get(exr_file)
|
|
||||||
# Write to temp buffer
|
|
||||||
buffer = io.BytesIO(response.content)
|
|
||||||
nparr = np.frombuffer(buffer.getvalue(), np.uint8)
|
|
||||||
image = cv.imdecode(nparr, cv.IMREAD_UNCHANGED).astype(np.float32)
|
|
||||||
else:
|
|
||||||
# Handle local file
|
|
||||||
exr_path = get_annotated_filepath(exr_file)
|
|
||||||
image = cv.imread(exr_path, cv.IMREAD_UNCHANGED).astype(np.float32)
|
|
||||||
|
|
||||||
if len(image.shape) == 2:
|
|
||||||
image = np.repeat(image[..., np.newaxis], 3, axis=2)
|
|
||||||
|
|
||||||
# Extract RGB and flip channels
|
|
||||||
rgb = np.flip(image[:,:,:3], 2).copy()
|
|
||||||
|
|
||||||
# Apply tonemapping
|
|
||||||
if tonemap == "sRGB":
|
|
||||||
self.linearToSRGB(rgb)
|
|
||||||
rgb = np.clip(rgb, 0, 1)
|
|
||||||
elif tonemap == "Reinhard":
|
|
||||||
rgb = np.clip(rgb, 0, None)
|
|
||||||
rgb = rgb / (rgb + 1)
|
|
||||||
self.linearToSRGB(rgb)
|
|
||||||
rgb = np.clip(rgb, 0, 1)
|
|
||||||
|
|
||||||
rgb = torch.unsqueeze(torch.from_numpy(rgb), 0)
|
|
||||||
|
|
||||||
# Handle alpha/mask
|
|
||||||
mask = torch.zeros((1, image.shape[0], image.shape[1]), dtype=torch.float32)
|
|
||||||
if image.shape[2] > 3:
|
|
||||||
mask[0] = torch.from_numpy(np.clip(image[:,:,3], 0, 1))
|
|
||||||
|
|
||||||
return (rgb, mask)
|
|
||||||
else:
|
|
||||||
# Return defaults if no file provided
|
|
||||||
return (default_image, default_mask)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error loading EXR: {str(e)}")
|
|
||||||
# Return defaults on error
|
|
||||||
return (default_image, default_mask)
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
|
||||||
"ComfyUIDeployExternalEXR": ComfyUIDeployExternalEXR
|
|
||||||
}
|
|
||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
||||||
"ComfyUIDeployExternalEXR": "External EXR (ComfyUI Deploy)"
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
from PIL import Image, ImageOps
|
|
||||||
import numpy as np
|
|
||||||
import torch
|
|
||||||
import folder_paths
|
|
||||||
|
|
||||||
|
|
||||||
class AnyType(str):
|
|
||||||
def __ne__(self, __value: object) -> bool:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
WILDCARD = AnyType("*")
|
|
||||||
|
|
||||||
|
|
||||||
class ComfyUIDeployExternalFaceModel:
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"input_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "input_reactor_face_model"},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"default_face_model_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"face_model_save_name": ( # if `default_face_model_name` is a link to download a file, we will attempt to save it with this name
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
"face_model_url": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = (WILDCARD,)
|
|
||||||
RETURN_NAMES = ("path",)
|
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(
|
|
||||||
self,
|
|
||||||
input_id,
|
|
||||||
default_face_model_name=None,
|
|
||||||
face_model_save_name=None,
|
|
||||||
display_name=None,
|
|
||||||
description=None,
|
|
||||||
face_model_url=None,
|
|
||||||
):
|
|
||||||
import requests
|
|
||||||
import os
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
if face_model_url and face_model_url.startswith("http"):
|
|
||||||
if face_model_save_name:
|
|
||||||
existing_face_models = folder_paths.get_filename_list("reactor/faces")
|
|
||||||
# Check if face_model_save_name exists in the list
|
|
||||||
if face_model_save_name in existing_face_models:
|
|
||||||
print(f"using face model: {face_model_save_name}")
|
|
||||||
return (face_model_save_name,)
|
|
||||||
else:
|
|
||||||
face_model_save_name = str(uuid.uuid4()) + ".safetensors"
|
|
||||||
print(face_model_save_name)
|
|
||||||
print(folder_paths.folder_names_and_paths["reactor/faces"][0][0])
|
|
||||||
destination_path = os.path.join(
|
|
||||||
folder_paths.folder_names_and_paths["reactor/faces"][0][0],
|
|
||||||
face_model_save_name,
|
|
||||||
)
|
|
||||||
|
|
||||||
print(destination_path)
|
|
||||||
print(
|
|
||||||
"Downloading external face model - "
|
|
||||||
+ face_model_url
|
|
||||||
+ " to "
|
|
||||||
+ destination_path
|
|
||||||
)
|
|
||||||
response = requests.get(
|
|
||||||
face_model_url,
|
|
||||||
headers={"User-Agent": "Mozilla/5.0"},
|
|
||||||
allow_redirects=True,
|
|
||||||
)
|
|
||||||
with open(destination_path, "wb") as out_file:
|
|
||||||
out_file.write(response.content)
|
|
||||||
return (face_model_save_name,)
|
|
||||||
else:
|
|
||||||
print(f"using face model: {default_face_model_name}")
|
|
||||||
return (default_face_model_name,)
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalFaceModel": ComfyUIDeployExternalFaceModel}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
||||||
"ComfyUIDeployExternalFaceModel": "External Face Model (ComfyUI Deploy)"
|
|
||||||
}
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
import folder_paths
|
|
||||||
|
|
||||||
|
|
||||||
class AnyType(str):
|
|
||||||
def __ne__(self, __value: object) -> bool:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
WILDCARD = AnyType("*")
|
|
||||||
|
|
||||||
|
|
||||||
class ComfyUIDeployExternalFile:
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"input_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "input_file"},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
"file_url": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = (WILDCARD,)
|
|
||||||
RETURN_NAMES = ("path",)
|
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(
|
|
||||||
self,
|
|
||||||
input_id,
|
|
||||||
display_name=None,
|
|
||||||
description=None,
|
|
||||||
file_url=None,
|
|
||||||
):
|
|
||||||
import requests
|
|
||||||
import os
|
|
||||||
import uuid
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
|
|
||||||
if file_url:
|
|
||||||
if file_url.startswith("http"):
|
|
||||||
# Use cache directory for saving files
|
|
||||||
cache_dir = folder_paths.get_temp_directory()
|
|
||||||
if not os.path.exists(cache_dir):
|
|
||||||
os.makedirs(cache_dir)
|
|
||||||
|
|
||||||
# Always generate random filename to avoid conflicts
|
|
||||||
parsed_url = urlparse(file_url)
|
|
||||||
original_filename = os.path.basename(parsed_url.path)
|
|
||||||
|
|
||||||
# Extract file extension from original filename if available
|
|
||||||
file_extension = ""
|
|
||||||
if original_filename and "." in original_filename:
|
|
||||||
file_extension = os.path.splitext(original_filename)[1]
|
|
||||||
else:
|
|
||||||
# Try to determine extension from content-type if no extension found
|
|
||||||
file_extension = ".bin"
|
|
||||||
|
|
||||||
# Generate random filename with preserved extension
|
|
||||||
filename = str(uuid.uuid4()) + file_extension
|
|
||||||
|
|
||||||
destination_path = os.path.join(cache_dir, filename)
|
|
||||||
print(f"Cache directory: {cache_dir}")
|
|
||||||
print(f"Destination path: {destination_path}")
|
|
||||||
print(
|
|
||||||
"Downloading external file - "
|
|
||||||
+ file_url
|
|
||||||
+ " to "
|
|
||||||
+ destination_path
|
|
||||||
)
|
|
||||||
|
|
||||||
headers = {"User-Agent": "Mozilla/5.0"}
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.get(
|
|
||||||
file_url,
|
|
||||||
headers=headers,
|
|
||||||
allow_redirects=True,
|
|
||||||
timeout=30, # Add timeout to prevent hanging
|
|
||||||
)
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
with open(destination_path, "wb") as out_file:
|
|
||||||
out_file.write(response.content)
|
|
||||||
print(f"External file downloaded: {file_url} to {destination_path}")
|
|
||||||
return (destination_path,)
|
|
||||||
|
|
||||||
except requests.exceptions.HTTPError as e:
|
|
||||||
error_msg = f"HTTP Error {e.response.status_code}: {e.response.reason} for URL: {file_url}"
|
|
||||||
print(f"⚠️ Download failed - {error_msg}")
|
|
||||||
if e.response.status_code == 404:
|
|
||||||
print(
|
|
||||||
"💡 This URL might have expired or the file may have been deleted"
|
|
||||||
)
|
|
||||||
# Return empty string instead of crashing
|
|
||||||
return ("",)
|
|
||||||
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
error_msg = (
|
|
||||||
f"Network error downloading file from {file_url}: {str(e)}"
|
|
||||||
)
|
|
||||||
print(f"⚠️ Download failed - {error_msg}")
|
|
||||||
return ("",)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
error_msg = (
|
|
||||||
f"Unexpected error downloading file from {file_url}: {str(e)}"
|
|
||||||
)
|
|
||||||
print(f"⚠️ Download failed - {error_msg}")
|
|
||||||
return ("",)
|
|
||||||
else:
|
|
||||||
print(f"External file loading: {file_url}")
|
|
||||||
return (file_url,)
|
|
||||||
else:
|
|
||||||
print(f"No file URL provided")
|
|
||||||
return ("",)
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalFile": ComfyUIDeployExternalFile}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
||||||
"ComfyUIDeployExternalFile": "External File (ComfyUI Deploy)"
|
|
||||||
}
|
|
||||||
@@ -15,61 +15,42 @@ class ComfyUIDeployExternalImage:
|
|||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
"default_value": ("IMAGE",),
|
"default_value": ("IMAGE",),
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"default_value_url": ("STRING", {"image_preview": True, "default": ""}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE",)
|
RETURN_TYPES = ("IMAGE",)
|
||||||
RETURN_NAMES = ("image",)
|
RETURN_NAMES = ("image",)
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, display_name=None, description=None, default_value_url=None):
|
FUNCTION = "run"
|
||||||
|
|
||||||
|
CATEGORY = "image"
|
||||||
|
|
||||||
|
def run(self, input_id, default_value=None):
|
||||||
image = default_value
|
image = default_value
|
||||||
|
try:
|
||||||
# Try both input_id and default_value_url
|
if input_id.startswith('http'):
|
||||||
urls_to_try = [url for url in [input_id, default_value_url] if url]
|
import requests
|
||||||
|
from io import BytesIO
|
||||||
print(default_value_url)
|
print("Fetching image from url: ", input_id)
|
||||||
|
response = requests.get(input_id)
|
||||||
for url in urls_to_try:
|
image = Image.open(BytesIO(response.content))
|
||||||
try:
|
elif input_id.startswith('data:image/png;base64,') or input_id.startswith('data:image/jpeg;base64,') or input_id.startswith('data:image/jpg;base64,'):
|
||||||
if url.startswith('http'):
|
import base64
|
||||||
import requests
|
from io import BytesIO
|
||||||
from io import BytesIO
|
print("Decoding base64 image")
|
||||||
print(f"Fetching image from url: {url}")
|
base64_image = input_id[input_id.find(",")+1:]
|
||||||
response = requests.get(url)
|
decoded_image = base64.b64decode(base64_image)
|
||||||
image = Image.open(BytesIO(response.content))
|
image = Image.open(BytesIO(decoded_image))
|
||||||
break
|
else:
|
||||||
elif url.startswith(('data:image/png;base64,', 'data:image/jpeg;base64,', 'data:image/jpg;base64,')):
|
raise ValueError("Invalid image url provided.")
|
||||||
import base64
|
|
||||||
from io import BytesIO
|
image = ImageOps.exif_transpose(image)
|
||||||
print("Decoding base64 image")
|
image = image.convert("RGB")
|
||||||
base64_image = url[url.find(",")+1:]
|
image = np.array(image).astype(np.float32) / 255.0
|
||||||
decoded_image = base64.b64decode(base64_image)
|
image = torch.from_numpy(image)[None,]
|
||||||
image = Image.open(BytesIO(decoded_image))
|
return [image]
|
||||||
break
|
except:
|
||||||
except:
|
return [image]
|
||||||
continue
|
|
||||||
|
|
||||||
if image is not None:
|
|
||||||
try:
|
|
||||||
image = ImageOps.exif_transpose(image)
|
|
||||||
image = image.convert("RGB")
|
|
||||||
image = np.array(image).astype(np.float32) / 255.0
|
|
||||||
image = torch.from_numpy(image)[None,]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return [image]
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalImage": ComfyUIDeployExternalImage}
|
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalImage": ComfyUIDeployExternalImage}
|
||||||
|
|||||||
@@ -15,23 +15,17 @@ class ComfyUIDeployExternalImageAlpha:
|
|||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
"default_value": ("IMAGE",),
|
"default_value": ("IMAGE",),
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE",)
|
RETURN_TYPES = ("IMAGE",)
|
||||||
RETURN_NAMES = ("image",)
|
RETURN_NAMES = ("image",)
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, display_name=None, description=None):
|
FUNCTION = "run"
|
||||||
|
|
||||||
|
CATEGORY = "image"
|
||||||
|
|
||||||
|
def run(self, input_id, default_value=None):
|
||||||
image = default_value
|
image = default_value
|
||||||
try:
|
try:
|
||||||
if input_id.startswith('http'):
|
if input_id.startswith('http'):
|
||||||
|
|||||||
@@ -21,50 +21,24 @@ class ComfyUIDeployExternalImageBatch:
|
|||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
"default_value": ("IMAGE",),
|
"default_value": ("IMAGE",),
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE",)
|
RETURN_TYPES = ("IMAGE",)
|
||||||
RETURN_NAMES = ("image",)
|
RETURN_NAMES = ("image",)
|
||||||
|
|
||||||
FUNCTION = "run"
|
FUNCTION = "run"
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
CATEGORY = "image"
|
||||||
|
|
||||||
def process_image(self, image):
|
def run(self, input_id, images=None, default_value=None):
|
||||||
image = ImageOps.exif_transpose(image)
|
|
||||||
image = image.convert("RGB")
|
|
||||||
image = np.array(image).astype(np.float32) / 255.0
|
|
||||||
image_tensor = torch.from_numpy(image)[None,]
|
|
||||||
return image_tensor
|
|
||||||
|
|
||||||
def run(self, input_id, images=None, default_value=None, display_name=None, description=None):
|
|
||||||
import requests
|
|
||||||
import zipfile
|
|
||||||
import io
|
|
||||||
|
|
||||||
processed_images = []
|
processed_images = []
|
||||||
try:
|
try:
|
||||||
images_list = json.loads(images) # Assuming images is a JSON array string
|
images_list = json.loads(images) # Assuming images is a JSON array string
|
||||||
print(images_list)
|
print(images_list)
|
||||||
for img_input in images_list:
|
for img_input in images_list:
|
||||||
if img_input.startswith('http') and img_input.endswith('.zip'):
|
if img_input.startswith('http'):
|
||||||
print("Fetching zip file from url: ", img_input)
|
import requests
|
||||||
response = requests.get(img_input)
|
|
||||||
zip_file = zipfile.ZipFile(io.BytesIO(response.content))
|
|
||||||
for file_name in zip_file.namelist():
|
|
||||||
if file_name.lower().endswith(('.png', '.jpg', '.jpeg')):
|
|
||||||
with zip_file.open(file_name) as file:
|
|
||||||
image = Image.open(file)
|
|
||||||
image = self.process_image(image)
|
|
||||||
processed_images.append(image)
|
|
||||||
elif img_input.startswith('http'):
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
print("Fetching image from url: ", img_input)
|
print("Fetching image from url: ", img_input)
|
||||||
response = requests.get(img_input)
|
response = requests.get(img_input)
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
import folder_paths
|
import folder_paths
|
||||||
|
from PIL import Image, ImageOps
|
||||||
|
import numpy as np
|
||||||
class AnyType(str):
|
import torch
|
||||||
def __ne__(self, __value: object) -> bool:
|
import folder_paths
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
WILDCARD = AnyType("*")
|
|
||||||
|
|
||||||
|
|
||||||
class ComfyUIDeployExternalLora:
|
class ComfyUIDeployExternalLora:
|
||||||
@@ -21,88 +17,40 @@ class ComfyUIDeployExternalLora:
|
|||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
"default_lora_name": (folder_paths.get_filename_list("loras"),),
|
"default_lora_name": (folder_paths.get_filename_list("loras"),),
|
||||||
"lora_save_name": ( # if `default_lora_name` is a link to download a file, we will attempt to save it with this name
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
"lora_url": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"bearer_token": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = (WILDCARD,)
|
RETURN_TYPES = (folder_paths.get_filename_list("loras"),)
|
||||||
RETURN_NAMES = ("path",)
|
RETURN_NAMES = ("path",)
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(
|
FUNCTION = "run"
|
||||||
self,
|
|
||||||
input_id,
|
CATEGORY = "deploy"
|
||||||
default_lora_name=None,
|
|
||||||
lora_save_name=None,
|
def run(self, input_id, default_lora_name=None):
|
||||||
display_name=None,
|
|
||||||
description=None,
|
|
||||||
lora_url=None,
|
|
||||||
bearer_token=None,
|
|
||||||
):
|
|
||||||
import requests
|
import requests
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
if lora_url:
|
if default_lora_name.startswith("http"):
|
||||||
if lora_url.startswith("http"):
|
unique_filename = str(uuid.uuid4()) + ".safetensors"
|
||||||
if lora_save_name:
|
print(unique_filename)
|
||||||
existing_loras = folder_paths.get_filename_list("loras")
|
print(folder_paths.folder_names_and_paths["loras"][0][0])
|
||||||
# Check if lora_save_name exists in the list
|
destination_path = os.path.join(
|
||||||
if lora_save_name in existing_loras:
|
folder_paths.folder_names_and_paths["loras"][0][0], unique_filename
|
||||||
print(f"using lora: {lora_save_name}")
|
)
|
||||||
return (lora_save_name,)
|
print(destination_path)
|
||||||
else:
|
print("Downloading external lora - " + input_id + " to " + destination_path)
|
||||||
lora_save_name = str(uuid.uuid4()) + ".safetensors"
|
response = requests.get(
|
||||||
print(lora_save_name)
|
input_id,
|
||||||
print(folder_paths.folder_names_and_paths["loras"][0][0])
|
headers={"User-Agent": "Mozilla/5.0"},
|
||||||
destination_path = os.path.join(
|
allow_redirects=True,
|
||||||
folder_paths.folder_names_and_paths["loras"][0][0], lora_save_name
|
)
|
||||||
)
|
with open(destination_path, "wb") as out_file:
|
||||||
print(destination_path)
|
out_file.write(response.content)
|
||||||
print(
|
return (unique_filename,)
|
||||||
"Downloading external lora - "
|
|
||||||
+ lora_url
|
|
||||||
+ " to "
|
|
||||||
+ destination_path
|
|
||||||
)
|
|
||||||
headers = {"User-Agent": "Mozilla/5.0"}
|
|
||||||
if bearer_token:
|
|
||||||
headers["Authorization"] = f"Bearer {bearer_token}"
|
|
||||||
print("using bearer token")
|
|
||||||
response = requests.get(
|
|
||||||
lora_url,
|
|
||||||
headers=headers,
|
|
||||||
allow_redirects=True,
|
|
||||||
)
|
|
||||||
with open(destination_path, "wb") as out_file:
|
|
||||||
out_file.write(response.content)
|
|
||||||
print(f"Ext Lora loading: {lora_url} to {lora_save_name}")
|
|
||||||
return (lora_save_name,)
|
|
||||||
else:
|
|
||||||
print(f"Ext Lora loading: {lora_url}")
|
|
||||||
return (lora_url,)
|
|
||||||
else:
|
else:
|
||||||
print(f"Ext Lora loading: {default_lora_name}")
|
print(f"using lora: {default_lora_name}")
|
||||||
return (default_lora_name,)
|
return (default_lora_name,)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,25 +16,19 @@ class ComfyUIDeployExternalNumber:
|
|||||||
"optional": {
|
"optional": {
|
||||||
"default_value": (
|
"default_value": (
|
||||||
"FLOAT",
|
"FLOAT",
|
||||||
{"multiline": True, "display": "number", "default": 0, "min": -2147483647, "max": 2147483647, "step": 0.01},
|
{"multiline": True, "display": "number", "default": 0, "step": 0.01},
|
||||||
),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("FLOAT",)
|
RETURN_TYPES = ("FLOAT",)
|
||||||
RETURN_NAMES = ("value",)
|
RETURN_NAMES = ("value",)
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, display_name=None, description=None):
|
FUNCTION = "run"
|
||||||
|
|
||||||
|
CATEGORY = "number"
|
||||||
|
|
||||||
|
def run(self, input_id, default_value=None):
|
||||||
try:
|
try:
|
||||||
float_value = float(input_id)
|
float_value = float(input_id)
|
||||||
print("my number", float_value)
|
print("my number", float_value)
|
||||||
|
|||||||
@@ -16,25 +16,19 @@ class ComfyUIDeployExternalNumberInt:
|
|||||||
"optional": {
|
"optional": {
|
||||||
"default_value": (
|
"default_value": (
|
||||||
"INT",
|
"INT",
|
||||||
{"multiline": True, "display": "number", "min": -2147483647, "max": 2147483647, "default": 0},
|
{"multiline": True, "display": "number", "default": 0},
|
||||||
),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("INT",)
|
RETURN_TYPES = ("INT",)
|
||||||
RETURN_NAMES = ("value",)
|
RETURN_NAMES = ("value",)
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, display_name=None, description=None):
|
FUNCTION = "run"
|
||||||
|
|
||||||
|
CATEGORY = "number"
|
||||||
|
|
||||||
|
def run(self, input_id, default_value=None):
|
||||||
if not input_id or (isinstance(input_id, str) and not input_id.strip().isdigit()):
|
if not input_id or (isinstance(input_id, str) and not input_id.strip().isdigit()):
|
||||||
return [default_value]
|
return [default_value]
|
||||||
return [int(input_id)]
|
return [int(input_id)]
|
||||||
|
|||||||
@@ -11,33 +11,27 @@ class ComfyUIDeployExternalNumberSlider:
|
|||||||
"optional": {
|
"optional": {
|
||||||
"default_value": (
|
"default_value": (
|
||||||
"FLOAT",
|
"FLOAT",
|
||||||
{"multiline": True, "display": "number", "min": -2147483647, "max": 2147483647, "default": 0.5, "step": 0.01},
|
{"multiline": True, "display": "number", "default": 0.5, "step": 0.01},
|
||||||
),
|
),
|
||||||
"min_value": (
|
"min_value": (
|
||||||
"FLOAT",
|
"FLOAT",
|
||||||
{"multiline": True, "display": "number", "min": -2147483647, "max": 2147483647, "default": 0, "step": 0.01},
|
{"multiline": True, "display": "number", "default": 0, "step": 0.01},
|
||||||
),
|
),
|
||||||
"max_value": (
|
"max_value": (
|
||||||
"FLOAT",
|
"FLOAT",
|
||||||
{"multiline": True, "display": "number", "min": -2147483647, "max": 2147483647, "default": 1, "step": 0.01},
|
{"multiline": True, "display": "number", "default": 1, "step": 0.01},
|
||||||
),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TYPES = ("FLOAT",)
|
RETURN_TYPES = ("FLOAT",)
|
||||||
RETURN_NAMES = ("value",)
|
RETURN_NAMES = ("value",)
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, min_value=0, max_value=1, display_name=None, description=None):
|
FUNCTION = "run"
|
||||||
|
|
||||||
|
CATEGORY = "number"
|
||||||
|
|
||||||
|
def run(self, input_id, default_value=None, min_value=0, max_value=1):
|
||||||
try:
|
try:
|
||||||
float_value = float(input_id)
|
float_value = float(input_id)
|
||||||
if min_value <= float_value <= max_value:
|
if min_value <= float_value <= max_value:
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
class ComfyUIDeployExternalNumberSliderInt:
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"input_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "input_number_slider_int"},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"default_value": (
|
|
||||||
"INT",
|
|
||||||
{"multiline": True, "display": "number", "min": -2147483647, "max": 2147483647, "default": 1, "step": 1},
|
|
||||||
),
|
|
||||||
"min_value": (
|
|
||||||
"INT",
|
|
||||||
{"multiline": True, "display": "number", "min": -2147483647, "max": 2147483647, "default": 0, "step": 1},
|
|
||||||
),
|
|
||||||
"max_value": (
|
|
||||||
"INT",
|
|
||||||
{"multiline": True, "display": "number", "min": -2147483647, "max": 2147483647, "default": 10, "step": 1},
|
|
||||||
),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = ("INT",)
|
|
||||||
RETURN_NAMES = ("value",)
|
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, min_value=0, max_value=10, display_name=None, description=None):
|
|
||||||
try:
|
|
||||||
int_value = int(round(float(input_id)))
|
|
||||||
if min_value <= int_value <= max_value:
|
|
||||||
print("my integer", int_value)
|
|
||||||
return [int_value]
|
|
||||||
else:
|
|
||||||
print("Integer out of range. Returning default value:", default_value)
|
|
||||||
return [default_value]
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
print("Invalid input. Returning default value:", default_value)
|
|
||||||
return [default_value]
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalNumberSliderInt": ComfyUIDeployExternalNumberSliderInt}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {"ComfyUIDeployExternalNumberSliderInt": "External Number Slider Int (ComfyUI Deploy)"}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
class ComfyUIDeployExternalSeed:
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"input_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "input_seed"},
|
|
||||||
),
|
|
||||||
"default_value": (
|
|
||||||
"INT",
|
|
||||||
{"default": -1},
|
|
||||||
),
|
|
||||||
"min_value": (
|
|
||||||
"INT",
|
|
||||||
{"default": 1, "min": 1, "max": 999999999999999},
|
|
||||||
),
|
|
||||||
"max_value": (
|
|
||||||
"INT",
|
|
||||||
{"default": 4294967295, "min": 1, "max": 999999999999999},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{
|
|
||||||
"multiline": True,
|
|
||||||
"default": 'For default value:\n"-1" (i.e. not in range): Randomize within the min and max value range. \nin range: Fixed, always the same value\n',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = ("INT",)
|
|
||||||
RETURN_NAMES = ("seed",)
|
|
||||||
FUNCTION = "run"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
# Limits
|
|
||||||
_MAX_LIMIT = 999_999_999_999_999 # 15 digits
|
|
||||||
|
|
||||||
# Store cached seed when fixed flag is enabled
|
|
||||||
_cached_seed = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def IS_CHANGED(
|
|
||||||
cls,
|
|
||||||
input_id,
|
|
||||||
min_value,
|
|
||||||
max_value,
|
|
||||||
default_value=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
"""Inform ComfyUI whether the node output should be considered changed.
|
|
||||||
|
|
||||||
If default_value is within range (Fixed mode), we return the inputs tuple
|
|
||||||
so the cached result is reused until the user changes something.
|
|
||||||
For Randomize mode, we force re-execution each queue.
|
|
||||||
"""
|
|
||||||
# Clamp values to allowed range for check
|
|
||||||
min_value = max(1, min_value)
|
|
||||||
max_value = min(cls._MAX_LIMIT, max_value)
|
|
||||||
|
|
||||||
# Fixed mode when default_value is within range
|
|
||||||
if (
|
|
||||||
default_value is not None
|
|
||||||
and default_value >= min_value
|
|
||||||
and default_value <= max_value
|
|
||||||
):
|
|
||||||
return (input_id, default_value)
|
|
||||||
|
|
||||||
# For Randomize (default_value is -1 or out of range) we force re-execution
|
|
||||||
import random as _rnd
|
|
||||||
|
|
||||||
return _rnd.random()
|
|
||||||
|
|
||||||
def run(
|
|
||||||
self,
|
|
||||||
input_id,
|
|
||||||
min_value: int,
|
|
||||||
max_value: int,
|
|
||||||
display_name=None,
|
|
||||||
description=None,
|
|
||||||
default_value: int = -1,
|
|
||||||
):
|
|
||||||
# Clamp values to allowed range
|
|
||||||
min_value = max(1, min_value)
|
|
||||||
max_value = min(self._MAX_LIMIT, max_value)
|
|
||||||
|
|
||||||
# Ensure limits are in correct order after clamping
|
|
||||||
if min_value > max_value:
|
|
||||||
min_value, max_value = max_value, min_value
|
|
||||||
|
|
||||||
# Fixed mode: default_value is within range
|
|
||||||
if default_value >= min_value and default_value <= max_value:
|
|
||||||
seed = int(default_value)
|
|
||||||
self._cached_seed = seed
|
|
||||||
return [seed]
|
|
||||||
|
|
||||||
# Randomize mode: default_value is -1 or out of range
|
|
||||||
seed = random.randint(min_value, max_value)
|
|
||||||
self._cached_seed = seed
|
|
||||||
return [seed]
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalSeed": ComfyUIDeployExternalSeed}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
||||||
"ComfyUIDeployExternalSeed": "External Seed (ComfyUI Deploy)"
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
class StringFunction:
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"action": (["append", "replace"], {}),
|
|
||||||
"tidy_tags": (["yes", "no"], {}),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"text_a": ("STRING", {"multiline": True, "dynamicPrompts": False}),
|
|
||||||
"text_b": ("STRING", {"multiline": True, "dynamicPrompts": False}),
|
|
||||||
"text_c": ("STRING", {"multiline": True, "dynamicPrompts": False}),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = ("STRING",)
|
|
||||||
FUNCTION = "exec"
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
OUTPUT_NODE = True
|
|
||||||
|
|
||||||
def exec(self, action, tidy_tags, text_a="", text_b="", text_c=""):
|
|
||||||
tidy_tags = tidy_tags == "yes"
|
|
||||||
out = ""
|
|
||||||
if action == "append":
|
|
||||||
out = (", " if tidy_tags else "").join(
|
|
||||||
filter(None, [text_a, text_b, text_c])
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
if text_c is None:
|
|
||||||
text_c = ""
|
|
||||||
if text_b.startswith("/") and text_b.endswith("/"):
|
|
||||||
regex = text_b[1:-1]
|
|
||||||
out = re.sub(regex, text_c, text_a)
|
|
||||||
else:
|
|
||||||
out = text_a.replace(text_b, text_c)
|
|
||||||
if tidy_tags:
|
|
||||||
out = re.sub(r"\s{2,}", " ", out)
|
|
||||||
out = out.replace(" ,", ",")
|
|
||||||
out = re.sub(r",{2,}", ",", out)
|
|
||||||
out = out.strip()
|
|
||||||
return {"ui": {"text": (out,)}, "result": (out,)}
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
|
||||||
"ComfyUIDeployStringCombine": StringFunction,
|
|
||||||
}
|
|
||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
||||||
"ComfyUIDeployStringCombine": "String Combine (ComfyUI Deploy)",
|
|
||||||
}
|
|
||||||
@@ -18,14 +18,6 @@ class ComfyUIDeployExternalText:
|
|||||||
"STRING",
|
"STRING",
|
||||||
{"multiline": True, "default": ""},
|
{"multiline": True, "default": ""},
|
||||||
),
|
),
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,9 +26,9 @@ class ComfyUIDeployExternalText:
|
|||||||
|
|
||||||
FUNCTION = "run"
|
FUNCTION = "run"
|
||||||
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
CATEGORY = "text"
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, display_name=None, description=None):
|
def run(self, input_id, default_value=None):
|
||||||
return [default_value]
|
return [default_value]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
class AnyType(str):
|
|
||||||
def __ne__(self, __value: object) -> bool:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
WILDCARD = AnyType("*")
|
|
||||||
|
|
||||||
class ComfyUIDeployExternalTextAny:
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"input_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "input_text"},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"default_value": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = (WILDCARD,)
|
|
||||||
RETURN_NAMES = ("text",)
|
|
||||||
|
|
||||||
FUNCTION = "run"
|
|
||||||
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def run(self, input_id, default_value=None, display_name=None, description=None):
|
|
||||||
return [default_value]
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyUIDeployExternalTextAny": ComfyUIDeployExternalTextAny}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {"ComfyUIDeployExternalTextAny": "External Text Any (ComfyUI Deploy)"}
|
|
||||||
@@ -36,7 +36,6 @@ class ComfyUIDeployExternalVideo:
|
|||||||
RETURN_NAMES = ("video")
|
RETURN_NAMES = ("video")
|
||||||
|
|
||||||
FUNCTION = "load_video"
|
FUNCTION = "load_video"
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def load_video(self, input_id, default_value):
|
def load_video(self, input_id, default_value):
|
||||||
input_dir = folder_paths.get_input_directory()
|
input_dir = folder_paths.get_input_directory()
|
||||||
|
|||||||
+42
-346
@@ -1,15 +1,10 @@
|
|||||||
# credit goes to https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite
|
# credit goes to https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite and is meant to work with
|
||||||
# Intended to work with https://github.com/NicholasKao1029/ComfyUI-VideoHelperSuite/tree/main
|
|
||||||
import os
|
import os
|
||||||
import itertools
|
import itertools
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import torch
|
import torch
|
||||||
from typing import Union
|
|
||||||
from torch import Tensor
|
|
||||||
import cv2
|
import cv2
|
||||||
import psutil
|
|
||||||
|
|
||||||
from collections.abc import Mapping
|
|
||||||
import folder_paths
|
import folder_paths
|
||||||
from comfy.utils import common_upscale
|
from comfy.utils import common_upscale
|
||||||
|
|
||||||
@@ -95,25 +90,13 @@ if gifski_path is None:
|
|||||||
gifski_path = shutil.which("gifski")
|
gifski_path = shutil.which("gifski")
|
||||||
|
|
||||||
|
|
||||||
def is_safe_path(path):
|
|
||||||
if "VHS_STRICT_PATHS" not in os.environ:
|
|
||||||
return True
|
|
||||||
basedir = os.path.abspath(".")
|
|
||||||
try:
|
|
||||||
common_path = os.path.commonpath([basedir, path])
|
|
||||||
except:
|
|
||||||
# Different drive on windows
|
|
||||||
return False
|
|
||||||
return common_path == basedir
|
|
||||||
|
|
||||||
|
|
||||||
def get_sorted_dir_files_from_directory(
|
def get_sorted_dir_files_from_directory(
|
||||||
directory: str,
|
directory: str,
|
||||||
skip_first_images: int = 0,
|
skip_first_images: int = 0,
|
||||||
select_every_nth: int = 1,
|
select_every_nth: int = 1,
|
||||||
extensions: Iterable = None,
|
extensions: Iterable = None,
|
||||||
):
|
):
|
||||||
directory = strip_path(directory)
|
directory = directory.strip()
|
||||||
dir_files = os.listdir(directory)
|
dir_files = os.listdir(directory)
|
||||||
dir_files = sorted(dir_files)
|
dir_files = sorted(dir_files)
|
||||||
dir_files = [os.path.join(directory, x) for x in dir_files]
|
dir_files = [os.path.join(directory, x) for x in dir_files]
|
||||||
@@ -194,59 +177,18 @@ def requeue_workflow(requeue_required=(-1, True)):
|
|||||||
|
|
||||||
|
|
||||||
def get_audio(file, start_time=0, duration=0):
|
def get_audio(file, start_time=0, duration=0):
|
||||||
args = [ffmpeg_path, "-i", file]
|
args = [ffmpeg_path, "-v", "error", "-i", file]
|
||||||
if start_time > 0:
|
if start_time > 0:
|
||||||
args += ["-ss", str(start_time)]
|
args += ["-ss", str(start_time)]
|
||||||
if duration > 0:
|
if duration > 0:
|
||||||
args += ["-t", str(duration)]
|
args += ["-t", str(duration)]
|
||||||
try:
|
try:
|
||||||
# TODO: scan for sample rate and maintain
|
|
||||||
res = subprocess.run(
|
res = subprocess.run(
|
||||||
args + ["-f", "f32le", "-"], capture_output=True, check=True
|
args + ["-f", "wav", "-"], stdout=subprocess.PIPE, check=True
|
||||||
)
|
).stdout
|
||||||
audio = torch.frombuffer(bytearray(res.stdout), dtype=torch.float32)
|
|
||||||
match = re.search(", (\\d+) Hz, (\\w+), ", res.stderr.decode("utf-8"))
|
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
raise Exception(
|
return False
|
||||||
f"VHS failed to extract audio from {file}:\n" + e.stderr.decode("utf-8")
|
return res
|
||||||
)
|
|
||||||
if match:
|
|
||||||
ar = int(match.group(1))
|
|
||||||
# NOTE: Just throwing an error for other channel types right now
|
|
||||||
# Will deal with issues if they come
|
|
||||||
ac = {"mono": 1, "stereo": 2}[match.group(2)]
|
|
||||||
else:
|
|
||||||
ar = 44100
|
|
||||||
ac = 2
|
|
||||||
audio = audio.reshape((-1, ac)).transpose(0, 1).unsqueeze(0)
|
|
||||||
return {"waveform": audio, "sample_rate": ar}
|
|
||||||
|
|
||||||
|
|
||||||
class LazyAudioMap(Mapping):
|
|
||||||
def __init__(self, file, start_time, duration):
|
|
||||||
self.file = file
|
|
||||||
self.start_time = start_time
|
|
||||||
self.duration = duration
|
|
||||||
self._dict = None
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
if self._dict is None:
|
|
||||||
self._dict = get_audio(self.file, self.start_time, self.duration)
|
|
||||||
return self._dict[key]
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
if self._dict is None:
|
|
||||||
self._dict = get_audio(self.file, self.start_time, self.duration)
|
|
||||||
return iter(self._dict)
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
if self._dict is None:
|
|
||||||
self._dict = get_audio(self.file, self.start_time, self.duration)
|
|
||||||
return len(self._dict)
|
|
||||||
|
|
||||||
|
|
||||||
def lazy_get_audio(file, start_time=0, duration=0):
|
|
||||||
return LazyAudioMap(file, start_time, duration)
|
|
||||||
|
|
||||||
|
|
||||||
def lazy_eval(func):
|
def lazy_eval(func):
|
||||||
@@ -288,19 +230,6 @@ def validate_sequence(path):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def strip_path(path):
|
|
||||||
# This leaves whitespace inside quotes and only a single "
|
|
||||||
# thus ' ""test"' -> '"test'
|
|
||||||
# consider path.strip(string.whitespace+"\"")
|
|
||||||
# or weightier re.fullmatch("[\\s\"]*(.+?)[\\s\"]*", path).group(1)
|
|
||||||
path = path.strip()
|
|
||||||
if path.startswith('"'):
|
|
||||||
path = path[1:]
|
|
||||||
if path.endswith('"'):
|
|
||||||
path = path[:-1]
|
|
||||||
return path
|
|
||||||
|
|
||||||
|
|
||||||
def hash_path(path):
|
def hash_path(path):
|
||||||
if path is None:
|
if path is None:
|
||||||
return "input"
|
return "input"
|
||||||
@@ -357,145 +286,6 @@ def target_size(
|
|||||||
return (width, height)
|
return (width, height)
|
||||||
|
|
||||||
|
|
||||||
def validate_index(
|
|
||||||
index: int,
|
|
||||||
length: int = 0,
|
|
||||||
is_range: bool = False,
|
|
||||||
allow_negative=False,
|
|
||||||
allow_missing=False,
|
|
||||||
) -> int:
|
|
||||||
# if part of range, do nothing
|
|
||||||
if is_range:
|
|
||||||
return index
|
|
||||||
# otherwise, validate index
|
|
||||||
# validate not out of range - only when latent_count is passed in
|
|
||||||
if length > 0 and index > length - 1 and not allow_missing:
|
|
||||||
raise IndexError(f"Index '{index}' out of range for {length} item(s).")
|
|
||||||
# if negative, validate not out of range
|
|
||||||
if index < 0:
|
|
||||||
if not allow_negative:
|
|
||||||
raise IndexError(f"Negative indeces not allowed, but was '{index}'.")
|
|
||||||
conv_index = length + index
|
|
||||||
if conv_index < 0 and not allow_missing:
|
|
||||||
raise IndexError(
|
|
||||||
f"Index '{index}', converted to '{conv_index}' out of range for {length} item(s)."
|
|
||||||
)
|
|
||||||
index = conv_index
|
|
||||||
return index
|
|
||||||
|
|
||||||
|
|
||||||
def convert_to_index_int(
|
|
||||||
raw_index: str,
|
|
||||||
length: int = 0,
|
|
||||||
is_range: bool = False,
|
|
||||||
allow_negative=False,
|
|
||||||
allow_missing=False,
|
|
||||||
) -> int:
|
|
||||||
try:
|
|
||||||
return validate_index(
|
|
||||||
int(raw_index),
|
|
||||||
length=length,
|
|
||||||
is_range=is_range,
|
|
||||||
allow_negative=allow_negative,
|
|
||||||
allow_missing=allow_missing,
|
|
||||||
)
|
|
||||||
except ValueError as e:
|
|
||||||
raise ValueError(f"Index '{raw_index}' must be an integer.", e)
|
|
||||||
|
|
||||||
|
|
||||||
def convert_str_to_indexes(
|
|
||||||
indexes_str: str, length: int = 0, allow_missing=False
|
|
||||||
) -> list[int]:
|
|
||||||
if not indexes_str:
|
|
||||||
return []
|
|
||||||
int_indexes = list(range(0, length))
|
|
||||||
allow_negative = length > 0
|
|
||||||
chosen_indexes = []
|
|
||||||
# parse string - allow positive ints, negative ints, and ranges separated by ':'
|
|
||||||
groups = indexes_str.split(",")
|
|
||||||
groups = [g.strip() for g in groups]
|
|
||||||
for g in groups:
|
|
||||||
# parse range of indeces (e.g. 2:16)
|
|
||||||
if ":" in g:
|
|
||||||
index_range = g.split(":", 2)
|
|
||||||
index_range = [r.strip() for r in index_range]
|
|
||||||
|
|
||||||
start_index = index_range[0]
|
|
||||||
if len(start_index) > 0:
|
|
||||||
start_index = convert_to_index_int(
|
|
||||||
start_index,
|
|
||||||
length=length,
|
|
||||||
is_range=True,
|
|
||||||
allow_negative=allow_negative,
|
|
||||||
allow_missing=allow_missing,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
start_index = 0
|
|
||||||
end_index = index_range[1]
|
|
||||||
if len(end_index) > 0:
|
|
||||||
end_index = convert_to_index_int(
|
|
||||||
end_index,
|
|
||||||
length=length,
|
|
||||||
is_range=True,
|
|
||||||
allow_negative=allow_negative,
|
|
||||||
allow_missing=allow_missing,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
end_index = length
|
|
||||||
# support step as well, to allow things like reversing, every-other, etc.
|
|
||||||
step = 1
|
|
||||||
if len(index_range) > 2:
|
|
||||||
step = index_range[2]
|
|
||||||
if len(step) > 0:
|
|
||||||
step = convert_to_index_int(
|
|
||||||
step,
|
|
||||||
length=length,
|
|
||||||
is_range=True,
|
|
||||||
allow_negative=True,
|
|
||||||
allow_missing=True,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
step = 1
|
|
||||||
# if latents were passed in, base indeces on known latent count
|
|
||||||
if len(int_indexes) > 0:
|
|
||||||
chosen_indexes.extend(int_indexes[start_index:end_index][::step])
|
|
||||||
# otherwise, assume indeces are valid
|
|
||||||
else:
|
|
||||||
chosen_indexes.extend(list(range(start_index, end_index, step)))
|
|
||||||
# parse individual indeces
|
|
||||||
else:
|
|
||||||
chosen_indexes.append(
|
|
||||||
convert_to_index_int(
|
|
||||||
g,
|
|
||||||
length=length,
|
|
||||||
allow_negative=allow_negative,
|
|
||||||
allow_missing=allow_missing,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return chosen_indexes
|
|
||||||
|
|
||||||
|
|
||||||
def select_indexes(input_obj: Union[Tensor, list], idxs: list):
|
|
||||||
if type(input_obj) == Tensor:
|
|
||||||
return input_obj[idxs]
|
|
||||||
else:
|
|
||||||
return [input_obj[i] for i in idxs]
|
|
||||||
|
|
||||||
|
|
||||||
def select_indexes_from_str(
|
|
||||||
input_obj: Union[Tensor, list], indexes: str, err_if_missing=True, err_if_empty=True
|
|
||||||
):
|
|
||||||
real_idxs = convert_str_to_indexes(
|
|
||||||
indexes, len(input_obj), allow_missing=not err_if_missing
|
|
||||||
)
|
|
||||||
if err_if_empty and len(real_idxs) == 0:
|
|
||||||
raise Exception(f"Nothing was selected based on indexes found in '{indexes}'.")
|
|
||||||
return select_indexes(input_obj, real_idxs)
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
|
|
||||||
def cv_frame_generator(
|
def cv_frame_generator(
|
||||||
video,
|
video,
|
||||||
force_rate,
|
force_rate,
|
||||||
@@ -505,10 +295,9 @@ def cv_frame_generator(
|
|||||||
meta_batch=None,
|
meta_batch=None,
|
||||||
unique_id=None,
|
unique_id=None,
|
||||||
):
|
):
|
||||||
video_cap = cv2.VideoCapture(strip_path(video))
|
video_cap = cv2.VideoCapture(video)
|
||||||
if not video_cap.isOpened():
|
if not video_cap.isOpened():
|
||||||
raise ValueError(f"{video} could not be loaded with cv.")
|
raise ValueError(f"{video} could not be loaded with cv.")
|
||||||
pbar = None
|
|
||||||
|
|
||||||
# extract video metadata
|
# extract video metadata
|
||||||
fps = video_cap.get(cv2.CAP_PROP_FPS)
|
fps = video_cap.get(cv2.CAP_PROP_FPS)
|
||||||
@@ -530,8 +319,6 @@ def cv_frame_generator(
|
|||||||
target_frame_time = 1 / force_rate
|
target_frame_time = 1 / force_rate
|
||||||
|
|
||||||
yield (width, height, fps, duration, total_frames, target_frame_time)
|
yield (width, height, fps, duration, total_frames, target_frame_time)
|
||||||
if meta_batch is not None:
|
|
||||||
yield min(frame_load_cap, total_frames)
|
|
||||||
|
|
||||||
time_offset = target_frame_time - base_frame_time
|
time_offset = target_frame_time - base_frame_time
|
||||||
while video_cap.isOpened():
|
while video_cap.isOpened():
|
||||||
@@ -562,8 +349,7 @@ def cv_frame_generator(
|
|||||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||||
# convert frame to comfyui's expected format
|
# convert frame to comfyui's expected format
|
||||||
# TODO: frame contains no exif information. Check if opencv2 has already applied
|
# TODO: frame contains no exif information. Check if opencv2 has already applied
|
||||||
frame = np.array(frame, dtype=np.float32)
|
frame = np.array(frame, dtype=np.float32) / 255.0
|
||||||
torch.from_numpy(frame).div_(255)
|
|
||||||
if prev_frame is not None:
|
if prev_frame is not None:
|
||||||
inp = yield prev_frame
|
inp = yield prev_frame
|
||||||
if inp is not None:
|
if inp is not None:
|
||||||
@@ -571,8 +357,6 @@ def cv_frame_generator(
|
|||||||
return
|
return
|
||||||
prev_frame = frame
|
prev_frame = frame
|
||||||
frames_added += 1
|
frames_added += 1
|
||||||
if pbar is not None:
|
|
||||||
pbar.update_absolute(frames_added, frame_load_cap)
|
|
||||||
# if cap exists and we've reached it, stop processing frames
|
# if cap exists and we've reached it, stop processing frames
|
||||||
if frame_load_cap > 0 and frames_added >= frame_load_cap:
|
if frame_load_cap > 0 and frames_added >= frame_load_cap:
|
||||||
break
|
break
|
||||||
@@ -583,17 +367,6 @@ def cv_frame_generator(
|
|||||||
yield prev_frame
|
yield prev_frame
|
||||||
|
|
||||||
|
|
||||||
def batched(it, n):
|
|
||||||
while batch := tuple(itertools.islice(it, n)):
|
|
||||||
yield batch
|
|
||||||
|
|
||||||
|
|
||||||
def batched_vae_encode(images, vae, frames_per_batch):
|
|
||||||
for batch in batched(images, frames_per_batch):
|
|
||||||
image_batch = torch.from_numpy(np.array(batch))
|
|
||||||
yield from vae.encode(image_batch).numpy()
|
|
||||||
|
|
||||||
|
|
||||||
def load_video_cv(
|
def load_video_cv(
|
||||||
video: str,
|
video: str,
|
||||||
force_rate: int,
|
force_rate: int,
|
||||||
@@ -605,8 +378,6 @@ def load_video_cv(
|
|||||||
select_every_nth: int,
|
select_every_nth: int,
|
||||||
meta_batch=None,
|
meta_batch=None,
|
||||||
unique_id=None,
|
unique_id=None,
|
||||||
memory_limit_mb=None,
|
|
||||||
vae=None,
|
|
||||||
):
|
):
|
||||||
if meta_batch is None or unique_id not in meta_batch.inputs:
|
if meta_batch is None or unique_id not in meta_batch.inputs:
|
||||||
gen = cv_frame_generator(
|
gen = cv_frame_generator(
|
||||||
@@ -630,89 +401,30 @@ def load_video_cv(
|
|||||||
total_frames,
|
total_frames,
|
||||||
target_frame_time,
|
target_frame_time,
|
||||||
)
|
)
|
||||||
meta_batch.total_frames = min(meta_batch.total_frames, next(gen))
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
(gen, width, height, fps, duration, total_frames, target_frame_time) = (
|
(gen, width, height, fps, duration, total_frames, target_frame_time) = (
|
||||||
meta_batch.inputs[unique_id]
|
meta_batch.inputs[unique_id]
|
||||||
)
|
)
|
||||||
|
|
||||||
memory_limit = None
|
if meta_batch is not None:
|
||||||
if memory_limit_mb is not None:
|
gen = itertools.islice(gen, meta_batch.frames_per_batch)
|
||||||
memory_limit *= 2**20
|
|
||||||
else:
|
|
||||||
# TODO: verify if garbage collection should be performed here.
|
|
||||||
# leaves ~128 MB unreserved for safety
|
|
||||||
try:
|
|
||||||
memory_limit = (
|
|
||||||
psutil.virtual_memory().available + psutil.swap_memory().free
|
|
||||||
) - 2**27
|
|
||||||
except:
|
|
||||||
print(
|
|
||||||
"Failed to calculate available memory. Memory load limit has been disabled"
|
|
||||||
)
|
|
||||||
if memory_limit is not None:
|
|
||||||
if vae is not None:
|
|
||||||
# space required to load as f32, exist as latent with wiggle room, decode to f32
|
|
||||||
max_loadable_frames = int(
|
|
||||||
memory_limit // (width * height * 3 * (4 + 4 + 1 / 10))
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# TODO: use better estimate for when vae is not None
|
|
||||||
# Consider completely ignoring for load_latent case?
|
|
||||||
max_loadable_frames = int(memory_limit // (width * height * 3 * (0.1)))
|
|
||||||
if meta_batch is not None:
|
|
||||||
if meta_batch.frames_per_batch > max_loadable_frames:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Meta Batch set to {meta_batch.frames_per_batch} frames but only {max_loadable_frames} can fit in memory"
|
|
||||||
)
|
|
||||||
gen = itertools.islice(gen, meta_batch.frames_per_batch)
|
|
||||||
else:
|
|
||||||
original_gen = gen
|
|
||||||
gen = itertools.islice(gen, max_loadable_frames)
|
|
||||||
downscale_ratio = getattr(vae, "downscale_ratio", 8)
|
|
||||||
frames_per_batch = (1920 * 1080 * 16) // (width * height) or 1
|
|
||||||
if force_size != "Disabled" or vae is not None:
|
|
||||||
new_size = target_size(
|
|
||||||
width, height, force_size, custom_width, custom_height, downscale_ratio
|
|
||||||
)
|
|
||||||
if new_size[0] != width or new_size[1] != height:
|
|
||||||
|
|
||||||
def rescale(frame):
|
# Some minor wizardry to eliminate a copy and reduce max memory by a factor of ~2
|
||||||
s = torch.from_numpy(
|
images = torch.from_numpy(
|
||||||
np.fromiter(frame, np.dtype((np.float32, (height, width, 3))))
|
np.fromiter(gen, np.dtype((np.float32, (height, width, 3))))
|
||||||
)
|
)
|
||||||
s = s.movedim(-1, 1)
|
|
||||||
s = common_upscale(s, new_size[0], new_size[1], "lanczos", "center")
|
|
||||||
return s.movedim(1, -1).numpy()
|
|
||||||
|
|
||||||
gen = itertools.chain.from_iterable(
|
|
||||||
map(rescale, batched(gen, frames_per_batch))
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
new_size = width, height
|
|
||||||
if vae is not None:
|
|
||||||
gen = batched_vae_encode(gen, vae, frames_per_batch)
|
|
||||||
vw, vh = new_size[0] // downscale_ratio, new_size[1] // downscale_ratio
|
|
||||||
images = torch.from_numpy(np.fromiter(gen, np.dtype((np.float32, (4, vh, vw)))))
|
|
||||||
else:
|
|
||||||
# Some minor wizardry to eliminate a copy and reduce max memory by a factor of ~2
|
|
||||||
images = torch.from_numpy(
|
|
||||||
np.fromiter(gen, np.dtype((np.float32, (new_size[1], new_size[0], 3))))
|
|
||||||
)
|
|
||||||
if meta_batch is None and memory_limit is not None:
|
|
||||||
try:
|
|
||||||
next(original_gen)
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Memory limit hit after loading {len(images)} frames. Stopping execution."
|
|
||||||
)
|
|
||||||
except StopIteration:
|
|
||||||
pass
|
|
||||||
if len(images) == 0:
|
if len(images) == 0:
|
||||||
raise RuntimeError("No frames generated")
|
raise RuntimeError("No frames generated")
|
||||||
|
if force_size != "Disabled":
|
||||||
|
new_size = target_size(width, height, force_size, custom_width, custom_height)
|
||||||
|
if new_size[0] != width or new_size[1] != height:
|
||||||
|
s = images.movedim(-1, 1)
|
||||||
|
s = common_upscale(s, new_size[0], new_size[1], "lanczos", "center")
|
||||||
|
images = s.movedim(1, -1)
|
||||||
|
|
||||||
# Setup lambda for lazy audio capture
|
# Setup lambda for lazy audio capture
|
||||||
audio = lazy_get_audio(
|
audio = lambda: get_audio(
|
||||||
video,
|
video,
|
||||||
skip_first_frames * target_frame_time,
|
skip_first_frames * target_frame_time,
|
||||||
frame_load_cap * target_frame_time * select_every_nth,
|
frame_load_cap * target_frame_time * select_every_nth,
|
||||||
@@ -728,16 +440,13 @@ def load_video_cv(
|
|||||||
"loaded_fps": 1 / target_frame_time,
|
"loaded_fps": 1 / target_frame_time,
|
||||||
"loaded_frame_count": len(images),
|
"loaded_frame_count": len(images),
|
||||||
"loaded_duration": len(images) * target_frame_time,
|
"loaded_duration": len(images) * target_frame_time,
|
||||||
"loaded_width": new_size[0],
|
"loaded_width": images.shape[2],
|
||||||
"loaded_height": new_size[1],
|
"loaded_height": images.shape[1],
|
||||||
}
|
}
|
||||||
if vae is None:
|
|
||||||
return (images, len(images), audio, video_info, None)
|
return (images, len(images), lazy_eval(audio), video_info)
|
||||||
else:
|
|
||||||
return (None, len(images), audio, video_info, {"samples": images})
|
|
||||||
|
|
||||||
|
|
||||||
# modeled after Video upload node
|
|
||||||
class ComfyUIDeployExternalVideo:
|
class ComfyUIDeployExternalVideo:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
@@ -792,34 +501,27 @@ class ComfyUIDeployExternalVideo:
|
|||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
"meta_batch": ("VHS_BatchManager",),
|
"meta_batch": ("VHS_BatchManager",),
|
||||||
"vae": ("VAE",),
|
"default_value": (sorted(files),),
|
||||||
"default_video": (sorted(files),),
|
|
||||||
"display_name": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": ""},
|
|
||||||
),
|
|
||||||
"description": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": True, "default": ""},
|
|
||||||
),
|
|
||||||
"default_value_url": ("STRING", {"image_preview": True, "default": ""}),
|
|
||||||
},
|
},
|
||||||
"hidden": {"unique_id": "UNIQUE_ID"},
|
"hidden": {"unique_id": "UNIQUE_ID"},
|
||||||
}
|
}
|
||||||
|
|
||||||
CATEGORY = "Video Helper Suite 🎥🅥🅗🅢"
|
CATEGORY = "Video Helper Suite 🎥🅥🅗🅢"
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE", "INT", "AUDIO", "VHS_VIDEOINFO", "LATENT")
|
RETURN_TYPES = (
|
||||||
|
"IMAGE",
|
||||||
|
"INT",
|
||||||
|
"VHS_AUDIO",
|
||||||
|
"VHS_VIDEOINFO",
|
||||||
|
)
|
||||||
RETURN_NAMES = (
|
RETURN_NAMES = (
|
||||||
"IMAGE",
|
"IMAGE",
|
||||||
"frame_count",
|
"frame_count",
|
||||||
"audio",
|
"audio",
|
||||||
"video_info",
|
"video_info",
|
||||||
"LATENT",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
FUNCTION = "load_video"
|
FUNCTION = "load_video"
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
def load_video(self, **kwargs):
|
def load_video(self, **kwargs):
|
||||||
input_id = kwargs.get("input_id")
|
input_id = kwargs.get("input_id")
|
||||||
@@ -832,21 +534,18 @@ class ComfyUIDeployExternalVideo:
|
|||||||
select_every_nth = kwargs.get("select_every_nth")
|
select_every_nth = kwargs.get("select_every_nth")
|
||||||
meta_batch = kwargs.get("meta_batch")
|
meta_batch = kwargs.get("meta_batch")
|
||||||
unique_id = kwargs.get("unique_id")
|
unique_id = kwargs.get("unique_id")
|
||||||
default_value_url = kwargs.get("default_value_url")
|
|
||||||
|
video = kwargs.get("default_value")
|
||||||
|
video_path = folder_paths.get_annotated_filepath(video.strip('"'))
|
||||||
|
|
||||||
input_dir = folder_paths.get_input_directory()
|
input_dir = folder_paths.get_input_directory()
|
||||||
if input_id.startswith("http") or (
|
if input_id.startswith("http"):
|
||||||
default_value_url and default_value_url.startswith("http")
|
|
||||||
):
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
# Use input_id if it's a URL, otherwise use default_value_url
|
print("Fetching video from URL: ", input_id)
|
||||||
url = input_id if input_id.startswith("http") else default_value_url
|
response = requests.get(input_id, stream=True)
|
||||||
|
|
||||||
print("Fetching video from URL: ", url)
|
|
||||||
response = requests.get(url, stream=True)
|
|
||||||
file_size = int(response.headers.get("Content-Length", 0))
|
file_size = int(response.headers.get("Content-Length", 0))
|
||||||
file_extension = url.split(".")[-1].split("?")[
|
file_extension = input_id.split(".")[-1].split("?")[
|
||||||
0
|
0
|
||||||
] # Extract extension and handle URLs with parameters
|
] # Extract extension and handle URLs with parameters
|
||||||
if file_extension not in video_extensions:
|
if file_extension not in video_extensions:
|
||||||
@@ -867,11 +566,8 @@ class ComfyUIDeployExternalVideo:
|
|||||||
leave=True,
|
leave=True,
|
||||||
):
|
):
|
||||||
out_file.write(chunk)
|
out_file.write(chunk)
|
||||||
else:
|
|
||||||
video = kwargs.get("default_video", None)
|
print("video path: ", video_path)
|
||||||
if video is None:
|
|
||||||
raise "No default video given and no external video provided"
|
|
||||||
video_path = folder_paths.get_annotated_filepath(video.strip('"'))
|
|
||||||
|
|
||||||
return load_video_cv(
|
return load_video_cv(
|
||||||
video=video_path,
|
video=video_path,
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class ComfyDeployWebscoketImageInput:
|
|||||||
RETURN_NAMES = ("images",)
|
RETURN_NAMES = ("images",)
|
||||||
|
|
||||||
FUNCTION = "run"
|
FUNCTION = "run"
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def VALIDATE_INPUTS(s, input_id):
|
def VALIDATE_INPUTS(s, input_id):
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
# In file: comfyui-deploy/comfy-nodes/output_exr.py
|
|
||||||
|
|
||||||
import os
|
|
||||||
import numpy as np
|
|
||||||
import folder_paths
|
|
||||||
|
|
||||||
# Try to set up OpenCV for EXR writing.
|
|
||||||
try:
|
|
||||||
os.environ["OPENCV_IO_ENABLE_OPENEXR"] = "1"
|
|
||||||
import cv2
|
|
||||||
OPENCV_AVAILABLE = True
|
|
||||||
except ImportError:
|
|
||||||
print("Warning: OpenCV not found for ComfyDeployOutputEXR. Please add opencv-python-headless to requirements.txt")
|
|
||||||
OPENCV_AVAILABLE = False
|
|
||||||
|
|
||||||
# ALIGNED: Renamed class to match project conventions
|
|
||||||
class ComfyDeployOutputEXR:
|
|
||||||
def __init__(self):
|
|
||||||
self.output_dir = folder_paths.get_output_directory()
|
|
||||||
self.type = "output"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"images": ("IMAGE", ),
|
|
||||||
"filename_prefix": ("STRING", {"default": "ComfyDeploy_EXR"})
|
|
||||||
},
|
|
||||||
# ADDED: Optional output_id for consistency with other ComfyDeploy nodes
|
|
||||||
"optional": {
|
|
||||||
"output_id": ("STRING", {"multiline": False, "default": "output_exr"}),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = ()
|
|
||||||
# ALIGNED: Changed function name to 'run'
|
|
||||||
FUNCTION = "run"
|
|
||||||
OUTPUT_NODE = True
|
|
||||||
# ALIGNED: Matched the category name
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
DESCRIPTION = "Saves the input images as EXR (HDR) files."
|
|
||||||
|
|
||||||
def run(self, images, filename_prefix="ComfyDeploy_EXR", output_id="output_exr"):
|
|
||||||
if not OPENCV_AVAILABLE:
|
|
||||||
raise ImportError("OpenCV is required to save EXR files. Please ensure opencv-python-headless is in requirements.txt.")
|
|
||||||
|
|
||||||
full_output_folder, filename, counter, subfolder, filename_prefix = (
|
|
||||||
folder_paths.get_save_image_path(
|
|
||||||
filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
results = list()
|
|
||||||
|
|
||||||
for image in images:
|
|
||||||
image_np = image.cpu().numpy()
|
|
||||||
|
|
||||||
if image_np.dtype != np.float32:
|
|
||||||
image_np = image_np.astype(np.float32)
|
|
||||||
|
|
||||||
file = f"{filename}_{counter:05}.exr"
|
|
||||||
file_path = os.path.join(full_output_folder, file)
|
|
||||||
|
|
||||||
image_np_bgr = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
|
|
||||||
cv2.imwrite(file_path, image_np_bgr)
|
|
||||||
|
|
||||||
results.append({
|
|
||||||
"filename": file,
|
|
||||||
"subfolder": subfolder,
|
|
||||||
"type": self.type,
|
|
||||||
"output_id": output_id, # ADDED
|
|
||||||
})
|
|
||||||
counter += 1
|
|
||||||
|
|
||||||
return {"ui": {"images": results}}
|
|
||||||
|
|
||||||
# ALIGNED: Mappings are defined at the bottom of the node file in this project
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyDeployOutputEXR": ComfyDeployOutputEXR}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {"ComfyDeployOutputEXR": "EXR Output (ComfyDeploy)"}
|
|
||||||
@@ -1,168 +0,0 @@
|
|||||||
import folder_paths
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
|
|
||||||
class AnyType(str):
|
|
||||||
def __ne__(self, __value: object) -> bool:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
WILDCARD = AnyType("*")
|
|
||||||
|
|
||||||
|
|
||||||
class ComfyDeployOutputFile:
|
|
||||||
def __init__(self):
|
|
||||||
self.output_dir = folder_paths.get_output_directory()
|
|
||||||
self.type = "output"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"file_path": (
|
|
||||||
"STRING",
|
|
||||||
{
|
|
||||||
"forceInput": True,
|
|
||||||
"tooltip": "Path to the file to output and upload.",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"output_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "output_file"},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = ()
|
|
||||||
FUNCTION = "run"
|
|
||||||
OUTPUT_NODE = True
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
DESCRIPTION = "Outputs any file by path for upload to ComfyDeploy."
|
|
||||||
|
|
||||||
def run(self, file_path, output_id="output_file"):
|
|
||||||
if not file_path or not os.path.exists(file_path):
|
|
||||||
print(f"⚠️ File not found: {file_path}")
|
|
||||||
return {"ui": {"files": []}}
|
|
||||||
|
|
||||||
# Security checks - ensure file is within safe ComfyUI paths
|
|
||||||
try:
|
|
||||||
# Get absolute paths for comparison
|
|
||||||
file_abs_path = os.path.abspath(file_path)
|
|
||||||
base_path = folder_paths.base_path
|
|
||||||
temp_dir = folder_paths.get_temp_directory()
|
|
||||||
|
|
||||||
# Check if file is within ComfyUI base path or temp directory
|
|
||||||
if not (
|
|
||||||
file_abs_path.startswith(os.path.abspath(base_path))
|
|
||||||
or file_abs_path.startswith(os.path.abspath(temp_dir))
|
|
||||||
):
|
|
||||||
print(f"⚠️ Security: File outside allowed ComfyUI paths: {file_path}")
|
|
||||||
return {"ui": {"files": []}}
|
|
||||||
|
|
||||||
# Check for path traversal attempts (but allow absolute paths within ComfyUI)
|
|
||||||
if ".." in file_path:
|
|
||||||
print(f"⚠️ Security: Path traversal attempt detected: {file_path}")
|
|
||||||
return {"ui": {"files": []}}
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"⚠️ Security check failed: {str(e)}")
|
|
||||||
return {"ui": {"files": []}}
|
|
||||||
|
|
||||||
# Get the original filename and extension
|
|
||||||
original_filename = os.path.basename(file_path)
|
|
||||||
file_extension = os.path.splitext(original_filename)[1]
|
|
||||||
|
|
||||||
# Additional filename security check
|
|
||||||
if ".." in original_filename:
|
|
||||||
print(f"⚠️ Security: Insecure filename: {original_filename}")
|
|
||||||
return {"ui": {"files": []}}
|
|
||||||
|
|
||||||
results = []
|
|
||||||
|
|
||||||
# Check if file is in output folder, if not, symlink it there
|
|
||||||
try:
|
|
||||||
if file_path.startswith(self.output_dir):
|
|
||||||
# File is already in output directory - use as is
|
|
||||||
relative_path = os.path.relpath(file_path, self.output_dir)
|
|
||||||
path_parts = relative_path.split(os.sep)
|
|
||||||
|
|
||||||
if len(path_parts) > 1:
|
|
||||||
subfolder = os.sep.join(path_parts[:-1])
|
|
||||||
else:
|
|
||||||
subfolder = ""
|
|
||||||
|
|
||||||
filename = path_parts[-1]
|
|
||||||
file_type = self.type
|
|
||||||
else:
|
|
||||||
# File is not in output folder - symlink it to output/temp
|
|
||||||
print(
|
|
||||||
f"File is not in output folder, symlinking to output/temp: {file_path}"
|
|
||||||
)
|
|
||||||
output_temp_dir = os.path.join(self.output_dir, "temp")
|
|
||||||
if not os.path.exists(output_temp_dir):
|
|
||||||
os.makedirs(output_temp_dir)
|
|
||||||
|
|
||||||
# Use the existing filename but with UUID prefix to avoid conflicts
|
|
||||||
file_ext = os.path.splitext(original_filename)[1]
|
|
||||||
temp_filename = f"{uuid.uuid4()}{file_ext}"
|
|
||||||
temp_path = os.path.join(output_temp_dir, temp_filename)
|
|
||||||
|
|
||||||
# Create symlink to file in output/temp directory where upload system expects it
|
|
||||||
try:
|
|
||||||
# Remove existing symlink if it exists
|
|
||||||
if os.path.exists(temp_path):
|
|
||||||
os.remove(temp_path)
|
|
||||||
os.symlink(file_path, temp_path)
|
|
||||||
print(f"File symlinked to output/temp: {temp_path} -> {file_path}")
|
|
||||||
except OSError as e:
|
|
||||||
# Fall back to copying if symlink fails
|
|
||||||
print(f"Symlink failed ({e}), falling back to copy")
|
|
||||||
shutil.copy2(file_path, temp_path)
|
|
||||||
print(f"File copied to output/temp: {temp_path}")
|
|
||||||
|
|
||||||
# Use output/temp directory structure for upload
|
|
||||||
subfolder = "temp"
|
|
||||||
filename = temp_filename
|
|
||||||
file_type = self.type
|
|
||||||
|
|
||||||
results.append(
|
|
||||||
{
|
|
||||||
"filename": filename,
|
|
||||||
"subfolder": subfolder,
|
|
||||||
"type": file_type,
|
|
||||||
"output_id": output_id,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"⚠️ Error processing file path: {str(e)}")
|
|
||||||
return {"ui": {"files": []}}
|
|
||||||
|
|
||||||
# Determine the appropriate UI key based on file type
|
|
||||||
file_ext = file_extension.lower()
|
|
||||||
if file_ext in [".png", ".jpg", ".jpeg", ".webp", ".gif", ".bmp", ".tiff"]:
|
|
||||||
ui_key = "images"
|
|
||||||
elif file_ext in [".mp3", ".wav", ".flac", ".aac", ".ogg"]:
|
|
||||||
ui_key = "audio"
|
|
||||||
elif file_ext in [".txt", ".json", ".md", ".csv"]:
|
|
||||||
ui_key = "text_file"
|
|
||||||
elif file_ext in [".exr", ".hdr"]:
|
|
||||||
ui_key = "images" # EXR files are still images
|
|
||||||
elif file_ext in [".zip", ".psb", ".psd"]:
|
|
||||||
ui_key = "files" # Archives and Photoshop project files
|
|
||||||
else:
|
|
||||||
ui_key = "files" # Generic files
|
|
||||||
|
|
||||||
return {"ui": {ui_key: results}}
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
|
||||||
"ComfyDeployOutputFile": ComfyDeployOutputFile,
|
|
||||||
}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
||||||
"ComfyDeployOutputFile": "File Output (ComfyDeploy)",
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
import os
|
|
||||||
import json
|
|
||||||
import numpy as np
|
|
||||||
from PIL import Image
|
|
||||||
from PIL.PngImagePlugin import PngInfo
|
|
||||||
import folder_paths
|
|
||||||
|
|
||||||
|
|
||||||
class ComfyDeployOutputImage:
|
|
||||||
def __init__(self):
|
|
||||||
self.output_dir = folder_paths.get_output_directory()
|
|
||||||
self.type = "output"
|
|
||||||
self.prefix_append = ""
|
|
||||||
self.compress_level = 4
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"images": ("IMAGE", {"tooltip": "The images to save."}),
|
|
||||||
"filename_prefix": (
|
|
||||||
"STRING",
|
|
||||||
{
|
|
||||||
"default": "ComfyUI",
|
|
||||||
"tooltip": "The prefix for the file to save. This may include formatting information such as %date:yyyy-MM-dd% or %Empty Latent Image.width% to include values from nodes.",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
"file_type": (["png", "jpg", "webp"], {"default": "webp"}),
|
|
||||||
"quality": ("INT", {"default": 80, "min": 1, "max": 100, "step": 1}),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"output_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "output_images"},
|
|
||||||
),
|
|
||||||
"remove_metadata": ("BOOLEAN", {"default": True}),
|
|
||||||
},
|
|
||||||
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = ()
|
|
||||||
FUNCTION = "run"
|
|
||||||
|
|
||||||
OUTPUT_NODE = True
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
DESCRIPTION = "Saves the input images to your ComfyUI output directory."
|
|
||||||
|
|
||||||
def run(
|
|
||||||
self,
|
|
||||||
images,
|
|
||||||
filename_prefix="ComfyUI",
|
|
||||||
file_type="png",
|
|
||||||
quality=80,
|
|
||||||
output_id="output_images",
|
|
||||||
prompt=None,
|
|
||||||
extra_pnginfo=None,
|
|
||||||
remove_metadata=True,
|
|
||||||
):
|
|
||||||
filename_prefix += self.prefix_append
|
|
||||||
full_output_folder, filename, counter, subfolder, filename_prefix = (
|
|
||||||
folder_paths.get_save_image_path(
|
|
||||||
filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
results = list()
|
|
||||||
for batch_number, image in enumerate(images):
|
|
||||||
i = 255.0 * image.cpu().numpy()
|
|
||||||
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
|
||||||
metadata = PngInfo()
|
|
||||||
if not remove_metadata:
|
|
||||||
if prompt is not None:
|
|
||||||
metadata.add_text("prompt", json.dumps(prompt))
|
|
||||||
if extra_pnginfo is not None:
|
|
||||||
for x in extra_pnginfo:
|
|
||||||
metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
|
||||||
|
|
||||||
filename_with_batch_num = filename.replace("%batch_num%", str(batch_number))
|
|
||||||
file = f"{filename_with_batch_num}_{counter:05}_.{file_type}"
|
|
||||||
file_path = os.path.join(full_output_folder, file)
|
|
||||||
|
|
||||||
if file_type == "png":
|
|
||||||
img.save(
|
|
||||||
file_path, pnginfo=metadata, compress_level=self.compress_level
|
|
||||||
)
|
|
||||||
elif file_type == "jpg":
|
|
||||||
img.save(file_path, quality=quality, optimize=True)
|
|
||||||
elif file_type == "webp":
|
|
||||||
img.save(file_path, quality=quality)
|
|
||||||
|
|
||||||
results.append(
|
|
||||||
{
|
|
||||||
"filename": file,
|
|
||||||
"subfolder": subfolder,
|
|
||||||
"type": self.type,
|
|
||||||
"output_id": output_id,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
counter += 1
|
|
||||||
|
|
||||||
return {"ui": {"images": results}}
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyDeployOutputImage": ComfyDeployOutputImage}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {"ComfyDeployOutputImage": "Image Output (ComfyDeploy)"}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
import os
|
|
||||||
import json
|
|
||||||
import folder_paths
|
|
||||||
|
|
||||||
|
|
||||||
class ComfyDeployOutputText:
|
|
||||||
def __init__(self):
|
|
||||||
self.output_dir = folder_paths.get_output_directory()
|
|
||||||
self.type = "output"
|
|
||||||
self.prefix_append = ""
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def INPUT_TYPES(s):
|
|
||||||
return {
|
|
||||||
"required": {
|
|
||||||
"text": (
|
|
||||||
"STRING",
|
|
||||||
{
|
|
||||||
"multiline": True,
|
|
||||||
"forceInput": True,
|
|
||||||
"tooltip": "The text to save.",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
"filename_prefix": (
|
|
||||||
"STRING",
|
|
||||||
{
|
|
||||||
"default": "ComfyUI",
|
|
||||||
"tooltip": "The prefix for the file to save. This may include formatting information such as %date:yyyy-MM-dd% to include values from nodes.",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
"file_type": (["txt", "json", "md"], {"default": "txt"}),
|
|
||||||
},
|
|
||||||
"optional": {
|
|
||||||
"output_id": (
|
|
||||||
"STRING",
|
|
||||||
{"multiline": False, "default": "output_text"},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = ()
|
|
||||||
FUNCTION = "run"
|
|
||||||
|
|
||||||
OUTPUT_NODE = True
|
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
DESCRIPTION = "Saves the input text to your ComfyUI output directory."
|
|
||||||
|
|
||||||
def run(
|
|
||||||
self,
|
|
||||||
text,
|
|
||||||
filename_prefix="ComfyUI",
|
|
||||||
file_type="txt",
|
|
||||||
output_id="output_text",
|
|
||||||
prompt=None,
|
|
||||||
extra_pnginfo=None,
|
|
||||||
):
|
|
||||||
filename_prefix += self.prefix_append
|
|
||||||
# For text, we don't need dimensions, so pass 0, 0
|
|
||||||
full_output_folder, filename, counter, subfolder, filename_prefix = (
|
|
||||||
folder_paths.get_save_image_path(filename_prefix, self.output_dir, 0, 0)
|
|
||||||
)
|
|
||||||
|
|
||||||
results = list()
|
|
||||||
|
|
||||||
# Create file path
|
|
||||||
file = f"{filename}_{counter:05}_.{file_type}"
|
|
||||||
file_path = os.path.join(full_output_folder, file)
|
|
||||||
|
|
||||||
# Save the text based on file type
|
|
||||||
if file_type == "json":
|
|
||||||
try:
|
|
||||||
# Try to save as JSON if the text is valid JSON
|
|
||||||
json_data = json.loads(text) if isinstance(text, str) else text
|
|
||||||
with open(file_path, "w", encoding="utf-8") as f:
|
|
||||||
json.dump(json_data, f, indent=2)
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
# Fall back to saving as plain text if not valid JSON
|
|
||||||
with open(file_path, "w", encoding="utf-8") as f:
|
|
||||||
f.write(text)
|
|
||||||
else:
|
|
||||||
# Save as plain text for txt and md
|
|
||||||
with open(file_path, "w", encoding="utf-8") as f:
|
|
||||||
f.write(text)
|
|
||||||
|
|
||||||
results.append(
|
|
||||||
{
|
|
||||||
"filename": file,
|
|
||||||
"subfolder": subfolder,
|
|
||||||
"type": self.type,
|
|
||||||
"output_id": output_id,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return {"ui": {"text_file": results}}
|
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"ComfyDeployOutputText": ComfyDeployOutputText}
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {"ComfyDeployOutputText": "Text Output (ComfyDeploy)"}
|
|
||||||
@@ -33,8 +33,10 @@ class ComfyDeployWebscoketImageOutput:
|
|||||||
|
|
||||||
RETURN_TYPES = ()
|
RETURN_TYPES = ()
|
||||||
RETURN_NAMES = ("text",)
|
RETURN_NAMES = ("text",)
|
||||||
|
|
||||||
FUNCTION = "run"
|
FUNCTION = "run"
|
||||||
CATEGORY = "🔗ComfyDeploy"
|
|
||||||
|
CATEGORY = "output"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def VALIDATE_INPUTS(s, output_id):
|
def VALIDATE_INPUTS(s, output_id):
|
||||||
|
|||||||
+415
-2819
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 156 KiB |
@@ -1,152 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "ed93ac94-4f26-4ed3-a57b-73cd8f4d3494",
|
|
||||||
"revision": 0,
|
|
||||||
"last_node_id": 5,
|
|
||||||
"last_link_id": 1,
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"type": "LoraLoader",
|
|
||||||
"pos": [
|
|
||||||
736.646728515625,
|
|
||||||
628.3823852539062
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
315,
|
|
||||||
126
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "model",
|
|
||||||
"type": "MODEL",
|
|
||||||
"link": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "clip",
|
|
||||||
"type": "CLIP",
|
|
||||||
"link": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "lora_name",
|
|
||||||
"type": "COMBO",
|
|
||||||
"widget": {
|
|
||||||
"name": "lora_name"
|
|
||||||
},
|
|
||||||
"link": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "MODEL",
|
|
||||||
"type": "MODEL",
|
|
||||||
"links": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CLIP",
|
|
||||||
"type": "CLIP",
|
|
||||||
"links": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "LoraLoader"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
"1-292.safetensors",
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"type": "ComfyUIDeployExternalLora",
|
|
||||||
"pos": [
|
|
||||||
299.6898498535156,
|
|
||||||
624.7929077148438
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
400,
|
|
||||||
208
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "path",
|
|
||||||
"type": "*",
|
|
||||||
"links": [
|
|
||||||
1
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfyui-deploy",
|
|
||||||
"ver": "cd3a2ff5471828f9c840e746551592e882c05aa4",
|
|
||||||
"Node name for S&R": "ComfyUIDeployExternalLora"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
"input_lora",
|
|
||||||
"HyperSD\\FLUX.1\\Hyper-FLUX.1-dev-16steps-lora.safetensors",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"type": "Note",
|
|
||||||
"pos": [
|
|
||||||
302.09033203125,
|
|
||||||
401.2951965332031
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
479.4894104003906,
|
|
||||||
161.61924743652344
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": [
|
|
||||||
"\"External Lora\" node will let you to use different loras from the Comfy Deploy UI or even via API.\n\n- lora_url:\n url that will be used to download your LoRA model in execution time\n\n- lora_save_name:\n when we download your model, this will be saved in your private storage, \n give it a good name :D"
|
|
||||||
],
|
|
||||||
"color": "#432",
|
|
||||||
"bgcolor": "#653"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
[
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
"COMBO"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"groups": [],
|
|
||||||
"config": {},
|
|
||||||
"extra": {
|
|
||||||
"ds": {
|
|
||||||
"scale": 1.167184107045006,
|
|
||||||
"offset": [
|
|
||||||
298.431389807788,
|
|
||||||
-207.58877445762934
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"VHS_latentpreview": false,
|
|
||||||
"VHS_latentpreviewrate": 0,
|
|
||||||
"VHS_MetadataImage": true,
|
|
||||||
"VHS_KeepIntermediate": true
|
|
||||||
},
|
|
||||||
"version": 0.4
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 233 KiB |
@@ -1,873 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "351f402b-62f2-4f62-8a5e-0b9d3510e8f9",
|
|
||||||
"revision": 0,
|
|
||||||
"last_node_id": 29,
|
|
||||||
"last_link_id": 28,
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"type": "JoinImageWithAlpha",
|
|
||||||
"pos": [
|
|
||||||
814.478271484375,
|
|
||||||
419.3052062988281
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
264.5999755859375,
|
|
||||||
46
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 5,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "image",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "alpha",
|
|
||||||
"type": "MASK",
|
|
||||||
"link": 12
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "IMAGE",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
11
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "JoinImageWithAlpha"
|
|
||||||
},
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 15,
|
|
||||||
"type": "PreviewImage",
|
|
||||||
"pos": [
|
|
||||||
1950,
|
|
||||||
640
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
210,
|
|
||||||
246
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 18,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "images",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 16
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "PreviewImage"
|
|
||||||
},
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10,
|
|
||||||
"type": "LoadImage",
|
|
||||||
"pos": [
|
|
||||||
467.8168640136719,
|
|
||||||
422.453857421875
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
315,
|
|
||||||
314
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "IMAGE",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
10
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "MASK",
|
|
||||||
"type": "MASK",
|
|
||||||
"links": [
|
|
||||||
12
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "LoadImage"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
"Bob-Minion-Background-PNG-Image.png",
|
|
||||||
"image",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 18,
|
|
||||||
"type": "Note",
|
|
||||||
"pos": [
|
|
||||||
460.8001708984375,
|
|
||||||
263.64251708984375
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
379.4292297363281,
|
|
||||||
88
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": [
|
|
||||||
"Option 1: CREATE THE MASK FROM THE ALPHA CHANNEL (Useful for example to generate the background of an image)\n\nMake sure that you are using \"External Image Alpha\". \n"
|
|
||||||
],
|
|
||||||
"color": "#432",
|
|
||||||
"bgcolor": "#653"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 21,
|
|
||||||
"type": "LoadImage",
|
|
||||||
"pos": [
|
|
||||||
469.57025146484375,
|
|
||||||
1506.3018798828125
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
315,
|
|
||||||
314
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "IMAGE",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
18
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "MASK",
|
|
||||||
"type": "MASK",
|
|
||||||
"links": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "LoadImage"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
"ComfyUI_temp_otmos_00005_.png",
|
|
||||||
"image",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 25,
|
|
||||||
"type": "MaskToImage",
|
|
||||||
"pos": [
|
|
||||||
1283.1668701171875,
|
|
||||||
1579.603271484375
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
176.39999389648438,
|
|
||||||
26
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 13,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "mask",
|
|
||||||
"type": "MASK",
|
|
||||||
"link": 28
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "IMAGE",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
21
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "MaskToImage"
|
|
||||||
},
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 13,
|
|
||||||
"type": "SplitImageWithAlpha",
|
|
||||||
"pos": [
|
|
||||||
1602.5518798828125,
|
|
||||||
417.59869384765625
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
277.20001220703125,
|
|
||||||
46
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 11,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "image",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 13
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "IMAGE",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
14,
|
|
||||||
25
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "MASK",
|
|
||||||
"type": "MASK",
|
|
||||||
"links": [
|
|
||||||
15,
|
|
||||||
26
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "SplitImageWithAlpha"
|
|
||||||
},
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 29,
|
|
||||||
"type": "VAEEncodeForInpaint",
|
|
||||||
"pos": [
|
|
||||||
2220.89453125,
|
|
||||||
401.0885009765625
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
340.20001220703125,
|
|
||||||
98
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 16,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "pixels",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 25
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "vae",
|
|
||||||
"type": "VAE",
|
|
||||||
"link": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mask",
|
|
||||||
"type": "MASK",
|
|
||||||
"link": 26
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "LATENT",
|
|
||||||
"type": "LATENT",
|
|
||||||
"links": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "VAEEncodeForInpaint"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
6
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 14,
|
|
||||||
"type": "PreviewImage",
|
|
||||||
"pos": [
|
|
||||||
1950,
|
|
||||||
350
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
210,
|
|
||||||
246
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 14,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "images",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 14
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "PreviewImage"
|
|
||||||
},
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 17,
|
|
||||||
"type": "MaskToImage",
|
|
||||||
"pos": [
|
|
||||||
1752.33203125,
|
|
||||||
572.061767578125
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
176.39999389648438,
|
|
||||||
26
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 15,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "mask",
|
|
||||||
"type": "MASK",
|
|
||||||
"link": 15
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "IMAGE",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
16
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "MaskToImage"
|
|
||||||
},
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 27,
|
|
||||||
"type": "PreviewImage",
|
|
||||||
"pos": [
|
|
||||||
1329.2960205078125,
|
|
||||||
1132.759765625
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
210,
|
|
||||||
246
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 10,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "images",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 22
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "PreviewImage"
|
|
||||||
},
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 20,
|
|
||||||
"type": "LoadImage",
|
|
||||||
"pos": [
|
|
||||||
468.1963806152344,
|
|
||||||
1128.9498291015625
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
315,
|
|
||||||
314
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 3,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "IMAGE",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
17
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "MASK",
|
|
||||||
"type": "MASK",
|
|
||||||
"links": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "LoadImage"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
"clipspace/clipspace-mask-1126817.300000012.png [input]",
|
|
||||||
"image",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 24,
|
|
||||||
"type": "ImageToMask",
|
|
||||||
"pos": [
|
|
||||||
1255.560302734375,
|
|
||||||
1468.347900390625
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
315,
|
|
||||||
58
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 9,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "image",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 19
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "MASK",
|
|
||||||
"type": "MASK",
|
|
||||||
"links": [
|
|
||||||
24,
|
|
||||||
28
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "ImageToMask"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
"red"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 26,
|
|
||||||
"type": "PreviewImage",
|
|
||||||
"pos": [
|
|
||||||
1488.1925048828125,
|
|
||||||
1579.146728515625
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
210,
|
|
||||||
246
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 17,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "images",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 21
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "PreviewImage"
|
|
||||||
},
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 28,
|
|
||||||
"type": "VAEEncodeForInpaint",
|
|
||||||
"pos": [
|
|
||||||
1637.603271484375,
|
|
||||||
1182.81298828125
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
340.20001220703125,
|
|
||||||
98
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 12,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "pixels",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 23
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "vae",
|
|
||||||
"type": "VAE",
|
|
||||||
"link": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mask",
|
|
||||||
"type": "MASK",
|
|
||||||
"link": 24
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "LATENT",
|
|
||||||
"type": "LATENT",
|
|
||||||
"links": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfy-core",
|
|
||||||
"ver": "0.3.27",
|
|
||||||
"Node name for S&R": "VAEEncodeForInpaint"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
6
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 19,
|
|
||||||
"type": "Note",
|
|
||||||
"pos": [
|
|
||||||
467.4615173339844,
|
|
||||||
985.1439819335938
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
379.4292297363281,
|
|
||||||
88
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 4,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": [
|
|
||||||
"Option 2: UPLOAD THE MASK AS OTHER IMAGE (useful if you require the image that is below the mask to do inpainting, in this case to generate new glasses)"
|
|
||||||
],
|
|
||||||
"color": "#432",
|
|
||||||
"bgcolor": "#653"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 22,
|
|
||||||
"type": "ComfyUIDeployExternalImage",
|
|
||||||
"pos": [
|
|
||||||
910.8199462890625,
|
|
||||||
1132.306396484375
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
390.5999755859375,
|
|
||||||
154
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 7,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "default_value",
|
|
||||||
"shape": 7,
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 17
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "image",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
22,
|
|
||||||
23
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfyui-deploy",
|
|
||||||
"ver": "cd3a2ff5471828f9c840e746551592e882c05aa4",
|
|
||||||
"Node name for S&R": "ComfyUIDeployExternalImage"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
"input_image",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 23,
|
|
||||||
"type": "ComfyUIDeployExternalImage",
|
|
||||||
"pos": [
|
|
||||||
843.6348876953125,
|
|
||||||
1467.8876953125
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
390.5999755859375,
|
|
||||||
154
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 6,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "default_value",
|
|
||||||
"shape": 7,
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 18
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "image",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
19
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfyui-deploy",
|
|
||||||
"ver": "cd3a2ff5471828f9c840e746551592e882c05aa4",
|
|
||||||
"Node name for S&R": "ComfyUIDeployExternalImage"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
"input_image_mask",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 12,
|
|
||||||
"type": "ComfyUIDeployExternalImageAlpha",
|
|
||||||
"pos": [
|
|
||||||
1107.891357421875,
|
|
||||||
418.2679138183594
|
|
||||||
],
|
|
||||||
"size": [
|
|
||||||
466.1999816894531,
|
|
||||||
200
|
|
||||||
],
|
|
||||||
"flags": {},
|
|
||||||
"order": 8,
|
|
||||||
"mode": 0,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "default_value",
|
|
||||||
"shape": 7,
|
|
||||||
"type": "IMAGE",
|
|
||||||
"link": 11
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "image",
|
|
||||||
"type": "IMAGE",
|
|
||||||
"links": [
|
|
||||||
13
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"cnr_id": "comfyui-deploy",
|
|
||||||
"ver": "cd3a2ff5471828f9c840e746551592e882c05aa4",
|
|
||||||
"Node name for S&R": "ComfyUIDeployExternalImageAlpha"
|
|
||||||
},
|
|
||||||
"widgets_values": [
|
|
||||||
"input_image_alpha",
|
|
||||||
"",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"links": [
|
|
||||||
[
|
|
||||||
10,
|
|
||||||
10,
|
|
||||||
0,
|
|
||||||
11,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
11,
|
|
||||||
11,
|
|
||||||
0,
|
|
||||||
12,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
12,
|
|
||||||
10,
|
|
||||||
1,
|
|
||||||
11,
|
|
||||||
1,
|
|
||||||
"MASK"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
13,
|
|
||||||
12,
|
|
||||||
0,
|
|
||||||
13,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
14,
|
|
||||||
13,
|
|
||||||
0,
|
|
||||||
14,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
15,
|
|
||||||
13,
|
|
||||||
1,
|
|
||||||
17,
|
|
||||||
0,
|
|
||||||
"MASK"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
16,
|
|
||||||
17,
|
|
||||||
0,
|
|
||||||
15,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
17,
|
|
||||||
20,
|
|
||||||
0,
|
|
||||||
22,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
18,
|
|
||||||
21,
|
|
||||||
0,
|
|
||||||
23,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
19,
|
|
||||||
23,
|
|
||||||
0,
|
|
||||||
24,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
21,
|
|
||||||
25,
|
|
||||||
0,
|
|
||||||
26,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
22,
|
|
||||||
22,
|
|
||||||
0,
|
|
||||||
27,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
23,
|
|
||||||
22,
|
|
||||||
0,
|
|
||||||
28,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
24,
|
|
||||||
24,
|
|
||||||
0,
|
|
||||||
28,
|
|
||||||
2,
|
|
||||||
"MASK"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
25,
|
|
||||||
13,
|
|
||||||
0,
|
|
||||||
29,
|
|
||||||
0,
|
|
||||||
"IMAGE"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
26,
|
|
||||||
13,
|
|
||||||
1,
|
|
||||||
29,
|
|
||||||
2,
|
|
||||||
"MASK"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
28,
|
|
||||||
24,
|
|
||||||
0,
|
|
||||||
25,
|
|
||||||
0,
|
|
||||||
"MASK"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"groups": [],
|
|
||||||
"config": {},
|
|
||||||
"extra": {
|
|
||||||
"ds": {
|
|
||||||
"scale": 0.9646149645000013,
|
|
||||||
"offset": [
|
|
||||||
48.66905973637718,
|
|
||||||
-817.5683540167485
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"VHS_latentpreview": false,
|
|
||||||
"VHS_latentpreviewrate": 0,
|
|
||||||
"VHS_MetadataImage": true,
|
|
||||||
"VHS_KeepIntermediate": true
|
|
||||||
},
|
|
||||||
"version": 0.4
|
|
||||||
}
|
|
||||||
@@ -1,359 +0,0 @@
|
|||||||
{
|
|
||||||
"extra": {
|
|
||||||
"ds": {
|
|
||||||
"scale": 0.6010518407212623,
|
|
||||||
"offset": [815.5938895649746, 84.94304700477853]
|
|
||||||
},
|
|
||||||
"node_versions": {
|
|
||||||
"comfy-core": "0.3.19",
|
|
||||||
"comfyui-deploy": "b3df94d1affcf7ce05ee7eeda99989194bcd9159"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"links": [
|
|
||||||
[9, 8, 0, 9, 0, "IMAGE"],
|
|
||||||
[45, 30, 1, 6, 0, "CLIP"],
|
|
||||||
[46, 30, 2, 8, 1, "VAE"],
|
|
||||||
[47, 30, 0, 31, 0, "MODEL"],
|
|
||||||
[51, 27, 0, 31, 3, "LATENT"],
|
|
||||||
[52, 31, 0, 8, 0, "LATENT"],
|
|
||||||
[54, 30, 1, 33, 0, "CLIP"],
|
|
||||||
[55, 33, 0, 31, 2, "CONDITIONING"],
|
|
||||||
[56, 6, 0, 35, 0, "CONDITIONING"],
|
|
||||||
[57, 35, 0, 31, 1, "CONDITIONING"],
|
|
||||||
[58, 38, 0, 6, 1, "STRING"],
|
|
||||||
[59, 40, 0, 27, 0, "INT"],
|
|
||||||
[60, 39, 0, 27, 1, "INT"]
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"pos": [384, 192],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [422.8500061035156, 164.30999755859375],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#232",
|
|
||||||
"flags": {},
|
|
||||||
"order": 7,
|
|
||||||
"title": "CLIP Text Encode (Positive Prompt)",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 45, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 58,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#353",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [56],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"cute anime girl with massive fluffy fennec ears and a big fluffy tail blonde messy long hair blue eyes wearing a maid outfit with a long black gold leaf pattern dress and a white apron mouth open placing a fancy black forest cake with candles on top of a dinner table of an old dark Victorian mansion lit by candlelight with a bright window to the foggy forest and very expensive stuff everywhere there are paintings on the walls"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"pos": [1151, 195],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 46],
|
|
||||||
"type": "VAEDecode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 11,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 52, "name": "samples", "type": "LATENT" },
|
|
||||||
{ "link": 46, "name": "vae", "type": "VAE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "IMAGE", "type": "IMAGE", "links": [9], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAEDecode" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 9,
|
|
||||||
"pos": [1375, 194],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [985.2999877929688, 1060.3800048828125],
|
|
||||||
"type": "SaveImage",
|
|
||||||
"flags": {},
|
|
||||||
"order": 12,
|
|
||||||
"inputs": [{ "link": 9, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": ["ComfyUI"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 31,
|
|
||||||
"pos": [816, 192],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 262],
|
|
||||||
"type": "KSampler",
|
|
||||||
"flags": {},
|
|
||||||
"order": 10,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 47, "name": "model", "type": "MODEL" },
|
|
||||||
{ "link": 57, "name": "positive", "type": "CONDITIONING" },
|
|
||||||
{ "link": 55, "name": "negative", "type": "CONDITIONING" },
|
|
||||||
{ "link": 51, "name": "latent_image", "type": "LATENT" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "LATENT",
|
|
||||||
"type": "LATENT",
|
|
||||||
"links": [52],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "KSampler" },
|
|
||||||
"widgets_values": [
|
|
||||||
1024035737089801,
|
|
||||||
"randomize",
|
|
||||||
20,
|
|
||||||
1,
|
|
||||||
"euler",
|
|
||||||
"simple",
|
|
||||||
1
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 35,
|
|
||||||
"pos": [576, 96],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [211.60000610351562, 58],
|
|
||||||
"type": "FluxGuidance",
|
|
||||||
"flags": {},
|
|
||||||
"order": 9,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 56, "name": "conditioning", "type": "CONDITIONING" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [57],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "FluxGuidance" },
|
|
||||||
"widgets_values": [3.5]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 37,
|
|
||||||
"pos": [60, 345],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [225, 88],
|
|
||||||
"type": "MarkdownNote",
|
|
||||||
"color": "#432",
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#653",
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": [
|
|
||||||
"🛈 [Learn more about this workflow](https://comfyanonymous.github.io/ComfyUI_examples/flux/#flux-dev-1)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 34,
|
|
||||||
"pos": [825, 510],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [282.8599853515625, 164.0800018310547],
|
|
||||||
"type": "Note",
|
|
||||||
"color": "#432",
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#653",
|
|
||||||
"outputs": [],
|
|
||||||
"properties": { "text": "" },
|
|
||||||
"widgets_values": [
|
|
||||||
"Note that Flux dev and schnell do not have any negative prompt so CFG should be set to 1.0. Setting CFG to 1.0 means the negative prompt is ignored."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 30,
|
|
||||||
"pos": [48, 192],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 98],
|
|
||||||
"type": "CheckpointLoaderSimple",
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "MODEL",
|
|
||||||
"type": "MODEL",
|
|
||||||
"links": [47],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CLIP",
|
|
||||||
"type": "CLIP",
|
|
||||||
"links": [45, 54],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "VAE",
|
|
||||||
"type": "VAE",
|
|
||||||
"links": [46],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CheckpointLoaderSimple" },
|
|
||||||
"widgets_values": ["FLUX1/flux1-dev-fp8.safetensors"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 33,
|
|
||||||
"pos": [390, 400],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [422.8500061035156, 164.30999755859375],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#322",
|
|
||||||
"flags": { "collapsed": true },
|
|
||||||
"order": 6,
|
|
||||||
"title": "CLIP Text Encode (Negative Prompt)",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 54, "name": "clip", "type": "CLIP", "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"bgcolor": "#533",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [55],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [""]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 27,
|
|
||||||
"pos": [461.8629455566406, 460.2491149902344],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 126],
|
|
||||||
"type": "EmptySD3LatentImage",
|
|
||||||
"color": "#323",
|
|
||||||
"flags": {},
|
|
||||||
"order": 8,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"pos": [10, 60],
|
|
||||||
"link": 59,
|
|
||||||
"name": "height",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "height" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 60,
|
|
||||||
"name": "width",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "width" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#535",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "LATENT",
|
|
||||||
"type": "LATENT",
|
|
||||||
"links": [51],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "EmptySD3LatentImage" },
|
|
||||||
"widgets_values": [1024, 1024, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 38,
|
|
||||||
"pos": [-497.3238525390625, 306.5517578125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 3,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [58] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"prompt",
|
|
||||||
"cute anime girl with massive fluffy fennec ears and a big fluffy tail blonde messy long hair blue eyes wearing a maid outfit with a long black gold leaf pattern dress and a white apron mouth open placing a fancy black forest cake with candles on top of a dinner table of an old dark Victorian mansion lit by candlelight with a bright window to the foggy forest and very expensive stuff everywhere there are paintings on the walls",
|
|
||||||
"Prompt",
|
|
||||||
"The prompt to generate an image from."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 39,
|
|
||||||
"pos": [-507.4543762207031, 612.9552001953125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 4,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [60], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["width", 1024, "Width", "The width of the image."]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 40,
|
|
||||||
"pos": [-497.8695068359375, 864.68994140625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 5,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [59], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["height", 1024, "Height", "The height of the image."]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {},
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"color": "#3f789e",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Input",
|
|
||||||
"bounding": [
|
|
||||||
-508.010986328125, 186.76593017578125, 453.23040771484375,
|
|
||||||
334.3218994140625
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"color": "#A88",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Additional",
|
|
||||||
"bounding": [
|
|
||||||
-517.1227416992188, 537.53759765625, 644.4954223632812,
|
|
||||||
599.2609252929688
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 0.4,
|
|
||||||
"last_link_id": 60,
|
|
||||||
"last_node_id": 40
|
|
||||||
}
|
|
||||||
@@ -1,423 +0,0 @@
|
|||||||
{
|
|
||||||
"extra": {
|
|
||||||
"ds": {
|
|
||||||
"scale": 0.6830134553650709,
|
|
||||||
"offset": [750.2474149300585, 120.48924647647146]
|
|
||||||
},
|
|
||||||
"node_versions": {
|
|
||||||
"comfy-core": "0.3.19",
|
|
||||||
"comfyui-deploy": "171a227856bd5f31e97828d89f83f3741004d05e"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"links": [
|
|
||||||
[9, 8, 0, 9, 0, "IMAGE"],
|
|
||||||
[10, 11, 0, 6, 0, "CLIP"],
|
|
||||||
[12, 10, 0, 8, 1, "VAE"],
|
|
||||||
[19, 16, 0, 13, 2, "SAMPLER"],
|
|
||||||
[20, 17, 0, 13, 3, "SIGMAS"],
|
|
||||||
[23, 5, 0, 13, 4, "LATENT"],
|
|
||||||
[24, 13, 0, 8, 0, "LATENT"],
|
|
||||||
[30, 22, 0, 13, 1, "GUIDER"],
|
|
||||||
[37, 25, 0, 13, 0, "NOISE"],
|
|
||||||
[38, 12, 0, 17, 0, "MODEL"],
|
|
||||||
[39, 12, 0, 22, 0, "MODEL"],
|
|
||||||
[40, 6, 0, 22, 1, "CONDITIONING"],
|
|
||||||
[41, 28, 0, 6, 1, "STRING"],
|
|
||||||
[44, 29, 0, 5, 0, "INT"],
|
|
||||||
[45, 30, 0, 5, 1, "INT"]
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 13,
|
|
||||||
"pos": [842, 215],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [355.20001220703125, 106],
|
|
||||||
"type": "SamplerCustomAdvanced",
|
|
||||||
"flags": {},
|
|
||||||
"order": 14,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 37, "name": "noise", "type": "NOISE", "slot_index": 0 },
|
|
||||||
{ "link": 30, "name": "guider", "type": "GUIDER", "slot_index": 1 },
|
|
||||||
{ "link": 19, "name": "sampler", "type": "SAMPLER", "slot_index": 2 },
|
|
||||||
{ "link": 20, "name": "sigmas", "type": "SIGMAS", "slot_index": 3 },
|
|
||||||
{
|
|
||||||
"link": 23,
|
|
||||||
"name": "latent_image",
|
|
||||||
"type": "LATENT",
|
|
||||||
"slot_index": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "output",
|
|
||||||
"type": "LATENT",
|
|
||||||
"links": [24],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "denoised_output",
|
|
||||||
"type": "LATENT",
|
|
||||||
"links": null,
|
|
||||||
"shape": 3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "SamplerCustomAdvanced" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"pos": [1248, 192],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 46],
|
|
||||||
"type": "VAEDecode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 15,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 24, "name": "samples", "type": "LATENT" },
|
|
||||||
{ "link": 12, "name": "vae", "type": "VAE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "IMAGE", "type": "IMAGE", "links": [9], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAEDecode" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 22,
|
|
||||||
"pos": [559, 125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [241.79998779296875, 46],
|
|
||||||
"type": "BasicGuider",
|
|
||||||
"flags": {},
|
|
||||||
"order": 13,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 39, "name": "model", "type": "MODEL", "slot_index": 0 },
|
|
||||||
{
|
|
||||||
"link": 40,
|
|
||||||
"name": "conditioning",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"slot_index": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "GUIDER",
|
|
||||||
"type": "GUIDER",
|
|
||||||
"links": [30],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "BasicGuider" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 16,
|
|
||||||
"pos": [480, 720],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 58],
|
|
||||||
"type": "KSamplerSelect",
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "SAMPLER", "type": "SAMPLER", "links": [19], "shape": 3 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "KSamplerSelect" },
|
|
||||||
"widgets_values": ["euler"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 17,
|
|
||||||
"pos": [480, 816],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 106],
|
|
||||||
"type": "BasicScheduler",
|
|
||||||
"flags": {},
|
|
||||||
"order": 10,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 38, "name": "model", "type": "MODEL", "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "SIGMAS", "type": "SIGMAS", "links": [20], "shape": 3 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "BasicScheduler" },
|
|
||||||
"widgets_values": ["simple", 4, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 27,
|
|
||||||
"pos": [480, 960],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [311.3529052734375, 131.16229248046875],
|
|
||||||
"type": "Note",
|
|
||||||
"color": "#432",
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#653",
|
|
||||||
"outputs": [],
|
|
||||||
"properties": { "text": "" },
|
|
||||||
"widgets_values": [
|
|
||||||
"The schnell model is a distilled model that can generate a good image with only 4 steps."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 9,
|
|
||||||
"pos": [1488, 192],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [985.3012084960938, 1060.3828125],
|
|
||||||
"type": "SaveImage",
|
|
||||||
"flags": {},
|
|
||||||
"order": 16,
|
|
||||||
"inputs": [{ "link": 9, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": ["ComfyUI"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 25,
|
|
||||||
"pos": [480, 587.7890625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 82],
|
|
||||||
"type": "RandomNoise",
|
|
||||||
"color": "#2a363b",
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#3f5159",
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "NOISE", "type": "NOISE", "links": [37], "shape": 3 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "RandomNoise" },
|
|
||||||
"widgets_values": [393845863554716, "randomize"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"pos": [471.7746276855469, 423.91571044921875],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 126],
|
|
||||||
"type": "EmptyLatentImage",
|
|
||||||
"color": "#323",
|
|
||||||
"flags": {},
|
|
||||||
"order": 12,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 44,
|
|
||||||
"name": "width",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "width" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pos": [10, 60],
|
|
||||||
"link": 45,
|
|
||||||
"name": "height",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "height" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#535",
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "LATENT", "type": "LATENT", "links": [23], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "EmptyLatentImage" },
|
|
||||||
"widgets_values": [1024, 1024, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 26,
|
|
||||||
"pos": [41.60395812988281, 517.059326171875],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [336, 288],
|
|
||||||
"type": "Note",
|
|
||||||
"color": "#432",
|
|
||||||
"flags": {},
|
|
||||||
"order": 3,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#653",
|
|
||||||
"outputs": [],
|
|
||||||
"properties": { "text": "" },
|
|
||||||
"widgets_values": [
|
|
||||||
"If you get an error in any of the nodes above make sure the files are in the correct directories.\n\nSee the top of the examples page for the links : https://comfyanonymous.github.io/ComfyUI_examples/flux/\n\nflux1-schnell.safetensors goes in: ComfyUI/models/unet/\n\nt5xxl_fp16.safetensors and clip_l.safetensors go in: ComfyUI/models/clip/\n\nae.safetensors goes in: ComfyUI/models/vae/\n\n\nTip: You can set the weight_dtype above to one of the fp8 types if you have memory issues."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"pos": [45.584651947021484, 229.13525390625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 122],
|
|
||||||
"type": "DualCLIPLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 4,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CLIP",
|
|
||||||
"type": "CLIP",
|
|
||||||
"links": [10],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "DualCLIPLoader" },
|
|
||||||
"widgets_values": [
|
|
||||||
"t5xxl_fp16.safetensors",
|
|
||||||
"clip_l.safetensors",
|
|
||||||
"flux",
|
|
||||||
"default"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 12,
|
|
||||||
"pos": [45.92215347290039, 95.6536865234375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 82],
|
|
||||||
"type": "UNETLoader",
|
|
||||||
"color": "#223",
|
|
||||||
"flags": { "pinned": true },
|
|
||||||
"order": 5,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#335",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "MODEL",
|
|
||||||
"type": "MODEL",
|
|
||||||
"links": [38, 39],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "UNETLoader" },
|
|
||||||
"widgets_values": ["flux1-schnell.safetensors", "default"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"pos": [385.87054443359375, 216.75625610351562],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [422.84503173828125, 164.31304931640625],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#232",
|
|
||||||
"flags": {},
|
|
||||||
"order": 11,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 10, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 41,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#353",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [40],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"a bottle with a beautiful rainbow galaxy inside it on top of a wooden table in the middle of a modern kitchen beside a plate of vegetables and mushrooms and a wine glasse that contains a planet earth with a plate with a half eaten apple pie on it"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10,
|
|
||||||
"pos": [42.45906066894531, 405.2187805175781],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 58],
|
|
||||||
"type": "VAELoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 6,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "VAE",
|
|
||||||
"type": "VAE",
|
|
||||||
"links": [12],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAELoader" },
|
|
||||||
"widgets_values": ["ae.sft"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 28,
|
|
||||||
"pos": [-620.3922119140625, 199.8013916015625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 7,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [41] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"prompt",
|
|
||||||
"a bottle with a beautiful rainbow galaxy inside it on top of a wooden table in the middle of a modern kitchen beside a plate of vegetables and mushrooms and a wine glasse that contains a planet earth with a plate with a half eaten apple pie on it",
|
|
||||||
"Prompt",
|
|
||||||
"The prompt to generate an image from."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 29,
|
|
||||||
"pos": [-677.4290161132812, 597.3389282226562],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 8,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [44], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["width", 1024, "Width", "The width of the image."]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 30,
|
|
||||||
"pos": [-670.0703735351562, 848.3707885742188],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 9,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [45], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["height", 1024, "Height", "The height of the image."]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {},
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"color": "#3f789e",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Input",
|
|
||||||
"bounding": [
|
|
||||||
-652.184326171875, 99.11231994628906, 565.7923583984375,
|
|
||||||
362.8800354003906
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"color": "#A88",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Additional",
|
|
||||||
"bounding": [
|
|
||||||
-720.3274536132812, 508.1206970214844, 703.0422973632812,
|
|
||||||
576.5584716796875
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 0.4,
|
|
||||||
"last_link_id": 45,
|
|
||||||
"last_node_id": 30
|
|
||||||
}
|
|
||||||
@@ -1,482 +0,0 @@
|
|||||||
{
|
|
||||||
"extra": {
|
|
||||||
"ds": {
|
|
||||||
"scale": 0.6830134553650709,
|
|
||||||
"offset": [1030.9627343190857, 159.73178253107423]
|
|
||||||
},
|
|
||||||
"groupNodes": {},
|
|
||||||
"node_versions": {
|
|
||||||
"comfy-core": "0.3.12",
|
|
||||||
"comfyui-deploy": "b3df94d1affcf7ce05ee7eeda99989194bcd9159"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"links": [
|
|
||||||
[19, 16, 0, 13, 2, "SAMPLER"],
|
|
||||||
[20, 17, 0, 13, 3, "SIGMAS"],
|
|
||||||
[30, 22, 0, 13, 1, "GUIDER"],
|
|
||||||
[37, 25, 0, 13, 0, "NOISE"],
|
|
||||||
[129, 26, 0, 22, 1, "CONDITIONING"],
|
|
||||||
[175, 44, 0, 26, 0, "CONDITIONING"],
|
|
||||||
[180, 45, 0, 13, 4, "LATENT"],
|
|
||||||
[181, 13, 0, 8, 0, "LATENT"],
|
|
||||||
[190, 12, 0, 17, 0, "MODEL"],
|
|
||||||
[195, 67, 0, 22, 0, "MODEL"],
|
|
||||||
[205, 11, 0, 44, 0, "CLIP"],
|
|
||||||
[206, 10, 0, 8, 1, "VAE"],
|
|
||||||
[209, 12, 0, 67, 0, "MODEL"],
|
|
||||||
[210, 13, 0, 73, 0, "LATENT"],
|
|
||||||
[211, 10, 0, 73, 1, "VAE"],
|
|
||||||
[215, 73, 0, 75, 0, "IMAGE"],
|
|
||||||
[216, 78, 0, 44, 1, "STRING"],
|
|
||||||
[217, 79, 0, 45, 0, "INT"],
|
|
||||||
[218, 83, 0, 45, 1, "INT"]
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 16,
|
|
||||||
"pos": [484, 751],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 58],
|
|
||||||
"type": "KSamplerSelect",
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "SAMPLER", "type": "SAMPLER", "links": [19], "shape": 3 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "KSamplerSelect" },
|
|
||||||
"widgets_values": ["euler"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 17,
|
|
||||||
"pos": [478, 860],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 106],
|
|
||||||
"type": "BasicScheduler",
|
|
||||||
"flags": {},
|
|
||||||
"order": 10,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 190, "name": "model", "type": "MODEL", "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "SIGMAS", "type": "SIGMAS", "links": [20], "shape": 3 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "BasicScheduler" },
|
|
||||||
"widgets_values": ["simple", 20, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 26,
|
|
||||||
"pos": [520, 100],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [317.4000244140625, 58],
|
|
||||||
"type": "FluxGuidance",
|
|
||||||
"color": "#233",
|
|
||||||
"flags": {},
|
|
||||||
"order": 14,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 175, "name": "conditioning", "type": "CONDITIONING" }
|
|
||||||
],
|
|
||||||
"bgcolor": "#355",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [129],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "FluxGuidance" },
|
|
||||||
"widgets_values": [6]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 45,
|
|
||||||
"pos": [475.540771484375, 432.673583984375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 130],
|
|
||||||
"type": "EmptyHunyuanLatentVideo",
|
|
||||||
"flags": {},
|
|
||||||
"order": 13,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"link": 217,
|
|
||||||
"name": "width",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "width" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"link": 218,
|
|
||||||
"name": "height",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "height" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "LATENT", "type": "LATENT", "links": [180], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "EmptyHunyuanLatentVideo" },
|
|
||||||
"widgets_values": [848, 480, 73, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 22,
|
|
||||||
"pos": [600, 0],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [222.3482666015625, 46],
|
|
||||||
"type": "BasicGuider",
|
|
||||||
"flags": {},
|
|
||||||
"order": 15,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 195, "name": "model", "type": "MODEL", "slot_index": 0 },
|
|
||||||
{
|
|
||||||
"link": 129,
|
|
||||||
"name": "conditioning",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"slot_index": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "GUIDER",
|
|
||||||
"type": "GUIDER",
|
|
||||||
"links": [30],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "BasicGuider" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 67,
|
|
||||||
"pos": [360, 0],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 58],
|
|
||||||
"type": "ModelSamplingSD3",
|
|
||||||
"flags": {},
|
|
||||||
"order": 11,
|
|
||||||
"inputs": [{ "link": 209, "name": "model", "type": "MODEL" }],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "MODEL", "type": "MODEL", "links": [195], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ModelSamplingSD3" },
|
|
||||||
"widgets_values": [7]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 73,
|
|
||||||
"pos": [1150, 200],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 150],
|
|
||||||
"type": "VAEDecodeTiled",
|
|
||||||
"flags": {},
|
|
||||||
"order": 18,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 210, "name": "samples", "type": "LATENT" },
|
|
||||||
{ "link": 211, "name": "vae", "type": "VAE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "IMAGE", "type": "IMAGE", "links": [215], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAEDecodeTiled" },
|
|
||||||
"widgets_values": [256, 64, 64, 8]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"pos": [1150, 90],
|
|
||||||
"mode": 2,
|
|
||||||
"size": [210, 46],
|
|
||||||
"type": "VAEDecode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 17,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 181, "name": "samples", "type": "LATENT" },
|
|
||||||
{ "link": 206, "name": "vae", "type": "VAE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "IMAGE", "type": "IMAGE", "links": [], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAEDecode" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 77,
|
|
||||||
"pos": [0, 0],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [350, 110],
|
|
||||||
"type": "Note",
|
|
||||||
"color": "#432",
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#653",
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": [
|
|
||||||
"Select a fp8 weight_dtype if you are running out of memory."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 13,
|
|
||||||
"pos": [860, 200],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [272.3617858886719, 124.53733825683594],
|
|
||||||
"type": "SamplerCustomAdvanced",
|
|
||||||
"flags": {},
|
|
||||||
"order": 16,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 37, "name": "noise", "type": "NOISE", "slot_index": 0 },
|
|
||||||
{ "link": 30, "name": "guider", "type": "GUIDER", "slot_index": 1 },
|
|
||||||
{ "link": 19, "name": "sampler", "type": "SAMPLER", "slot_index": 2 },
|
|
||||||
{ "link": 20, "name": "sigmas", "type": "SIGMAS", "slot_index": 3 },
|
|
||||||
{
|
|
||||||
"link": 180,
|
|
||||||
"name": "latent_image",
|
|
||||||
"type": "LATENT",
|
|
||||||
"slot_index": 4
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "output",
|
|
||||||
"type": "LATENT",
|
|
||||||
"links": [181, 210],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "denoised_output",
|
|
||||||
"type": "LATENT",
|
|
||||||
"links": null,
|
|
||||||
"shape": 3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "SamplerCustomAdvanced" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 75,
|
|
||||||
"pos": [1410, 200],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 366],
|
|
||||||
"type": "SaveAnimatedWEBP",
|
|
||||||
"flags": {},
|
|
||||||
"order": 19,
|
|
||||||
"inputs": [{ "link": 215, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": ["ComfyUI", 24, false, 80, "default"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 25,
|
|
||||||
"pos": [479, 618],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 82],
|
|
||||||
"type": "RandomNoise",
|
|
||||||
"color": "#2a363b",
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#3f5159",
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "NOISE", "type": "NOISE", "links": [37], "shape": 3 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "RandomNoise" },
|
|
||||||
"widgets_values": [1, "randomize"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 12,
|
|
||||||
"pos": [0, 150],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [350, 82],
|
|
||||||
"type": "UNETLoader",
|
|
||||||
"color": "#223",
|
|
||||||
"flags": {},
|
|
||||||
"order": 3,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#335",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "MODEL",
|
|
||||||
"type": "MODEL",
|
|
||||||
"links": [190, 209],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "UNETLoader" },
|
|
||||||
"widgets_values": ["hunyuan_video_t2v_720p_bf16.safetensors", "default"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10,
|
|
||||||
"pos": [0, 420],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [350, 60],
|
|
||||||
"type": "VAELoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 4,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "VAE",
|
|
||||||
"type": "VAE",
|
|
||||||
"links": [206, 211],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAELoader" },
|
|
||||||
"widgets_values": ["hunyuan_video_vae_bf16.safetensors"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"pos": [0, 270],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [350, 106],
|
|
||||||
"type": "DualCLIPLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 5,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CLIP",
|
|
||||||
"type": "CLIP",
|
|
||||||
"links": [205],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "DualCLIPLoader" },
|
|
||||||
"widgets_values": [
|
|
||||||
"clip_l.safetensors",
|
|
||||||
"llava_llama3_fp8_scaled.safetensors",
|
|
||||||
"hunyuan_video",
|
|
||||||
"default"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 44,
|
|
||||||
"pos": [459.0518798828125, 226.60147094726562],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [285.6000061035156, 54],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#232",
|
|
||||||
"flags": {},
|
|
||||||
"order": 12,
|
|
||||||
"title": "CLIP Text Encode (Positive Prompt)",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 205, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"link": 216,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#353",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [175],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"anime style anime girl with massive fennec ears and one big fluffy tail, she has blonde hair long hair blue eyes wearing a pink sweater and a long blue skirt walking in a beautiful outdoor scenery with snow mountains in the background"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 83,
|
|
||||||
"pos": [-591.1870727539062, 751.6737670898438],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 6,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [218], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["height", 480, "Height", "The height of the video."]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 74,
|
|
||||||
"pos": [1151.89599609375, 402.439697265625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 170],
|
|
||||||
"type": "Note",
|
|
||||||
"color": "#432",
|
|
||||||
"flags": {},
|
|
||||||
"order": 7,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#653",
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": [
|
|
||||||
"Use the tiled decode node by default because most people will need it.\n\nLower the tile_size and overlap if you run out of memory."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 78,
|
|
||||||
"pos": [-560.058837890625, 155.3986358642578],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 8,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [216] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"prompt",
|
|
||||||
"anime style anime girl with massive fennec ears and one big fluffy tail, she has blonde hair long hair blue eyes wearing a pink sweater and a long blue skirt walking in a beautiful outdoor scenery with snow mountains in the background",
|
|
||||||
"Prompt",
|
|
||||||
"The prompt to generate the video from."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 79,
|
|
||||||
"pos": [-588.2138061523438, 493.3861389160156],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 9,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [217], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["width", 848, "Width", "The width of the video."]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {},
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"color": "#3f789e",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Input",
|
|
||||||
"bounding": [
|
|
||||||
-662.9779052734375, 14.93773078918457, 575.2218627929688,
|
|
||||||
384.41424560546875
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"color": "#b06634",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Additional",
|
|
||||||
"bounding": [
|
|
||||||
-659.7621459960938, 414.3213195800781, 570.7182006835938,
|
|
||||||
594.72216796875
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 0.4,
|
|
||||||
"last_link_id": 218,
|
|
||||||
"last_node_id": 83
|
|
||||||
}
|
|
||||||
@@ -1,240 +0,0 @@
|
|||||||
{
|
|
||||||
"extra": {
|
|
||||||
"ds": { "scale": 1, "offset": { "0": 0, "1": 0 } },
|
|
||||||
"node_versions": {
|
|
||||||
"comfy-core": "0.3.12",
|
|
||||||
"comfyui-deploy": "171a227856bd5f31e97828d89f83f3741004d05e"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"links": [
|
|
||||||
[1, 4, 0, 3, 0, "MODEL"],
|
|
||||||
[2, 5, 0, 3, 3, "LATENT"],
|
|
||||||
[3, 4, 1, 6, 0, "CLIP"],
|
|
||||||
[4, 6, 0, 3, 1, "CONDITIONING"],
|
|
||||||
[5, 4, 1, 7, 0, "CLIP"],
|
|
||||||
[6, 7, 0, 3, 2, "CONDITIONING"],
|
|
||||||
[7, 3, 0, 8, 0, "LATENT"],
|
|
||||||
[8, 4, 2, 8, 1, "VAE"],
|
|
||||||
[9, 8, 0, 9, 0, "IMAGE"],
|
|
||||||
[10, 12, 0, 6, 1, "STRING"],
|
|
||||||
[11, 13, 0, 7, 1, "STRING"]
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"pos": [473, 609],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 106],
|
|
||||||
"type": "EmptyLatentImage",
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "LATENT", "type": "LATENT", "links": [2], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "EmptyLatentImage" },
|
|
||||||
"widgets_values": [512, 512, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"pos": [863, 186],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 262],
|
|
||||||
"type": "KSampler",
|
|
||||||
"flags": {},
|
|
||||||
"order": 7,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 1, "name": "model", "type": "MODEL" },
|
|
||||||
{ "link": 4, "name": "positive", "type": "CONDITIONING" },
|
|
||||||
{ "link": 6, "name": "negative", "type": "CONDITIONING" },
|
|
||||||
{ "link": 2, "name": "latent_image", "type": "LATENT" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "LATENT", "type": "LATENT", "links": [7], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "KSampler" },
|
|
||||||
"widgets_values": [
|
|
||||||
156680208700286,
|
|
||||||
"randomize",
|
|
||||||
20,
|
|
||||||
8,
|
|
||||||
"euler",
|
|
||||||
"normal",
|
|
||||||
1
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"pos": [1209, 188],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 46],
|
|
||||||
"type": "VAEDecode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 8,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 7, "name": "samples", "type": "LATENT" },
|
|
||||||
{ "link": 8, "name": "vae", "type": "VAE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "IMAGE", "type": "IMAGE", "links": [9], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAEDecode" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 9,
|
|
||||||
"pos": [1451, 189],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 58],
|
|
||||||
"type": "SaveImage",
|
|
||||||
"flags": {},
|
|
||||||
"order": 9,
|
|
||||||
"inputs": [{ "link": 9, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": ["ComfyUI"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"pos": [26, 474],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 98],
|
|
||||||
"type": "CheckpointLoaderSimple",
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "MODEL", "type": "MODEL", "links": [1], "slot_index": 0 },
|
|
||||||
{ "name": "CLIP", "type": "CLIP", "links": [3, 5], "slot_index": 1 },
|
|
||||||
{ "name": "VAE", "type": "VAE", "links": [8], "slot_index": 2 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CheckpointLoaderSimple" },
|
|
||||||
"widgets_values": ["v1-5-pruned-emaonly.ckpt"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"pos": [415, 186],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [422.84503173828125, 164.31304931640625],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 6,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 3, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"link": 10,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [4],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"beautiful scenery nature glass bottle landscape, , purple galaxy bottle,"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 7,
|
|
||||||
"pos": [413, 389],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [425.27801513671875, 180.6060791015625],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 5,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 5, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"link": 11,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [6],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": ["text, watermark"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 13,
|
|
||||||
"pos": [-70, -60],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"links": [11],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": ["negative_prompt", "text, watermark", "", ""]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 12,
|
|
||||||
"pos": [-72, 193],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 3,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"links": [10],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"positive_prompt",
|
|
||||||
"beautiful scenery nature glass bottle landscape, , purple galaxy bottle,",
|
|
||||||
"",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 14,
|
|
||||||
"pos": [419, 23],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 96],
|
|
||||||
"type": "ComfyDeploy",
|
|
||||||
"color": "#432",
|
|
||||||
"flags": {},
|
|
||||||
"order": 4,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#653",
|
|
||||||
"outputs": [],
|
|
||||||
"properties": { "version": "", "workflow_id": "", "workflow_name": "" },
|
|
||||||
"widgets_values": ["", "", "1"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {},
|
|
||||||
"groups": [],
|
|
||||||
"version": 0.4,
|
|
||||||
"last_link_id": 11,
|
|
||||||
"last_node_id": 14
|
|
||||||
}
|
|
||||||
@@ -1,409 +0,0 @@
|
|||||||
{
|
|
||||||
"extra": {
|
|
||||||
"ds": {
|
|
||||||
"scale": 0.620921323059155,
|
|
||||||
"offset": [1535.1422819333457, 285.0502099350181]
|
|
||||||
},
|
|
||||||
"node_versions": {
|
|
||||||
"comfy-core": "0.3.12",
|
|
||||||
"comfyui-deploy": "171a227856bd5f31e97828d89f83f3741004d05e"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"links": [
|
|
||||||
[7, 3, 0, 8, 0, "LATENT"],
|
|
||||||
[21, 16, 0, 3, 1, "CONDITIONING"],
|
|
||||||
[51, 8, 0, 9, 0, "IMAGE"],
|
|
||||||
[53, 4, 2, 8, 1, "VAE"],
|
|
||||||
[80, 40, 0, 3, 2, "CONDITIONING"],
|
|
||||||
[99, 4, 0, 3, 0, "MODEL"],
|
|
||||||
[100, 53, 0, 3, 3, "LATENT"],
|
|
||||||
[103, 43, 0, 16, 0, "CLIP"],
|
|
||||||
[104, 43, 0, 40, 0, "CLIP"],
|
|
||||||
[105, 54, 0, 16, 1, "STRING"],
|
|
||||||
[106, 55, 0, 40, 1, "STRING"],
|
|
||||||
[107, 56, 0, 53, 0, "INT"],
|
|
||||||
[108, 57, 0, 53, 1, "INT"]
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"pos": [1200, 96],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 46],
|
|
||||||
"type": "VAEDecode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 14,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 7, "name": "samples", "type": "LATENT" },
|
|
||||||
{ "link": 53, "name": "vae", "type": "VAE", "slot_index": 1 }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "IMAGE", "type": "IMAGE", "links": [51], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAEDecode" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 9,
|
|
||||||
"pos": [1440, 96],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [952.5112915039062, 1007.9328002929688],
|
|
||||||
"type": "SaveImage",
|
|
||||||
"flags": {},
|
|
||||||
"order": 15,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 51, "name": "images", "type": "IMAGE", "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": ["ComfyUI"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 53,
|
|
||||||
"pos": [480, 576],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 106],
|
|
||||||
"type": "EmptySD3LatentImage",
|
|
||||||
"flags": {},
|
|
||||||
"order": 10,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"link": 107,
|
|
||||||
"name": "width",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "width" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"link": 108,
|
|
||||||
"name": "height",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "height" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "LATENT",
|
|
||||||
"type": "LATENT",
|
|
||||||
"links": [100],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "EmptySD3LatentImage" },
|
|
||||||
"widgets_values": [1024, 1024, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 50,
|
|
||||||
"pos": [-384, 144],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [223.34756469726562, 254.37765502929688],
|
|
||||||
"type": "Note",
|
|
||||||
"color": "#432",
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#653",
|
|
||||||
"outputs": [],
|
|
||||||
"properties": { "text": "" },
|
|
||||||
"widgets_values": [
|
|
||||||
"SD3 supports different text encoder configurations, you can see how to load them here.\n\n\nMake sure to put these files:\nclip_g.safetensors\nclip_l.safetensors\nt5xxl_fp16.safetensors\n\n\nIn the ComfyUI/models/clip directory"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 41,
|
|
||||||
"pos": [-96, 0],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 82],
|
|
||||||
"type": "CLIPLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CLIP",
|
|
||||||
"type": "CLIP",
|
|
||||||
"links": [],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPLoader" },
|
|
||||||
"widgets_values": ["t5xxl_fp16.safetensors", "sd3", "default"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"pos": [-96, 480],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [384.75592041015625, 98],
|
|
||||||
"type": "CheckpointLoaderSimple",
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "MODEL", "type": "MODEL", "links": [99], "slot_index": 0 },
|
|
||||||
{ "name": "CLIP", "type": "CLIP", "links": [], "slot_index": 1 },
|
|
||||||
{ "name": "VAE", "type": "VAE", "links": [53], "slot_index": 2 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CheckpointLoaderSimple" },
|
|
||||||
"widgets_values": ["sd3.5_large.safetensors"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"pos": [864, 96],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 474],
|
|
||||||
"type": "KSampler",
|
|
||||||
"flags": {},
|
|
||||||
"order": 13,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 99, "name": "model", "type": "MODEL", "slot_index": 0 },
|
|
||||||
{ "link": 21, "name": "positive", "type": "CONDITIONING" },
|
|
||||||
{ "link": 80, "name": "negative", "type": "CONDITIONING" },
|
|
||||||
{ "link": 100, "name": "latent_image", "type": "LATENT" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "LATENT", "type": "LATENT", "links": [7], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "KSampler" },
|
|
||||||
"widgets_values": [
|
|
||||||
797639488625463,
|
|
||||||
"randomize",
|
|
||||||
20,
|
|
||||||
5.45,
|
|
||||||
"euler",
|
|
||||||
"sgm_uniform",
|
|
||||||
1
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 51,
|
|
||||||
"pos": [-96, 624],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [384, 192],
|
|
||||||
"type": "Note",
|
|
||||||
"color": "#432",
|
|
||||||
"flags": {},
|
|
||||||
"order": 3,
|
|
||||||
"inputs": [],
|
|
||||||
"bgcolor": "#653",
|
|
||||||
"outputs": [],
|
|
||||||
"properties": { "text": "" },
|
|
||||||
"widgets_values": [
|
|
||||||
"sd3.5_large.safetensors and sd3.5_medium.safetensors are files that do not contain any CLIP/text encoder weights so you need to load them separately.\n\nThey go in the ComfyUI/models/checkpoints directory."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 43,
|
|
||||||
"pos": [-96, 288],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 106],
|
|
||||||
"type": "TripleCLIPLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 4,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CLIP",
|
|
||||||
"type": "CLIP",
|
|
||||||
"links": [103, 104],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "TripleCLIPLoader" },
|
|
||||||
"widgets_values": [
|
|
||||||
"clip_l.safetensors",
|
|
||||||
"clip_g.safetensors",
|
|
||||||
"t5xxl_fp16.safetensors"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 42,
|
|
||||||
"pos": [-96, 144],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 106],
|
|
||||||
"type": "DualCLIPLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 5,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CLIP",
|
|
||||||
"type": "CLIP",
|
|
||||||
"links": [],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "DualCLIPLoader" },
|
|
||||||
"widgets_values": [
|
|
||||||
"clip_l.safetensors",
|
|
||||||
"clip_g.safetensors",
|
|
||||||
"sd3",
|
|
||||||
"default"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 40,
|
|
||||||
"pos": [399.0046081542969, 337.009765625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [397.45977783203125, 151.2898406982422],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#322",
|
|
||||||
"flags": {},
|
|
||||||
"order": 11,
|
|
||||||
"title": "Negative Prompt",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 104, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"link": 106,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#533",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [80],
|
|
||||||
"shape": 3,
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [""]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 16,
|
|
||||||
"pos": [398.5880432128906, 108.27188110351562],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [397.21484375, 158.671875],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#232",
|
|
||||||
"flags": {},
|
|
||||||
"order": 12,
|
|
||||||
"title": "Positive Prompt",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 103, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"link": 105,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#353",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [21],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"a bottle with a rainbow galaxy inside it on top of a wooden table on a snowy mountain top with the ocean and clouds in the background with a shot glass beside containing darkness beside a snow sculpture in the shape of a fox"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 57,
|
|
||||||
"pos": [-1015.1683349609375, 980.396240234375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 6,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [108], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["height", 1024, "Height", "The height of the image. "]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 56,
|
|
||||||
"pos": [-1014.532470703125, 732.8568725585938],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 7,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [107], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["width", 1024, "Width", "The width of the image. "]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 55,
|
|
||||||
"pos": [-1010.8035278320312, 487.404052734375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 8,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [106] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": ["negative_prompt", "", "Negative Prompt", ""]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 54,
|
|
||||||
"pos": [-1059.1072998046875, 127.12823486328125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 9,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [105] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"prompt",
|
|
||||||
"a bottle with a rainbow galaxy inside it on top of a wooden table on a snowy mountain top with the ocean and clouds in the background with a shot glass beside containing darkness beside a snow sculpture in the shape of a fox",
|
|
||||||
"Prompt",
|
|
||||||
"The prompt to generate an image from."
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {},
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"color": "#3f789e",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Different Text Encoder Configurations",
|
|
||||||
"bounding": [-144, -96, 480, 528],
|
|
||||||
"font_size": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"color": "#b06634",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Additional",
|
|
||||||
"bounding": [
|
|
||||||
-1194.5233154296875, 388.3871154785156, 722.5393676757812,
|
|
||||||
824.6746215820312
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"color": "#3f789e",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Input",
|
|
||||||
"bounding": [
|
|
||||||
-1148.487060546875, 30.449382781982422, 552.3358764648438,
|
|
||||||
329.3829040527344
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 0.4,
|
|
||||||
"last_link_id": 108,
|
|
||||||
"last_node_id": 57
|
|
||||||
}
|
|
||||||
@@ -1,452 +0,0 @@
|
|||||||
{
|
|
||||||
"extra": {
|
|
||||||
"ds": {
|
|
||||||
"scale": 0.6934334949441662,
|
|
||||||
"offset": [276.7941771713029, -7.923387380923855]
|
|
||||||
},
|
|
||||||
"node_versions": {
|
|
||||||
"comfy-core": "0.3.18",
|
|
||||||
"comfyui-deploy": "b3df94d1affcf7ce05ee7eeda99989194bcd9159"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"links": [
|
|
||||||
[35, 3, 0, 8, 0, "LATENT"],
|
|
||||||
[56, 8, 0, 28, 0, "IMAGE"],
|
|
||||||
[74, 38, 0, 6, 0, "CLIP"],
|
|
||||||
[75, 38, 0, 7, 0, "CLIP"],
|
|
||||||
[76, 39, 0, 8, 1, "VAE"],
|
|
||||||
[93, 8, 0, 47, 0, "IMAGE"],
|
|
||||||
[94, 49, 0, 51, 0, "CLIP_VISION"],
|
|
||||||
[97, 6, 0, 50, 0, "CONDITIONING"],
|
|
||||||
[98, 7, 0, 50, 1, "CONDITIONING"],
|
|
||||||
[99, 39, 0, 50, 2, "VAE"],
|
|
||||||
[101, 50, 0, 3, 1, "CONDITIONING"],
|
|
||||||
[102, 50, 1, 3, 2, "CONDITIONING"],
|
|
||||||
[103, 50, 2, 3, 3, "LATENT"],
|
|
||||||
[107, 51, 0, 50, 3, "CLIP_VISION_OUTPUT"],
|
|
||||||
[110, 37, 0, 54, 0, "MODEL"],
|
|
||||||
[111, 54, 0, 3, 0, "MODEL"],
|
|
||||||
[112, 55, 0, 6, 1, "STRING"],
|
|
||||||
[113, 56, 0, 7, 1, "STRING"],
|
|
||||||
[115, 57, 0, 50, 4, "IMAGE"],
|
|
||||||
[116, 57, 0, 51, 1, "IMAGE"],
|
|
||||||
[117, 58, 0, 50, 5, "INT"],
|
|
||||||
[118, 59, 0, 50, 6, "INT"]
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"pos": [1210, 190],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 46],
|
|
||||||
"type": "VAEDecode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 15,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 35, "name": "samples", "type": "LATENT" },
|
|
||||||
{ "link": 76, "name": "vae", "type": "VAE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "IMAGE", "type": "IMAGE", "links": [56, 93], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAEDecode" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 39,
|
|
||||||
"pos": [866.3932495117188, 499.18597412109375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [306.36004638671875, 58],
|
|
||||||
"type": "VAELoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "VAE", "type": "VAE", "links": [76, 99], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAELoader" },
|
|
||||||
"widgets_values": ["wan_2.1_vae.safetensors"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 28,
|
|
||||||
"pos": [1460, 190],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [870.8511352539062, 643.7430419921875],
|
|
||||||
"type": "SaveAnimatedWEBP",
|
|
||||||
"flags": {},
|
|
||||||
"order": 16,
|
|
||||||
"inputs": [{ "link": 56, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": ["ComfyUI", 16, false, 90, "default", ""]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 47,
|
|
||||||
"pos": [2367.213134765625, 193.6114959716797],
|
|
||||||
"mode": 4,
|
|
||||||
"size": [315, 130],
|
|
||||||
"type": "SaveWEBM",
|
|
||||||
"flags": {},
|
|
||||||
"order": 17,
|
|
||||||
"inputs": [{ "link": 93, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": { "Node name for S&R": "SaveWEBM" },
|
|
||||||
"widgets_values": ["ComfyUI", "vp9", 24, 32]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 50,
|
|
||||||
"pos": [673.0507202148438, 627.272705078125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [342.5999755859375, 250],
|
|
||||||
"type": "WanImageToVideo",
|
|
||||||
"flags": {},
|
|
||||||
"order": 13,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 97, "name": "positive", "type": "CONDITIONING" },
|
|
||||||
{ "link": 98, "name": "negative", "type": "CONDITIONING" },
|
|
||||||
{ "link": 99, "name": "vae", "type": "VAE" },
|
|
||||||
{
|
|
||||||
"link": 107,
|
|
||||||
"name": "clip_vision_output",
|
|
||||||
"type": "CLIP_VISION_OUTPUT",
|
|
||||||
"shape": 7
|
|
||||||
},
|
|
||||||
{ "link": 115, "name": "start_image", "type": "IMAGE", "shape": 7 },
|
|
||||||
{
|
|
||||||
"pos": [10, 116],
|
|
||||||
"link": 117,
|
|
||||||
"name": "width",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "width" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pos": [10, 140],
|
|
||||||
"link": 118,
|
|
||||||
"name": "height",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "height" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "positive",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [101],
|
|
||||||
"slot_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "negative",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [102],
|
|
||||||
"slot_index": 1
|
|
||||||
},
|
|
||||||
{ "name": "latent", "type": "LATENT", "links": [103], "slot_index": 2 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "WanImageToVideo" },
|
|
||||||
"widgets_values": [512, 512, 33, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"pos": [863, 187],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 262],
|
|
||||||
"type": "KSampler",
|
|
||||||
"flags": {},
|
|
||||||
"order": 14,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 111, "name": "model", "type": "MODEL" },
|
|
||||||
{ "link": 101, "name": "positive", "type": "CONDITIONING" },
|
|
||||||
{ "link": 102, "name": "negative", "type": "CONDITIONING" },
|
|
||||||
{ "link": 103, "name": "latent_image", "type": "LATENT" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "LATENT", "type": "LATENT", "links": [35], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "KSampler" },
|
|
||||||
"widgets_values": [
|
|
||||||
55104841546759,
|
|
||||||
"randomize",
|
|
||||||
20,
|
|
||||||
6,
|
|
||||||
"uni_pc",
|
|
||||||
"simple",
|
|
||||||
1
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 51,
|
|
||||||
"pos": [360, 640],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [253.60000610351562, 78],
|
|
||||||
"type": "CLIPVisionEncode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 12,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 94, "name": "clip_vision", "type": "CLIP_VISION" },
|
|
||||||
{ "link": 116, "name": "image", "type": "IMAGE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CLIP_VISION_OUTPUT",
|
|
||||||
"type": "CLIP_VISION_OUTPUT",
|
|
||||||
"links": [107],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPVisionEncode" },
|
|
||||||
"widgets_values": ["none"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 54,
|
|
||||||
"pos": [510, 70],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 58],
|
|
||||||
"type": "ModelSamplingSD3",
|
|
||||||
"flags": {},
|
|
||||||
"order": 9,
|
|
||||||
"inputs": [{ "link": 110, "name": "model", "type": "MODEL" }],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "MODEL", "type": "MODEL", "links": [111], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ModelSamplingSD3" },
|
|
||||||
"widgets_values": [8]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"pos": [415, 186],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [422.84503173828125, 164.31304931640625],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#232",
|
|
||||||
"flags": {},
|
|
||||||
"order": 10,
|
|
||||||
"title": "CLIP Text Encode (Positive Prompt)",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 74, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 112,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#353",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [97],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"a cute anime girl with massive fennec ears and a big fluffy tail wearing a maid outfit turning around"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 55,
|
|
||||||
"pos": [-672.6411743164062, 140.167724609375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [112] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"positive_prompt",
|
|
||||||
"a cute anime girl with massive fennec ears and a big fluffy tail wearing a maid outfit turning around",
|
|
||||||
"Prompt",
|
|
||||||
"The text prompt to guide video generation."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 57,
|
|
||||||
"pos": [-664.3828125, 405.5113525390625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [390.5999755859375, 366],
|
|
||||||
"type": "ComfyUIDeployExternalImage",
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": null, "name": "default_value", "type": "IMAGE", "shape": 7 }
|
|
||||||
],
|
|
||||||
"outputs": [{ "name": "image", "type": "IMAGE", "links": [115, 116] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalImage" },
|
|
||||||
"widgets_values": [
|
|
||||||
"image_url",
|
|
||||||
"Image Url",
|
|
||||||
"URL of the input image.",
|
|
||||||
"https://comfy-deploy-output.s3.us-east-2.amazonaws.com/assets/img_GZMJYXDnLbYjWybu.png",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 56,
|
|
||||||
"pos": [-674.42333984375, 953.0498046875],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 3,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [113] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"negative_prompt",
|
|
||||||
"色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走",
|
|
||||||
"Negative Prompt",
|
|
||||||
"The negative prompt to use. Use it to address details that you don't want in the video. This could be colors, objects, scenery and even the small details (e.g. moustache, blurry, low resolution). "
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 58,
|
|
||||||
"pos": [-668.314453125, 1208.204833984375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 4,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [117], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["width", 512, "Width", "The width of the video. "]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 59,
|
|
||||||
"pos": [-665.8831787109375, 1461.255126953125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 5,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [118], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["height", 512, "Height", "The Height of the video."]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 37,
|
|
||||||
"pos": [-3.3700287342071533, 81.69654846191406],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [346.7470703125, 82],
|
|
||||||
"type": "UNETLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 6,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "MODEL", "type": "MODEL", "links": [110], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "UNETLoader" },
|
|
||||||
"widgets_values": ["wan2.1_i2v_480p_14B_bf16.safetensors", "default"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 38,
|
|
||||||
"pos": [-3.7316977977752686, 230.76495361328125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [390, 98],
|
|
||||||
"type": "CLIPLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 7,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "CLIP", "type": "CLIP", "links": [74, 75], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPLoader" },
|
|
||||||
"widgets_values": [
|
|
||||||
"umt5_xxl_fp8_e4m3fn_scaled.safetensors",
|
|
||||||
"wan",
|
|
||||||
"default"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 49,
|
|
||||||
"pos": [16.57183265686035, 640.22314453125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 58],
|
|
||||||
"type": "CLIPVisionLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 8,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CLIP_VISION",
|
|
||||||
"type": "CLIP_VISION",
|
|
||||||
"links": [94],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPVisionLoader" },
|
|
||||||
"widgets_values": ["clip_vision_h.safetensors"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 7,
|
|
||||||
"pos": [414.1811828613281, 393.8824768066406],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [425.27801513671875, 180.6060791015625],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#322",
|
|
||||||
"flags": {},
|
|
||||||
"order": 11,
|
|
||||||
"title": "CLIP Text Encode (Negative Prompt)",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 75, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 113,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#533",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [98],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {},
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"color": "#3f789e",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Input",
|
|
||||||
"bounding": [
|
|
||||||
-708.2940063476562, 47.549102783203125, 617.7969360351562,
|
|
||||||
761.303955078125
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"color": "#b06634",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Additional",
|
|
||||||
"bounding": [
|
|
||||||
-703.6196899414062, 861.310791015625, 625.998779296875,
|
|
||||||
845.0675048828125
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 0.4,
|
|
||||||
"last_link_id": 118,
|
|
||||||
"last_node_id": 59
|
|
||||||
}
|
|
||||||
@@ -1,452 +0,0 @@
|
|||||||
{
|
|
||||||
"extra": {
|
|
||||||
"ds": {
|
|
||||||
"scale": 0.6303940863128795,
|
|
||||||
"offset": [-209.31226203277674, -32.62073943929215]
|
|
||||||
},
|
|
||||||
"node_versions": {
|
|
||||||
"comfy-core": "0.3.18",
|
|
||||||
"comfyui-deploy": "b3df94d1affcf7ce05ee7eeda99989194bcd9159"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"links": [
|
|
||||||
[1, 6, 0, 1, 0, "LATENT"],
|
|
||||||
[2, 2, 0, 1, 1, "VAE"],
|
|
||||||
[3, 1, 0, 3, 0, "IMAGE"],
|
|
||||||
[4, 1, 0, 4, 0, "IMAGE"],
|
|
||||||
[5, 9, 0, 5, 0, "CONDITIONING"],
|
|
||||||
[6, 18, 0, 5, 1, "CONDITIONING"],
|
|
||||||
[7, 2, 0, 5, 2, "VAE"],
|
|
||||||
[8, 7, 0, 5, 3, "CLIP_VISION_OUTPUT"],
|
|
||||||
[9, 11, 0, 5, 4, "IMAGE"],
|
|
||||||
[10, 13, 0, 5, 5, "INT"],
|
|
||||||
[11, 14, 0, 5, 6, "INT"],
|
|
||||||
[12, 8, 0, 6, 0, "MODEL"],
|
|
||||||
[13, 5, 0, 6, 1, "CONDITIONING"],
|
|
||||||
[14, 5, 1, 6, 2, "CONDITIONING"],
|
|
||||||
[15, 5, 2, 6, 3, "LATENT"],
|
|
||||||
[16, 17, 0, 7, 0, "CLIP_VISION"],
|
|
||||||
[17, 11, 0, 7, 1, "IMAGE"],
|
|
||||||
[18, 15, 0, 8, 0, "MODEL"],
|
|
||||||
[19, 16, 0, 9, 0, "CLIP"],
|
|
||||||
[20, 10, 0, 9, 1, "STRING"],
|
|
||||||
[21, 16, 0, 18, 0, "CLIP"],
|
|
||||||
[22, 12, 0, 18, 1, "STRING"]
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"pos": [1823.98876953125, 702.6244506835938],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 46],
|
|
||||||
"type": "VAEDecode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 15,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 1, "name": "samples", "type": "LATENT" },
|
|
||||||
{ "link": 2, "name": "vae", "type": "VAE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "IMAGE", "type": "IMAGE", "links": [3, 4], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAEDecode" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"pos": [1480.382080078125, 1011.8104248046875],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [306.36004638671875, 58],
|
|
||||||
"type": "VAELoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "VAE", "type": "VAE", "links": [2, 7], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAELoader" },
|
|
||||||
"widgets_values": ["wan_2.1_vae.safetensors"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"pos": [2073.98876953125, 702.6244506835938],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [870.8511352539062, 643.7430419921875],
|
|
||||||
"type": "SaveAnimatedWEBP",
|
|
||||||
"flags": {},
|
|
||||||
"order": 16,
|
|
||||||
"inputs": [{ "link": 3, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": ["ComfyUI", 16, false, 90, "default", ""]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 4,
|
|
||||||
"pos": [2981.201904296875, 706.2359008789062],
|
|
||||||
"mode": 4,
|
|
||||||
"size": [315, 130],
|
|
||||||
"type": "SaveWEBM",
|
|
||||||
"flags": {},
|
|
||||||
"order": 17,
|
|
||||||
"inputs": [{ "link": 4, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": { "Node name for S&R": "SaveWEBM" },
|
|
||||||
"widgets_values": ["ComfyUI", "vp9", 24, 32]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 5,
|
|
||||||
"pos": [1287.03955078125, 1139.8970947265625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [342.5999755859375, 250],
|
|
||||||
"type": "WanImageToVideo",
|
|
||||||
"flags": {},
|
|
||||||
"order": 13,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 5, "name": "positive", "type": "CONDITIONING" },
|
|
||||||
{ "link": 6, "name": "negative", "type": "CONDITIONING" },
|
|
||||||
{ "link": 7, "name": "vae", "type": "VAE" },
|
|
||||||
{
|
|
||||||
"link": 8,
|
|
||||||
"name": "clip_vision_output",
|
|
||||||
"type": "CLIP_VISION_OUTPUT",
|
|
||||||
"shape": 7
|
|
||||||
},
|
|
||||||
{ "link": 9, "name": "start_image", "type": "IMAGE", "shape": 7 },
|
|
||||||
{
|
|
||||||
"pos": [10, 116],
|
|
||||||
"link": 10,
|
|
||||||
"name": "width",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "width" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pos": [10, 140],
|
|
||||||
"link": 11,
|
|
||||||
"name": "height",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "height" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "positive",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [13],
|
|
||||||
"slot_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "negative",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [14],
|
|
||||||
"slot_index": 1
|
|
||||||
},
|
|
||||||
{ "name": "latent", "type": "LATENT", "links": [15], "slot_index": 2 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "WanImageToVideo" },
|
|
||||||
"widgets_values": [512, 512, 33, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"pos": [1476.98876953125, 699.6244506835938],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 262],
|
|
||||||
"type": "KSampler",
|
|
||||||
"flags": {},
|
|
||||||
"order": 14,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 12, "name": "model", "type": "MODEL" },
|
|
||||||
{ "link": 13, "name": "positive", "type": "CONDITIONING" },
|
|
||||||
{ "link": 14, "name": "negative", "type": "CONDITIONING" },
|
|
||||||
{ "link": 15, "name": "latent_image", "type": "LATENT" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "LATENT", "type": "LATENT", "links": [1], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "KSampler" },
|
|
||||||
"widgets_values": [
|
|
||||||
625624384968868,
|
|
||||||
"randomize",
|
|
||||||
20,
|
|
||||||
6,
|
|
||||||
"uni_pc",
|
|
||||||
"simple",
|
|
||||||
1
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 7,
|
|
||||||
"pos": [973.98876953125, 1152.6243896484375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [253.60000610351562, 78],
|
|
||||||
"type": "CLIPVisionEncode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 10,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 16, "name": "clip_vision", "type": "CLIP_VISION" },
|
|
||||||
{ "link": 17, "name": "image", "type": "IMAGE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CLIP_VISION_OUTPUT",
|
|
||||||
"type": "CLIP_VISION_OUTPUT",
|
|
||||||
"links": [8],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPVisionEncode" },
|
|
||||||
"widgets_values": ["none"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"pos": [1123.98876953125, 582.6244506835938],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 58],
|
|
||||||
"type": "ModelSamplingSD3",
|
|
||||||
"flags": {},
|
|
||||||
"order": 11,
|
|
||||||
"inputs": [{ "link": 18, "name": "model", "type": "MODEL" }],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "MODEL", "type": "MODEL", "links": [12], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ModelSamplingSD3" },
|
|
||||||
"widgets_values": [8]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 9,
|
|
||||||
"pos": [1028.98876953125, 698.6244506835938],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [422.84503173828125, 164.31304931640625],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#232",
|
|
||||||
"flags": {},
|
|
||||||
"order": 12,
|
|
||||||
"title": "CLIP Text Encode (Positive Prompt)",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 19, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 20,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#353",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [5],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"a cute anime girl with massive fennec ears and a big fluffy tail wearing a maid outfit turning around"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 11,
|
|
||||||
"pos": [-50.3940315246582, 918.1358032226562],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [390.5999755859375, 366],
|
|
||||||
"type": "ComfyUIDeployExternalImage",
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": null, "name": "default_value", "type": "IMAGE", "shape": 7 }
|
|
||||||
],
|
|
||||||
"outputs": [{ "name": "image", "type": "IMAGE", "links": [9, 17] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalImage" },
|
|
||||||
"widgets_values": [
|
|
||||||
"image_url",
|
|
||||||
"Image Url",
|
|
||||||
"URL of the input image.",
|
|
||||||
"https://comfy-deploy-output.s3.us-east-2.amazonaws.com/assets/img_GZMJYXDnLbYjWybu.png",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 12,
|
|
||||||
"pos": [-60.4345588684082, 1465.6741943359375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [22] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"negative_prompt",
|
|
||||||
"色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走",
|
|
||||||
"Negative Prompt",
|
|
||||||
"The negative prompt to use. Use it to address details that you don't want in the video. This could be colors, objects, scenery and even the small details (e.g. moustache, blurry, low resolution). "
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 13,
|
|
||||||
"pos": [-54.3256721496582, 1720.8292236328125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 3,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [10], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["width", 512, "Width", "The width of the video. "]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 14,
|
|
||||||
"pos": [-51.8943977355957, 1973.8795166015625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 4,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [11], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["height", 512, "Height", "The Height of the video."]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 16,
|
|
||||||
"pos": [610.257080078125, 743.389404296875],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [390, 98],
|
|
||||||
"type": "CLIPLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 5,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "CLIP", "type": "CLIP", "links": [19, 21], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPLoader" },
|
|
||||||
"widgets_values": [
|
|
||||||
"umt5_xxl_fp8_e4m3fn_scaled.safetensors",
|
|
||||||
"wan",
|
|
||||||
"default"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 17,
|
|
||||||
"pos": [630.5606079101562, 1152.8475341796875],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 58],
|
|
||||||
"type": "CLIPVisionLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 6,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CLIP_VISION",
|
|
||||||
"type": "CLIP_VISION",
|
|
||||||
"links": [16],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPVisionLoader" },
|
|
||||||
"widgets_values": ["clip_vision_h.safetensors"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 18,
|
|
||||||
"pos": [1028.169921875, 906.5068969726562],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [425.27801513671875, 180.6060791015625],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#322",
|
|
||||||
"flags": {},
|
|
||||||
"order": 9,
|
|
||||||
"title": "CLIP Text Encode (Negative Prompt)",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 21, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 22,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#533",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [6],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 15,
|
|
||||||
"pos": [610.6187744140625, 594.3209838867188],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [346.7470703125, 82],
|
|
||||||
"type": "UNETLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 7,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "MODEL", "type": "MODEL", "links": [18], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "UNETLoader" },
|
|
||||||
"widgets_values": ["wan2.1_i2v_720p_14B_bf16.safetensors", "default"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 10,
|
|
||||||
"pos": [-60.696964263916016, 649.5515747070312],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 8,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [20] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"positive_prompt",
|
|
||||||
"a cute anime girl with massive fennec ears and a big fluffy tail wearing a maid outfit running towards front happily",
|
|
||||||
"Prompt",
|
|
||||||
"The text prompt to guide video generation."
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {},
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"color": "#3f789e",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Input",
|
|
||||||
"bounding": [
|
|
||||||
-94.30522155761719, 560.1735229492188, 617.7969360351562,
|
|
||||||
761.303955078125
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"color": "#b06634",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Additional",
|
|
||||||
"bounding": [
|
|
||||||
-89.63090515136719, 1373.9351806640625, 625.998779296875,
|
|
||||||
845.0675048828125
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 0.4,
|
|
||||||
"last_link_id": 22,
|
|
||||||
"last_node_id": 18
|
|
||||||
}
|
|
||||||
@@ -1,359 +0,0 @@
|
|||||||
{
|
|
||||||
"extra": {
|
|
||||||
"ds": {
|
|
||||||
"scale": 0.8390545288824369,
|
|
||||||
"offset": [814.3725295729478, -347.90757575249455]
|
|
||||||
},
|
|
||||||
"node_versions": {
|
|
||||||
"comfy-core": "0.3.18",
|
|
||||||
"comfyui-deploy": "b3df94d1affcf7ce05ee7eeda99989194bcd9159"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"links": [
|
|
||||||
[35, 3, 0, 8, 0, "LATENT"],
|
|
||||||
[46, 6, 0, 3, 1, "CONDITIONING"],
|
|
||||||
[52, 7, 0, 3, 2, "CONDITIONING"],
|
|
||||||
[56, 8, 0, 28, 0, "IMAGE"],
|
|
||||||
[74, 38, 0, 6, 0, "CLIP"],
|
|
||||||
[75, 38, 0, 7, 0, "CLIP"],
|
|
||||||
[76, 39, 0, 8, 1, "VAE"],
|
|
||||||
[91, 40, 0, 3, 3, "LATENT"],
|
|
||||||
[93, 8, 0, 47, 0, "IMAGE"],
|
|
||||||
[94, 37, 0, 48, 0, "MODEL"],
|
|
||||||
[95, 48, 0, 3, 0, "MODEL"],
|
|
||||||
[96, 49, 0, 6, 1, "STRING"],
|
|
||||||
[97, 50, 0, 7, 1, "STRING"],
|
|
||||||
[99, 52, 0, 40, 1, "INT"],
|
|
||||||
[100, 51, 0, 40, 0, "INT"]
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": 8,
|
|
||||||
"pos": [1210, 190],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 46],
|
|
||||||
"type": "VAEDecode",
|
|
||||||
"flags": {},
|
|
||||||
"order": 12,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 35, "name": "samples", "type": "LATENT" },
|
|
||||||
{ "link": 76, "name": "vae", "type": "VAE" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "IMAGE", "type": "IMAGE", "links": [56, 93], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAEDecode" },
|
|
||||||
"widgets_values": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 39,
|
|
||||||
"pos": [866.3932495117188, 499.18597412109375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [306.36004638671875, 58],
|
|
||||||
"type": "VAELoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 0,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "VAE", "type": "VAE", "links": [76], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "VAELoader" },
|
|
||||||
"widgets_values": ["wan_2.1_vae.safetensors"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 47,
|
|
||||||
"pos": [2367.213134765625, 193.6114959716797],
|
|
||||||
"mode": 4,
|
|
||||||
"size": [315, 130],
|
|
||||||
"type": "SaveWEBM",
|
|
||||||
"flags": {},
|
|
||||||
"order": 14,
|
|
||||||
"inputs": [{ "link": 93, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": { "Node name for S&R": "SaveWEBM" },
|
|
||||||
"widgets_values": ["ComfyUI", "vp9", 24, 32]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"pos": [863, 187],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 262],
|
|
||||||
"type": "KSampler",
|
|
||||||
"flags": {},
|
|
||||||
"order": 11,
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 95, "name": "model", "type": "MODEL" },
|
|
||||||
{ "link": 46, "name": "positive", "type": "CONDITIONING" },
|
|
||||||
{ "link": 52, "name": "negative", "type": "CONDITIONING" },
|
|
||||||
{ "link": 91, "name": "latent_image", "type": "LATENT" }
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "LATENT", "type": "LATENT", "links": [35], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "KSampler" },
|
|
||||||
"widgets_values": [
|
|
||||||
577746309562741,
|
|
||||||
"randomize",
|
|
||||||
30,
|
|
||||||
6,
|
|
||||||
"uni_pc",
|
|
||||||
"simple",
|
|
||||||
1
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 48,
|
|
||||||
"pos": [440, 50],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [210, 58],
|
|
||||||
"type": "ModelSamplingSD3",
|
|
||||||
"flags": {},
|
|
||||||
"order": 7,
|
|
||||||
"inputs": [{ "link": 94, "name": "model", "type": "MODEL" }],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "MODEL", "type": "MODEL", "links": [95], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ModelSamplingSD3" },
|
|
||||||
"widgets_values": [8]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 37,
|
|
||||||
"pos": [20, 40],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [346.7470703125, 82],
|
|
||||||
"type": "UNETLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 1,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "MODEL", "type": "MODEL", "links": [94], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "UNETLoader" },
|
|
||||||
"widgets_values": ["wan2.1_t2v_1.3B_fp16.safetensors", "default"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 6,
|
|
||||||
"pos": [415, 186],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [422.84503173828125, 164.31304931640625],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#232",
|
|
||||||
"flags": {},
|
|
||||||
"order": 8,
|
|
||||||
"title": "CLIP Text Encode (Positive Prompt)",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 74, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 96,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#353",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [46],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"a fox moving quickly in a beautiful winter scenery nature trees mountains daytime tracking camera"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 7,
|
|
||||||
"pos": [413, 389],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [425.27801513671875, 180.6060791015625],
|
|
||||||
"type": "CLIPTextEncode",
|
|
||||||
"color": "#322",
|
|
||||||
"flags": {},
|
|
||||||
"order": 9,
|
|
||||||
"title": "CLIP Text Encode (Negative Prompt)",
|
|
||||||
"inputs": [
|
|
||||||
{ "link": 75, "name": "clip", "type": "CLIP" },
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 97,
|
|
||||||
"name": "text",
|
|
||||||
"type": "STRING",
|
|
||||||
"widget": { "name": "text" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"bgcolor": "#533",
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "CONDITIONING",
|
|
||||||
"type": "CONDITIONING",
|
|
||||||
"links": [52],
|
|
||||||
"slot_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPTextEncode" },
|
|
||||||
"widgets_values": [
|
|
||||||
"色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 38,
|
|
||||||
"pos": [-10.047812461853027, 187.37384033203125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [390, 98],
|
|
||||||
"type": "CLIPLoader",
|
|
||||||
"flags": {},
|
|
||||||
"order": 2,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "CLIP", "type": "CLIP", "links": [74, 75], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "CLIPLoader" },
|
|
||||||
"widgets_values": [
|
|
||||||
"umt5_xxl_fp8_e4m3fn_scaled.safetensors",
|
|
||||||
"wan",
|
|
||||||
"default"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 49,
|
|
||||||
"pos": [-535.2967529296875, 342.3277587890625],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 3,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [96] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"positive_prompt",
|
|
||||||
"a fox moving quickly in a beautiful winter scenery nature trees mountains daytime tracking camera",
|
|
||||||
"Prompt",
|
|
||||||
"The text prompt to guide video generation. "
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 50,
|
|
||||||
"pos": [-526.2716064453125, 703.8343505859375],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [400, 200],
|
|
||||||
"type": "ComfyUIDeployExternalText",
|
|
||||||
"flags": {},
|
|
||||||
"order": 4,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [{ "name": "text", "type": "STRING", "links": [97] }],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalText" },
|
|
||||||
"widgets_values": [
|
|
||||||
"negative_prompt",
|
|
||||||
"色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走",
|
|
||||||
"Negative Prompt",
|
|
||||||
"The negative prompt to use. Use it to address details that you don't want in the image. This could be colors, objects, scenery and even the small details (e.g. moustache, blurry, low resolution). "
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 40,
|
|
||||||
"pos": [516.926513671875, 619.59716796875],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [315, 150],
|
|
||||||
"type": "EmptyHunyuanLatentVideo",
|
|
||||||
"flags": {},
|
|
||||||
"order": 10,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"pos": [10, 36],
|
|
||||||
"link": 100,
|
|
||||||
"name": "width",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "width" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pos": [10, 60],
|
|
||||||
"link": 99,
|
|
||||||
"name": "height",
|
|
||||||
"type": "INT",
|
|
||||||
"widget": { "name": "height" }
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "LATENT", "type": "LATENT", "links": [91], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "EmptyHunyuanLatentVideo" },
|
|
||||||
"widgets_values": [832, 480, 33, 1]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 28,
|
|
||||||
"pos": [1460, 190],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [870.8511352539062, 643.7430419921875],
|
|
||||||
"type": "SaveAnimatedWEBP",
|
|
||||||
"flags": {},
|
|
||||||
"order": 13,
|
|
||||||
"inputs": [{ "link": 56, "name": "images", "type": "IMAGE" }],
|
|
||||||
"outputs": [],
|
|
||||||
"properties": {},
|
|
||||||
"widgets_values": ["ComfyUI", 16, false, 90, "default"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 51,
|
|
||||||
"pos": [-522.7415161132812, 959.3386840820312],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 5,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [100], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["width", 832, "Width", "The Width of the Video. "]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 52,
|
|
||||||
"pos": [-518.9917602539062, 1207.9444580078125],
|
|
||||||
"mode": 0,
|
|
||||||
"size": [453.5999755859375, 200],
|
|
||||||
"type": "ComfyUIDeployExternalNumberInt",
|
|
||||||
"flags": {},
|
|
||||||
"order": 6,
|
|
||||||
"inputs": [],
|
|
||||||
"outputs": [
|
|
||||||
{ "name": "value", "type": "INT", "links": [99], "slot_index": 0 }
|
|
||||||
],
|
|
||||||
"properties": { "Node name for S&R": "ComfyUIDeployExternalNumberInt" },
|
|
||||||
"widgets_values": ["height", 480, "Height", "The Height of the Video. "]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"config": {},
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"color": "#3f789e",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Inputs",
|
|
||||||
"bounding": [
|
|
||||||
-560.9110717773438, 255.1485595703125, 500.94989013671875,
|
|
||||||
333.4786682128906
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"color": "#b06634",
|
|
||||||
"flags": {},
|
|
||||||
"title": "Additional",
|
|
||||||
"bounding": [
|
|
||||||
-556.5305786132812, 619.87548828125, 761.2673950195312,
|
|
||||||
811.6837768554688
|
|
||||||
],
|
|
||||||
"font_size": 24
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 0.4,
|
|
||||||
"last_link_id": 100,
|
|
||||||
"last_node_id": 52
|
|
||||||
}
|
|
||||||
+17
-38
@@ -6,20 +6,16 @@ from PIL import Image, ImageOps
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from pydantic import BaseModel as PydanticBaseModel
|
from pydantic import BaseModel as PydanticBaseModel
|
||||||
|
|
||||||
|
|
||||||
class BaseModel(PydanticBaseModel):
|
class BaseModel(PydanticBaseModel):
|
||||||
class Config:
|
class Config:
|
||||||
arbitrary_types_allowed = True
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
|
|
||||||
class Status(Enum):
|
class Status(Enum):
|
||||||
NOT_STARTED = "not-started"
|
NOT_STARTED = "not-started"
|
||||||
RUNNING = "running"
|
RUNNING = "running"
|
||||||
SUCCESS = "success"
|
SUCCESS = "success"
|
||||||
FAILED = "failed"
|
FAILED = "failed"
|
||||||
UPLOADING = "uploading"
|
UPLOADING = "uploading"
|
||||||
CANCELLED = "cancelled"
|
|
||||||
|
|
||||||
|
|
||||||
class StreamingPrompt(BaseModel):
|
class StreamingPrompt(BaseModel):
|
||||||
workflow_api: Any
|
workflow_api: Any
|
||||||
@@ -28,52 +24,42 @@ class StreamingPrompt(BaseModel):
|
|||||||
running_prompt_ids: set[str] = set()
|
running_prompt_ids: set[str] = set()
|
||||||
status_endpoint: Optional[str]
|
status_endpoint: Optional[str]
|
||||||
file_upload_endpoint: Optional[str]
|
file_upload_endpoint: Optional[str]
|
||||||
workflow: Any
|
|
||||||
gpu_event_id: Optional[str] = None
|
|
||||||
|
|
||||||
|
|
||||||
class SimplePrompt(BaseModel):
|
class SimplePrompt(BaseModel):
|
||||||
status_endpoint: Optional[str]
|
status_endpoint: Optional[str]
|
||||||
file_upload_endpoint: Optional[str]
|
file_upload_endpoint: Optional[str]
|
||||||
|
|
||||||
token: Optional[str]
|
|
||||||
|
|
||||||
workflow_api: dict
|
workflow_api: dict
|
||||||
status: Status = Status.NOT_STARTED
|
status: Status = Status.NOT_STARTED
|
||||||
progress: set = set()
|
progress: set = set()
|
||||||
last_updated_node: Optional[str] = None
|
last_updated_node: Optional[str] = None,
|
||||||
uploading_nodes: set = set()
|
uploading_nodes: set = set()
|
||||||
done: bool = False
|
done: bool = False
|
||||||
is_realtime: bool = False
|
is_realtime: bool = False,
|
||||||
start_time: Optional[float] = None
|
start_time: Optional[float] = None,
|
||||||
gpu_event_id: Optional[str] = None
|
|
||||||
|
|
||||||
|
|
||||||
sockets = dict()
|
sockets = dict()
|
||||||
prompt_metadata: dict[str, SimplePrompt] = {}
|
prompt_metadata: dict[str, SimplePrompt] = {}
|
||||||
streaming_prompt_metadata: dict[str, StreamingPrompt] = {}
|
streaming_prompt_metadata: dict[str, StreamingPrompt] = {}
|
||||||
|
|
||||||
|
|
||||||
class BinaryEventTypes:
|
class BinaryEventTypes:
|
||||||
PREVIEW_IMAGE = 1
|
PREVIEW_IMAGE = 1
|
||||||
UNENCODED_PREVIEW_IMAGE = 2
|
UNENCODED_PREVIEW_IMAGE = 2
|
||||||
|
|
||||||
|
|
||||||
max_output_id_length = 24
|
max_output_id_length = 24
|
||||||
|
|
||||||
|
async def send_image(image_data, sid=None, output_id:str = None):
|
||||||
async def send_image(image_data, sid=None, output_id: str = None):
|
|
||||||
max_length = max_output_id_length
|
max_length = max_output_id_length
|
||||||
output_id = output_id[:max_length]
|
output_id = output_id[:max_length]
|
||||||
padded_output_id = output_id.ljust(max_length, "\x00")
|
padded_output_id = output_id.ljust(max_length, '\x00')
|
||||||
encoded_output_id = padded_output_id.encode("ascii", "replace")
|
encoded_output_id = padded_output_id.encode('ascii', 'replace')
|
||||||
|
|
||||||
image_type = image_data[0]
|
image_type = image_data[0]
|
||||||
image = image_data[1]
|
image = image_data[1]
|
||||||
max_size = image_data[2]
|
max_size = image_data[2]
|
||||||
quality = image_data[3]
|
quality = image_data[3]
|
||||||
if max_size is not None:
|
if max_size is not None:
|
||||||
if hasattr(Image, "Resampling"):
|
if hasattr(Image, 'Resampling'):
|
||||||
resampling = Image.Resampling.BILINEAR
|
resampling = Image.Resampling.BILINEAR
|
||||||
else:
|
else:
|
||||||
resampling = Image.ANTIALIAS
|
resampling = Image.ANTIALIAS
|
||||||
@@ -97,23 +83,17 @@ async def send_image(image_data, sid=None, output_id: str = None):
|
|||||||
position_after = bytesIO.tell()
|
position_after = bytesIO.tell()
|
||||||
bytes_written = position_after - position_before
|
bytes_written = position_after - position_before
|
||||||
print(f"Bytes written: {bytes_written}")
|
print(f"Bytes written: {bytes_written}")
|
||||||
|
|
||||||
image.save(bytesIO, format=image_type, quality=quality, compress_level=1)
|
image.save(bytesIO, format=image_type, quality=quality, compress_level=1)
|
||||||
preview_bytes = bytesIO.getvalue()
|
preview_bytes = bytesIO.getvalue()
|
||||||
await send_bytes(BinaryEventTypes.PREVIEW_IMAGE, preview_bytes, sid=sid)
|
await send_bytes(BinaryEventTypes.PREVIEW_IMAGE, preview_bytes, sid=sid)
|
||||||
|
|
||||||
|
|
||||||
async def send_socket_catch_exception(function, message):
|
async def send_socket_catch_exception(function, message):
|
||||||
try:
|
try:
|
||||||
await function(message)
|
await function(message)
|
||||||
except (
|
except (aiohttp.ClientError, aiohttp.ClientPayloadError, ConnectionResetError) as err:
|
||||||
aiohttp.ClientError,
|
|
||||||
aiohttp.ClientPayloadError,
|
|
||||||
ConnectionResetError,
|
|
||||||
) as err:
|
|
||||||
print("send error:", err)
|
print("send error:", err)
|
||||||
|
|
||||||
|
|
||||||
def encode_bytes(event, data):
|
def encode_bytes(event, data):
|
||||||
if not isinstance(event, int):
|
if not isinstance(event, int):
|
||||||
raise RuntimeError(f"Binary event types must be integers, got {event}")
|
raise RuntimeError(f"Binary event types must be integers, got {event}")
|
||||||
@@ -123,10 +103,9 @@ def encode_bytes(event, data):
|
|||||||
message.extend(data)
|
message.extend(data)
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
async def send_bytes(event, data, sid=None):
|
async def send_bytes(event, data, sid=None):
|
||||||
message = encode_bytes(event, data)
|
message = encode_bytes(event, data)
|
||||||
|
|
||||||
print("sending image to ", event, sid)
|
print("sending image to ", event, sid)
|
||||||
|
|
||||||
if sid is None:
|
if sid is None:
|
||||||
@@ -134,4 +113,4 @@ async def send_bytes(event, data, sid=None):
|
|||||||
for ws in _sockets:
|
for ws in _sockets:
|
||||||
await send_socket_catch_exception(ws.send_bytes, message)
|
await send_socket_catch_exception(ws.send_bytes, message)
|
||||||
elif sid in sockets:
|
elif sid in sockets:
|
||||||
await send_socket_catch_exception(sockets[sid].send_bytes, message)
|
await send_socket_catch_exception(sockets[sid].send_bytes, message)
|
||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "comfyui-deploy"
|
name = "comfyui-deploy"
|
||||||
description = "Open source comfyui deployment platform, a vercel for generative workflow infra."
|
description = "Open source comfyui deployment platform, a vercel for generative workflow infra."
|
||||||
version = "2.3.7"
|
version = "1.0.0"
|
||||||
license = { file = "LICENSE" }
|
license = "LICENSE"
|
||||||
dependencies = ["aiofiles", "pydantic", "opencv-python", "imageio-ffmpeg", "tabulate", "brotli"]
|
dependencies = ["aiofiles", "pydantic", "opencv-python", "imageio-ffmpeg"]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Repository = "https://github.com/BennyKok/comfyui-deploy"
|
Repository = "https://github.com/BennyKok/comfyui-deploy"
|
||||||
|
|||||||
+1
-3
@@ -2,6 +2,4 @@ aiofiles
|
|||||||
pydantic
|
pydantic
|
||||||
opencv-python
|
opencv-python
|
||||||
imageio-ffmpeg
|
imageio-ffmpeg
|
||||||
brotli
|
logfire
|
||||||
tabulate
|
|
||||||
# logfire
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/** @typedef {import('../../../web/scripts/api.js').api} API*/
|
||||||
|
import { api as _api } from '../../scripts/api.js';
|
||||||
|
/** @type {API} */
|
||||||
|
export const api = _api;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/** @typedef {import('../../../web/scripts/app.js').ComfyApp} ComfyApp*/
|
||||||
|
import { app as _app } from '../../scripts/app.js';
|
||||||
|
/** @type {ComfyApp} */
|
||||||
|
export const app = _app;
|
||||||
+388
-2413
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,68 +0,0 @@
|
|||||||
// Snapshot Utilities
|
|
||||||
// Centralized snapshot fetching with ComfyUI version fallback
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the current snapshot with ComfyUI version fallback
|
|
||||||
* If the snapshot response has null comfyui field, it will fetch the latest ComfyUI version
|
|
||||||
* and update the snapshot with the comfyui_hash
|
|
||||||
*
|
|
||||||
* @param {Function} getDataFn - Function that returns { apiKey, apiUrl } for ComfyUI version API calls
|
|
||||||
* @returns {Promise<Object>} - The snapshot data with comfyui field populated
|
|
||||||
*/
|
|
||||||
export async function fetchSnapshot(getDataFn = null) {
|
|
||||||
try {
|
|
||||||
// Fetch the current snapshot
|
|
||||||
const response = await fetch("/snapshot/get_current");
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Snapshot fetch failed: ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const snapshot = await response.json();
|
|
||||||
|
|
||||||
// Check if comfyui field is null and we have getDataFn for fallback
|
|
||||||
if (snapshot.comfyui === null && getDataFn) {
|
|
||||||
console.log(
|
|
||||||
"ComfyUI version is null in snapshot, fetching latest version..."
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = getDataFn();
|
|
||||||
if (data && data.apiKey) {
|
|
||||||
const comfyuiVersionResponse = await fetch(
|
|
||||||
`/comfyui-deploy/comfyui-version?api_url=${encodeURIComponent(
|
|
||||||
data.apiUrl || "https://api.comfydeploy.com"
|
|
||||||
)}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${data.apiKey}`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (comfyuiVersionResponse.ok) {
|
|
||||||
const versionData = await comfyuiVersionResponse.json();
|
|
||||||
if (versionData.comfyui_hash) {
|
|
||||||
console.log(
|
|
||||||
`Using ComfyUI hash from API: ${versionData.comfyui_hash}`
|
|
||||||
);
|
|
||||||
snapshot.comfyui = versionData.comfyui_hash;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.warn(
|
|
||||||
"Failed to fetch ComfyUI version from API:",
|
|
||||||
comfyuiVersionResponse.status
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Error fetching ComfyUI version fallback:", error);
|
|
||||||
// Continue with original snapshot even if fallback fails
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return snapshot;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching snapshot:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// /** @typedef {import('../../../web/scripts/api.js').api} API*/
|
||||||
|
// import { api as _api } from "../../scripts/api.js";
|
||||||
|
// /** @type {API} */
|
||||||
|
// export const api = _api;
|
||||||
|
|
||||||
|
/** @typedef {typeof import('../../../web/scripts/widgets.js').ComfyWidgets} Widgets*/
|
||||||
|
import { ComfyWidgets as _ComfyWidgets } from "../../scripts/widgets.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Widgets}
|
||||||
|
*/
|
||||||
|
export const ComfyWidgets = _ComfyWidgets;
|
||||||
|
|
||||||
|
// import { LGraphNode as _LGraphNode } from "../../types/litegraph.js";
|
||||||
|
|
||||||
|
/** @typedef {typeof import('../../../web/types/litegraph.js').LGraphNode} LGraphNode*/
|
||||||
|
/** @type {LGraphNode}*/
|
||||||
|
export const LGraphNode = LiteGraph.LGraphNode;
|
||||||
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -74,7 +74,7 @@
|
|||||||
"mitata": "^0.1.6",
|
"mitata": "^0.1.6",
|
||||||
"ms": "^2.1.3",
|
"ms": "^2.1.3",
|
||||||
"nanoid": "^5.0.4",
|
"nanoid": "^5.0.4",
|
||||||
"next": "14.2",
|
"next": "14.1",
|
||||||
"next-plausible": "^3.12.0",
|
"next-plausible": "^3.12.0",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"next-usequerystate": "^1.13.2",
|
"next-usequerystate": "^1.13.2",
|
||||||
|
|||||||
@@ -6,5 +6,4 @@ export const customInputNodes: Record<string, string> = {
|
|||||||
ComfyUIDeployExternalNumberInt: "integer",
|
ComfyUIDeployExternalNumberInt: "integer",
|
||||||
ComfyUIDeployExternalLora: "string - (public lora download url)",
|
ComfyUIDeployExternalLora: "string - (public lora download url)",
|
||||||
ComfyUIDeployExternalCheckpoint: "string - (public checkpoints download url)",
|
ComfyUIDeployExternalCheckpoint: "string - (public checkpoints download url)",
|
||||||
ComfyUIDeployExternalFaceModel: "string - (public face model download url)",
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,9 +51,7 @@ const createRunRoute = createRoute({
|
|||||||
export const registerCreateRunRoute = (app: App) => {
|
export const registerCreateRunRoute = (app: App) => {
|
||||||
app.openapi(createRunRoute, async (c) => {
|
app.openapi(createRunRoute, async (c) => {
|
||||||
const data = c.req.valid("json");
|
const data = c.req.valid("json");
|
||||||
const proto = c.req.headers.get('x-forwarded-proto') || "http";
|
const origin = new URL(c.req.url).origin;
|
||||||
const host = c.req.headers.get('x-forwarded-host') || c.req.headers.get('host');
|
|
||||||
const origin = `${proto}://${host}` || new URL(c.req.url).origin;
|
|
||||||
const apiKeyTokenData = c.get("apiKeyTokenData")!;
|
const apiKeyTokenData = c.get("apiKeyTokenData")!;
|
||||||
|
|
||||||
const { deployment_id, inputs } = data;
|
const { deployment_id, inputs } = data;
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export const createRun = withServerPromise(
|
|||||||
|
|
||||||
let prompt_id: string | undefined = undefined;
|
let prompt_id: string | undefined = undefined;
|
||||||
const shareData = {
|
const shareData = {
|
||||||
workflow_api_raw: workflow_api,
|
workflow_api: workflow_api,
|
||||||
status_endpoint: `${origin}/api/update-run`,
|
status_endpoint: `${origin}/api/update-run`,
|
||||||
file_upload_endpoint: `${origin}/api/file-upload`,
|
file_upload_endpoint: `${origin}/api/file-upload`,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user