Dr.Lt.Data
2 years ago
11 changed files with 1693 additions and 288 deletions
@ -0,0 +1,60 @@
|
||||
# ComfyUI Manager |
||||
|
||||
# Installation |
||||
|
||||
1. cd custom_nodes |
||||
2. git clone https://github.com/ltdrdata/ComfyUI-Manager.git |
||||
3. Restart ComfyUI |
||||
|
||||
|
||||
# How To Use |
||||
|
||||
1. Click "Manager" button on main menu |
||||
|
||||
![mainmenu](misc/main.png) |
||||
|
||||
|
||||
2. If you click on 'Install Custom Nodes' or 'Install Models', an installer dialog will open. |
||||
![menu](misc/menu.png) |
||||
|
||||
|
||||
3. Click 'Install' or 'Try Install' button. |
||||
|
||||
![node-install-dialog](misc/custom-nodes.png) |
||||
|
||||
![model-install-dialog](misc/models.png) |
||||
|
||||
* Installed: This item is already installed. |
||||
* Install: Clicking this button will install the item. |
||||
* Try Install: This is a custom node of which installation information cannot be confirmed. Click the button to try installing it. |
||||
|
||||
|
||||
# Custom node support guide |
||||
|
||||
* Currently, the system operates by cloning the git repository and sequentially installing the dependencies listed in requirements.txt using pip, followed by invoking the install.py script. In the future, we plan to discuss and determine the specifications for supporting custom nodes. |
||||
|
||||
* Please submit a pull request to update either the custom-node-list.json or model-list.json file. |
||||
|
||||
|
||||
# TODO: Unconventional form of custom node list |
||||
|
||||
* https://github.com/ailex000/ComfyUI-Extensions |
||||
* https://github.com/rock-land/graphNavigator/tree/main/graphNavigator |
||||
* https://github.com/diffus3/ComfyUI-extensions |
||||
* https://github.com/bmad4ever/ComfyUI-Bmad-Custom-Nodes |
||||
* https://github.com/pythongosssss/ComfyUI-Custom-Scripts |
||||
* https://github.com/diontimmer/Sample-Diffusion-ComfyUI-Extension |
||||
* https://github.com/m957ymj75urz/ComfyUI-Custom-Nodes |
||||
|
||||
|
||||
# Roadmap |
||||
|
||||
* Specification of custom nodes |
||||
* Specification scanner |
||||
* Search extension by node name |
||||
* Automatic recognition of missing custom nodes |
||||
* Automatic installation suggestion of missing custom nodes |
||||
|
||||
# Disclaimer |
||||
|
||||
* This extension simply provides the convenience of installing custom nodes and does not guarantee their proper functioning. |
@ -0,0 +1,270 @@
|
||||
import shutil |
||||
import folder_paths |
||||
import os, sys |
||||
import subprocess |
||||
|
||||
|
||||
sys.path.append('../..') |
||||
|
||||
from torchvision.datasets.utils import download_url |
||||
|
||||
# ensure .js |
||||
print("### Loading: ComfyUI-Manager") |
||||
|
||||
comfy_path = os.path.dirname(folder_paths.__file__) |
||||
custom_nodes_path = os.path.join(comfy_path, 'custom_nodes') |
||||
|
||||
def setup_js(): |
||||
impact_path = os.path.dirname(__file__) |
||||
js_dest_path = os.path.join(comfy_path, "web", "extensions", "core") |
||||
js_src_path = os.path.join(impact_path, "js", "comfyui-manager.js") |
||||
shutil.copy(js_src_path, js_dest_path) |
||||
|
||||
setup_js() |
||||
|
||||
|
||||
# Expand Server api |
||||
|
||||
import server |
||||
from aiohttp import web |
||||
import aiohttp |
||||
import json |
||||
import zipfile |
||||
import urllib.request |
||||
|
||||
|
||||
def get_model_path(data): |
||||
if data['save_path'] != 'default': |
||||
base_model = os.path.join(folder_paths.models_dir, data['save_path']) |
||||
else: |
||||
model_type = data['type'] |
||||
if model_type == "checkpoints": |
||||
base_model = folder_paths.folder_names_and_paths["checkpoints"][0][0] |
||||
elif model_type == "unclip": |
||||
base_model = folder_paths.folder_names_and_paths["checkpoints"][0][0] |
||||
elif model_type == "VAE": |
||||
base_model = folder_paths.folder_names_and_paths["vae"][0][0] |
||||
elif model_type == "lora": |
||||
base_model = folder_paths.folder_names_and_paths["loras"][0][0] |
||||
elif model_type == "T2I-Adapter": |
||||
base_model = folder_paths.folder_names_and_paths["controlnet"][0][0] |
||||
elif model_type == "T2I-Style": |
||||
base_model = folder_paths.folder_names_and_paths["controlnet"][0][0] |
||||
elif model_type == "controlnet": |
||||
base_model = folder_paths.folder_names_and_paths["controlnet"][0][0] |
||||
elif model_type == "clip_vision": |
||||
base_model = folder_paths.folder_names_and_paths["clip_vision"][0][0] |
||||
elif model_type == "gligen": |
||||
base_model = folder_paths.folder_names_and_paths["gligen"][0][0] |
||||
elif model_type == "upscale": |
||||
base_model = folder_paths.folder_names_and_paths["upscale_models"][0][0] |
||||
else: |
||||
base_model = None |
||||
|
||||
return os.path.join(base_model, data['filename']) |
||||
|
||||
|
||||
def check_custom_node_installed(json_obj): |
||||
for item in json_obj['custom_nodes']: |
||||
item['installed'] = 'None' |
||||
|
||||
if item['install_type'] == 'git-clone' and len(item['files']) == 1: |
||||
dir_name = os.path.splitext(os.path.basename(item['files'][0]))[0].replace(".git", "") |
||||
dir_path = os.path.join(custom_nodes_path, dir_name) |
||||
if os.path.exists(dir_path): |
||||
item['installed'] = 'True' |
||||
else: |
||||
item['installed'] = 'False' |
||||
|
||||
elif item['install_type'] == 'copy' and len(item['files']) == 1: |
||||
dir_name = os.path.basename(item['files'][0]) |
||||
dir_path = os.path.join(custom_nodes_path, dir_name) |
||||
if os.path.exists(dir_path): |
||||
item['installed'] = 'True' |
||||
else: |
||||
item['installed'] = 'False' |
||||
|
||||
|
||||
@server.PromptServer.instance.routes.post("/customnode/getlist") |
||||
async def fetch_customnode_list(request): |
||||
url = 'https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json' |
||||
async with aiohttp.ClientSession() as session: |
||||
async with session.get(url) as resp: |
||||
json_text = await resp.text() |
||||
json_obj = json.loads(json_text) |
||||
|
||||
check_custom_node_installed(json_obj) |
||||
|
||||
return web.json_response(json_obj, content_type='application/json') |
||||
|
||||
|
||||
def check_model_installed(json_obj): |
||||
for item in json_obj['models']: |
||||
item['installed'] = 'None' |
||||
|
||||
model_path = get_model_path(item) |
||||
|
||||
if model_path is not None: |
||||
if os.path.exists(model_path): |
||||
item['installed'] = 'True' |
||||
else: |
||||
item['installed'] = 'False' |
||||
|
||||
|
||||
@server.PromptServer.instance.routes.post("/externalmodel/getlist") |
||||
async def fetch_externalmodel_list(request): |
||||
url = 'https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/model-list.json' |
||||
async with aiohttp.ClientSession() as session: |
||||
async with session.get(url) as resp: |
||||
json_text = await resp.text() |
||||
json_obj = json.loads(json_text) |
||||
|
||||
check_model_installed(json_obj) |
||||
|
||||
return web.json_response(json_obj, content_type='application/json') |
||||
|
||||
|
||||
def unzip_install(files): |
||||
temp_filename = 'manager-temp.zip' |
||||
for url in files: |
||||
try: |
||||
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'} |
||||
|
||||
req = urllib.request.Request(url, headers=headers) |
||||
response = urllib.request.urlopen(req) |
||||
data = response.read() |
||||
|
||||
with open(temp_filename, 'wb') as f: |
||||
f.write(data) |
||||
|
||||
with zipfile.ZipFile(temp_filename, 'r') as zip_ref: |
||||
zip_ref.extractall(custom_nodes_path) |
||||
|
||||
os.remove(temp_filename) |
||||
except Exception as e: |
||||
print(f"Install(unzip) error: {url} / {e}") |
||||
return False |
||||
|
||||
print("Installation successful.") |
||||
return True |
||||
|
||||
|
||||
def download_url_with_agent(url, save_path): |
||||
try: |
||||
headers = { |
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'} |
||||
|
||||
req = urllib.request.Request(url, headers=headers) |
||||
response = urllib.request.urlopen(req) |
||||
data = response.read() |
||||
|
||||
with open(save_path, 'wb') as f: |
||||
f.write(data) |
||||
|
||||
except Exception as e: |
||||
print(f"Download error: {url} / {e}") |
||||
return False |
||||
|
||||
print("Installation successful.") |
||||
return True |
||||
|
||||
|
||||
def copy_install(files): |
||||
for url in files: |
||||
try: |
||||
download_url(url, custom_nodes_path) |
||||
except Exception as e: |
||||
print(f"Install(copy) error: {url} / {e}") |
||||
return False |
||||
|
||||
print("Installation successful.") |
||||
return True |
||||
|
||||
|
||||
def gitclone_install(files): |
||||
print(f"install: {files}") |
||||
for url in files: |
||||
try: |
||||
print(f"Download: git clone '{url}'") |
||||
clone_cmd = ["git", "clone", url] |
||||
code = subprocess.run(clone_cmd, cwd=custom_nodes_path) |
||||
|
||||
if code.returncode != 0: |
||||
print(f"git-clone failed: {url}") |
||||
return False |
||||
|
||||
repo_name = os.path.splitext(os.path.basename(url))[0] |
||||
repo_path = os.path.join(custom_nodes_path, repo_name) |
||||
|
||||
install_script_path = os.path.join(repo_path, "install.py") |
||||
requirements_path = os.path.join(repo_path, "requirements.txt") |
||||
|
||||
if os.path.exists(requirements_path): |
||||
print(f"Install: pip packages") |
||||
install_cmd = ["python", "-m", "pip", "install", "-r", "requirements.txt"] |
||||
code = subprocess.run(install_cmd, cwd=repo_path) |
||||
|
||||
if code.returncode != 0: |
||||
print(f"install script failed: {url}") |
||||
return False |
||||
|
||||
if os.path.exists(install_script_path): |
||||
print(f"Install: install script") |
||||
install_cmd = ["python", "install.py"] |
||||
code = subprocess.run(install_cmd, cwd=repo_path) |
||||
|
||||
if code.returncode != 0: |
||||
print(f"install script failed: {url}") |
||||
return False |
||||
|
||||
except Exception as e: |
||||
print(f"Install(git-clone) error: {url} / {e}") |
||||
return False |
||||
|
||||
print("Installation successful.") |
||||
return True |
||||
|
||||
|
||||
@server.PromptServer.instance.routes.post("/customnode/install") |
||||
async def install_custom_node(request): |
||||
json_data = await request.json() |
||||
|
||||
install_type = json_data['install_type'] |
||||
|
||||
print(f"Install custom node '{json_data['title']}'") |
||||
|
||||
res = False |
||||
|
||||
if install_type == "unzip": |
||||
res = unzip_install(json_data['files']) |
||||
|
||||
if install_type == "copy": |
||||
res = copy_install(json_data['files']) |
||||
|
||||
elif install_type == "git-clone": |
||||
res = gitclone_install(json_data['files']) |
||||
|
||||
if res: |
||||
return web.json_response({}, content_type='application/json') |
||||
|
||||
return web.Response(status=400) |
||||
|
||||
|
||||
@server.PromptServer.instance.routes.post("/model/install") |
||||
async def install_model(request): |
||||
json_data = await request.json() |
||||
|
||||
model_path = get_model_path(json_data) |
||||
|
||||
res = False |
||||
|
||||
if model_path is not None: |
||||
print(f"Install model '{json_data['name']}' into '{model_path}'") |
||||
res = download_url_with_agent(json_data['url'], model_path) |
||||
else: |
||||
print(f"Model installation error: invalid model type - {json_data['type']}") |
||||
|
||||
if res: |
||||
return web.json_response({}, content_type='application/json') |
||||
|
||||
return web.Response(status=400) |
@ -0,0 +1,398 @@
|
||||
{ |
||||
"custom_nodes": [ |
||||
{ |
||||
"author": "Dr.Lt.Data", |
||||
"title": "ComfyUI Impact Pack", |
||||
"reference": "https://github.com/ltdrdata/ComfyUI-Impact-Pack/", |
||||
"files": [ |
||||
"https://github.com/ltdrdata/ComfyUI-Impact-Pack" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details." |
||||
}, |
||||
{ |
||||
"author": "comfyanonymous", |
||||
"title": "ComfyUI_experiments/sampler_tonemap", |
||||
"reference": "https://github.com/comfyanonymous/ComfyUI_experiments", |
||||
"files": [ |
||||
"https://github.com/comfyanonymous/ComfyUI_experiments/raw/master/sampler_tonemap.py" |
||||
], |
||||
"install_type": "copy", |
||||
"description": "ModelSamplerTonemapNoiseTest a node that makes the sampler use a simple tonemapping algorithm to tonemap the noise. It will let you use higher CFG without breaking the image. To using higher CFG lower the multiplier value. Similar to Dynamic Thresholding extension of A1111." |
||||
}, |
||||
{ |
||||
"author": "Fannovel16", |
||||
"title": "ControlNet Preprocessors", |
||||
"reference": "https://github.com/Fannovel16/comfy_controlnet_preprocessors", |
||||
"files": [ |
||||
"https://github.com/Fannovel16/comfy_controlnet_preprocessors" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "ControlNet Preprocessors" |
||||
}, |
||||
{ |
||||
"author": "Fannovel16", |
||||
"title": "comfy_video", |
||||
"reference": "https://github.com/Fannovel16/comfy_video", |
||||
"files": [ |
||||
"https://github.com/Fannovel16/comfy_video" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Video_Frame_Extractor, Save_Frame_To_Folder, Simple_Frame_Folder_To_Video." |
||||
}, |
||||
{ |
||||
"author": "biegert", |
||||
"title": "CLIPSeg", |
||||
"reference": "https://github.com/biegert/ComfyUI-CLIPSeg", |
||||
"files": [ |
||||
"https://github.com/biegert/ComfyUI-CLIPSeg/raw/main/custom_nodes/clipseg.py" |
||||
], |
||||
"install_type": "copy", |
||||
"description": "The CLIPSeg node generates a binary mask for a given input image and text prompt." |
||||
}, |
||||
{ |
||||
"author": "BlenderNeko", |
||||
"title": "ComfyUI Cutoff", |
||||
"reference": "https://github.com/BlenderNeko/ComfyUI_Cutoff", |
||||
"files": [ |
||||
"https://github.com/BlenderNeko/ComfyUI_Cutoff" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "These custom nodes provides features that allow for better control over the effects of the text prompt." |
||||
}, |
||||
{ |
||||
"author": "BlenderNeko", |
||||
"title": "Advanced CLIP Text Encode", |
||||
"reference": "https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb", |
||||
"files": [ |
||||
"https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Advanced CLIP Text Encode (if you need A1111 like prompt. you need this. But Cutoff node includes this feature, already.)" |
||||
}, |
||||
{ |
||||
"author": "BlenderNeko", |
||||
"title": "ComfyUI Noise", |
||||
"reference": "https://github.com/BlenderNeko/ComfyUI_Noise", |
||||
"files": [ |
||||
"https://github.com/BlenderNeko/ComfyUI_Noise" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "This extension contains 6 nodes for ComfyUI that allows for more control and flexibility over the noise." |
||||
}, |
||||
{ |
||||
"author": "BlenderNeko", |
||||
"title": "(WIP) Tiled sampling for ComfyUI", |
||||
"reference": "https://github.com/BlenderNeko/ComfyUI_TiledKSampler", |
||||
"files": [ |
||||
"https://github.com/BlenderNeko/ComfyUI_TiledKSampler" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "This extension contains a tiled sampler for ComfyUI. It allows for denoising larger images by splitting it up into smaller tiles and denoising these. It tries to minimize any seams for showing up in the end result by gradually denoising all tiles one step at the time and randomizing tile positions for every step." |
||||
}, |
||||
{ |
||||
"author": "LucianoCirino", |
||||
"title": "Efficiency Nodes for ComfyUI", |
||||
"reference": "https://github.com/LucianoCirino/efficiency-nodes-comfyui", |
||||
"files": [ |
||||
"https://github.com/LucianoCirino/efficiency-nodes-comfyui" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "A collection of ComfyUI custom nodes to help streamline workflows and reduce total node count." |
||||
}, |
||||
{ |
||||
"author": "Derfuu", |
||||
"title": "Derfuu_ComfyUI_ModdedNodes", |
||||
"reference": "hhttps://github.com/Derfuu/Derfuu_ComfyUI_ModdedNodes", |
||||
"files": [ |
||||
"https://github.com/Derfuu/Derfuu_ComfyUI_ModdedNodes" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Automate calculation depending on image sizes or something you want." |
||||
}, |
||||
{ |
||||
"author": "paulo-coronado", |
||||
"title": "comfy_clip_blip_node", |
||||
"reference": "https://github.com/paulo-coronado/comfy_clip_blip_node", |
||||
"files": [ |
||||
"https://github.com/paulo-coronado/comfy_clip_blip_node" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "CLIPTextEncodeBLIP: This custom node provides a CLIP Encoder that is capable of receiving images as input." |
||||
}, |
||||
{ |
||||
"author": "Davemane42", |
||||
"title": "Visual Area Conditioning / Latent composition", |
||||
"reference": "https://github.com/Davemane42/ComfyUI_Dave_CustomNode", |
||||
"files": [ |
||||
"https://github.com/Davemane42/ComfyUI_Dave_CustomNode" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "This tool provides custom nodes that allow visualization and configuration of area conditioning and latent composite." |
||||
}, |
||||
{ |
||||
"author": "WASasquatch", |
||||
"title": "WAS Node Suite", |
||||
"reference": "https://github.com/WASasquatch/was-node-suite-comfyui", |
||||
"files": [ |
||||
"https://github.com/WASasquatch/was-node-suite-comfyui" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "A node suite for ComfyUI with many new nodes, such as image processing, text processing, and more." |
||||
}, |
||||
{ |
||||
"author": "omar92", |
||||
"title": "Quality of life Suit:V2", |
||||
"reference": "https://github.com/omar92/ComfyUI-QualityOfLifeSuit_Omar92", |
||||
"files": [ |
||||
"https://github.com/omar92/ComfyUI-QualityOfLifeSuit_Omar92" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "openAI suite, String suite, Latent Tools, Image Tools: These custom nodes provide expanded functionality for image and string processing, latent processing, as well as the ability to interface with models such as ChatGPT/DallE-2." |
||||
}, |
||||
{ |
||||
"author": "lilly1987", |
||||
"title": "simple wildcard for ComfyUI", |
||||
"reference": "https://github.com/lilly1987/ComfyUI_node_Lilly", |
||||
"files": [ |
||||
"https://github.com/lilly1987/ComfyUI_node_Lilly" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "These custom nodes provides a feature to insert arbitrary inputs through wildcards in the prompt. Additionally, this tool provides features that help simplify workflows, such as VAELoaderDecoder and SimplerSample." |
||||
}, |
||||
{ |
||||
"author": "sylym", |
||||
"title": "Vid2vid", |
||||
"reference": "https://github.com/sylym/comfy_vid2vid", |
||||
"files": [ |
||||
"https://github.com/sylym/comfy_vid2vid" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "A node suite for ComfyUI that allows you to load image sequence and generate new image sequence with different styles or content." |
||||
}, |
||||
{ |
||||
"author": "EllangoK", |
||||
"title": "ComfyUI-post-processing-nodes", |
||||
"reference": "https://github.com/EllangoK/ComfyUI-post-processing-nodes", |
||||
"files": [ |
||||
"https://github.com/EllangoK/ComfyUI-post-processing-nodes" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "A collection of post processing nodes for ComfyUI, simply download this repo and drag." |
||||
}, |
||||
{ |
||||
"author": "LEv145", |
||||
"title": "ImagesGrid", |
||||
"reference": "https://github.com/LEv145/images-grid-comfy-plugin", |
||||
"files": [ |
||||
"https://github.com/LEv145/images-grid-comfy-plugin" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "This tool provides a viewer node that allows for checking multiple outputs in a grid, similar to the X/Y Plot extension." |
||||
}, |
||||
{ |
||||
"author": "xXAdonesXx", |
||||
"title": "NodeGPT", |
||||
"reference": "https://github.com/xXAdonesXx/NodeGPT", |
||||
"files": [ |
||||
"https://github.com/xXAdonesXx/NodeGPT/raw/main/Textnode.py" |
||||
], |
||||
"install_type": "copy", |
||||
"description": "ComfyUI Extension Nodes for Automated Text Generation." |
||||
}, |
||||
{ |
||||
"author": "diontimmer", |
||||
"title": "ComfyUI-Vextra-Nodes", |
||||
"reference": "https://github.com/diontimmer/ComfyUI-Vextra-Nodes", |
||||
"files": [ |
||||
"https://github.com/diontimmer/ComfyUI-Vextra-Nodes" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Nodes: Pixel Sort, Swap Color Mode, Solid Color, Glitch This, Add Text To Image, Play Sound, Prettify Prompt, Generate Noise, Flatten Colors" |
||||
}, |
||||
{ |
||||
"author": "hnmr293", |
||||
"title": "ComfyUI-nodes-hnmr", |
||||
"reference": "https://github.com/hnmr293/ComfyUI-nodes-hnmr", |
||||
"files": [ |
||||
"https://github.com/hnmr293/ComfyUI-nodes-hnmr" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Provide various custom nodes for Latent, Sampling, Model, Loader, Image, Text" |
||||
}, |
||||
{ |
||||
"author": "BadCafeCode", |
||||
"title": "Masquerade Nodes", |
||||
"reference": "https://github.com/BadCafeCode/masquerade-nodes-comfyui", |
||||
"files": [ |
||||
"https://github.com/BadCafeCode/masquerade-nodes-comfyui" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "This is a node pack for ComfyUI, primarily dealing with masks." |
||||
}, |
||||
{ |
||||
"author": "guoyk93", |
||||
"title": "y.k.'s ComfyUI node suite", |
||||
"reference": "https://github.com/guoyk93/yk-node-suite-comfyui", |
||||
"files": [ |
||||
"https://github.com/guoyk93/yk-node-suite-comfyui" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Nodes: YKImagePadForOutpaint, YKMaskToImage" |
||||
}, |
||||
{ |
||||
"author": "Jcd1230", |
||||
"title": "Rembg Background Removal Node for ComfyUI", |
||||
"reference": "https://github.com/Jcd1230/rembg-comfyui-node", |
||||
"files": [ |
||||
"https://github.com/Jcd1230/rembg-comfyui-node" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Nodes: Image Remove Background (rembg)" |
||||
}, |
||||
{ |
||||
"author": "gamert", |
||||
"title": "ComfyUI_tagger", |
||||
"reference": "https://github.com/gamert/ComfyUI_tagger", |
||||
"files": [ |
||||
"https://github.com/gamert/ComfyUI_tagger" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Nodes: CLIPTextEncodeTaggerDD, ImageTaggerDD" |
||||
}, |
||||
{ |
||||
"author": "YinBailiang", |
||||
"title": "MergeBlockWeighted_fo_ComfyUI", |
||||
"reference": "https://github.com/YinBailiang/MergeBlockWeighted_fo_ComfyUI", |
||||
"files": [ |
||||
"https://github.com/YinBailiang/MergeBlockWeighted_fo_ComfyUI" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Nodes: MergeBlockWeighted" |
||||
}, |
||||
{ |
||||
"author": "trojblue", |
||||
"title": "trNodes", |
||||
"reference": "https://github.com/trojblue/trNodes", |
||||
"files": [ |
||||
"https://github.com/trojblue/trNodes" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Nodes: image_layering, color_correction, model_router" |
||||
}, |
||||
{ |
||||
"author": "szhublox", |
||||
"title": "Auto-MBW", |
||||
"reference": "https://github.com/szhublox/ambw_comfyui", |
||||
"files": [ |
||||
"https://github.com/szhublox/ambw_comfyui" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Auto-MBW for ComfyUI loosely based on sdweb-auto-MBW. Nodes: auto merge block weighted" |
||||
}, |
||||
{ |
||||
"author": "asd417", |
||||
"title": "CheckpointTomeLoader", |
||||
"reference": "https://github.com/asd417/tomeSD_for_Comfy", |
||||
"files": [ |
||||
"https://github.com/asd417/tomeSD_for_Comfy/raw/main/tomeloader.py" |
||||
], |
||||
"install_type": "copy", |
||||
"description": "tomeSD(https://github.com/dbolya/tomesd) applied to ComfyUI stable diffusion UI using custom node" |
||||
}, |
||||
{ |
||||
"author": "city96", |
||||
"title": "ComfyUI_NetDist", |
||||
"reference": "https://github.com/city96/ComfyUI_NetDist", |
||||
"files": [ |
||||
"https://github.com/city96/ComfyUI_NetDist" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Run ComfyUI workflows on multiple local GPUs/networked machines. Nodes: Remote images, Local Remote control" |
||||
}, |
||||
{ |
||||
"author": "Kaharos94", |
||||
"title": "ComfyUI-Saveaswebp", |
||||
"reference": "https://github.com/Kaharos94/ComfyUI-Saveaswebp", |
||||
"files": [ |
||||
"https://github.com/Kaharos94/ComfyUI-Saveaswebp/raw/main/Save_as_webp.py" |
||||
], |
||||
"install_type": "copy", |
||||
"description": "Save a picture as Webp file in Comfy + Workflow loading" |
||||
}, |
||||
{ |
||||
"author": "chenbaiyujason", |
||||
"title": "sc-node-comfyui", |
||||
"reference": "https://github.com/chenbaiyujason/sc-node-comfyui", |
||||
"files": [ |
||||
"https://github.com/chenbaiyujason/sc-node-comfyui" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Nodes for GPT interaction and text manipulation" |
||||
}, |
||||
{ |
||||
"author": "SLAPaper", |
||||
"title": "ComfyUI-Image-Selector", |
||||
"reference": "https://github.com/SLAPaper/ComfyUI-Image-Selector", |
||||
"files": [ |
||||
"https://github.com/SLAPaper/ComfyUI-Image-Selector" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "A custom node for ComfyUI, which can select one or some of images from a batch." |
||||
}, |
||||
{ |
||||
"author": "flyingshutter", |
||||
"title": "As_ComfyUI_CustomNodes", |
||||
"reference": "https://github.com/flyingshutter/As_ComfyUI_CustomNodes", |
||||
"files": [ |
||||
"https://github.com/flyingshutter/As_ComfyUI_CustomNodes" |
||||
], |
||||
"install_type": "git-clone", |
||||
"description": "Manipulation nodes for Image, Latent" |
||||
}, |
||||
{ |
||||
"author": "AlekPet", |
||||
"title": "TranslateCLIPTextEncode", |
||||
"reference": "https://github.com/AlekPet/comfyui_translate_clip_text_encode_node", |
||||
"files": [ |
||||
"https://github.com/AlekPet/comfyui_translate_clip_text_encode_node/raw/main/translate_clip_text_encode_node.py" |
||||
], |
||||
"install_type": "copy", |
||||
"description": "Custom node for ComfyUI, translate promt from other languages into english" |
||||
}, |
||||
{ |
||||
"author": "theally", |
||||
"title": "TheAlly's Custom Nodes", |
||||
"reference": "https://civitai.com/models/19625?modelVersionId=23296", |
||||
"files": [ |
||||
"https://civitai.com/api/download/models/25114", |
||||
"https://civitai.com/api/download/models/24679", |
||||
"https://civitai.com/api/download/models/24154", |
||||
"https://civitai.com/api/download/models/23884", |
||||
"https://civitai.com/api/download/models/23649", |
||||
"https://civitai.com/api/download/models/23467", |
||||
"https://civitai.com/api/download/models/23296" |
||||
], |
||||
"install_type": "unzip", |
||||
"description": "Custom nodes for ComfyUI by TheAlly." |
||||
}, |
||||
{ |
||||
"author": "xss", |
||||
"title": "Custom Nodes by xss", |
||||
"reference": "https://civitai.com/models/24869/comfyui-custom-nodes-by-xss", |
||||
"files": [ |
||||
"https://civitai.com/api/download/models/32717", |
||||
"https://civitai.com/api/download/models/47776", |
||||
"https://civitai.com/api/download/models/29772", |
||||
"https://civitai.com/api/download/models/31618", |
||||
"https://civitai.com/api/download/models/31591", |
||||
"https://civitai.com/api/download/models/29773", |
||||
"https://civitai.com/api/download/models/29774", |
||||
"https://civitai.com/api/download/models/29755", |
||||
"https://civitai.com/api/download/models/29750" |
||||
], |
||||
"install_type": "unzip", |
||||
"description": "Various image processing nodes." |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,550 @@
|
||||
import { app } from "/scripts/app.js"; |
||||
import { ComfyDialog, $el } from "/scripts/ui.js"; |
||||
import {ComfyWidgets} from "../../scripts/widgets.js"; |
||||
|
||||
async function getCustomNodes() { |
||||
const response = await fetch('/customnode/getlist', { |
||||
method: 'POST', |
||||
headers: { 'Content-Type': 'application/json' }, |
||||
body: JSON.stringify({}) |
||||
}); |
||||
|
||||
const data = await response.json(); |
||||
return data; |
||||
} |
||||
|
||||
async function getModelList() { |
||||
const response = await fetch('/externalmodel/getlist', { |
||||
method: 'POST', |
||||
headers: { 'Content-Type': 'application/json' }, |
||||
body: JSON.stringify({}) |
||||
}); |
||||
|
||||
const data = await response.json(); |
||||
return data; |
||||
} |
||||
|
||||
async function install_custom_node(target) { |
||||
if(CustomNodesInstaller.instance) { |
||||
CustomNodesInstaller.instance.startInstall(target); |
||||
|
||||
try { |
||||
const response = await fetch('/customnode/install', { |
||||
method: 'POST', |
||||
headers: { 'Content-Type': 'application/json' }, |
||||
body: JSON.stringify(target) |
||||
}); |
||||
|
||||
const status = await response.json(); |
||||
app.ui.dialog.close(); |
||||
target.installed = 'True'; |
||||
return true; |
||||
} |
||||
catch(exception) { |
||||
app.ui.dialog.show(`Install failed: ${target.title} / ${exception}`); |
||||
app.ui.dialog.element.style.zIndex = 9999; |
||||
return false; |
||||
} |
||||
finally { |
||||
CustomNodesInstaller.instance.stopInstall(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
async function install_model(target) { |
||||
if(ModelInstaller.instance) { |
||||
ModelInstaller.instance.startInstall(target); |
||||
|
||||
try { |
||||
const response = await fetch('/model/install', { |
||||
method: 'POST', |
||||
headers: { 'Content-Type': 'application/json' }, |
||||
body: JSON.stringify(target) |
||||
}); |
||||
|
||||
const status = await response.json(); |
||||
app.ui.dialog.close(); |
||||
target.installed = 'True'; |
||||
return true; |
||||
} |
||||
catch(exception) { |
||||
app.ui.dialog.show(`Install failed: ${target.title} / ${exception}`); |
||||
app.ui.dialog.element.style.zIndex = 9999; |
||||
return false; |
||||
} |
||||
finally { |
||||
ModelInstaller.instance.stopInstall(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
class CustomNodesInstaller extends ComfyDialog { |
||||
static instance = null; |
||||
|
||||
install_buttons = []; |
||||
message_box = null; |
||||
data = null; |
||||
|
||||
clear() { |
||||
this.install_buttons = []; |
||||
this.message_box = null; |
||||
this.data = null; |
||||
} |
||||
|
||||
constructor() { |
||||
super(); |
||||
this.element = $el("div.comfy-modal", { parent: document.body }, []); |
||||
} |
||||
|
||||
startInstall(target) { |
||||
console.log(target); |
||||
this.message_box.innerHTML = `<BR><font color="green">Installing '${target.title}'</font>`; |
||||
|
||||
for(let i in this.install_buttons) { |
||||
this.install_buttons[i].disabled = true; |
||||
this.install_buttons[i].style.backgroundColor = 'gray'; |
||||
} |
||||
} |
||||
|
||||
stopInstall() { |
||||
this.message_box.innerHTML = '<BR>To apply the installed custom node, please restart ComfyUI.'; |
||||
|
||||
for(let i in this.install_buttons) { |
||||
switch(this.data[i].installed) |
||||
{ |
||||
case 'True': |
||||
this.install_buttons[i].innerHTML = 'Installed'; |
||||
this.install_buttons[i].style.backgroundColor = 'green'; |
||||
this.install_buttons[i].disabled = true; |
||||
break; |
||||
case 'False': |
||||
this.install_buttons[i].innerHTML = 'Install'; |
||||
this.install_buttons[i].style.backgroundColor = 'black'; |
||||
this.install_buttons[i].disabled = false; |
||||
break; |
||||
default: |
||||
this.install_buttons[i].innerHTML = 'Try Install'; |
||||
this.install_buttons[i].style.backgroundColor = 'brown'; |
||||
this.install_buttons[i].disabled = false; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
async createGrid() { |
||||
var grid = document.createElement('table'); |
||||
grid.setAttribute('id', 'custom-nodes-grid'); |
||||
|
||||
grid.style.position = "relative"; |
||||
grid.style.display = "inline-block"; |
||||
grid.style.width = "100%" |
||||
|
||||
var headerRow = document.createElement('tr'); |
||||
var header1 = document.createElement('th'); |
||||
header1.innerHTML = ' ID '; |
||||
header1.style.width = "20px"; |
||||
var header2 = document.createElement('th'); |
||||
header2.innerHTML = 'Author'; |
||||
header2.style.width = "150px"; |
||||
var header3 = document.createElement('th'); |
||||
header3.innerHTML = 'Name'; |
||||
header3.style.width = "200px"; |
||||
var header4 = document.createElement('th'); |
||||
header4.innerHTML = 'Description'; |
||||
header4.style.width = "500px"; |
||||
var header5 = document.createElement('th'); |
||||
header5.innerHTML = 'Install'; |
||||
header5.style.width = "130px"; |
||||
headerRow.appendChild(header1); |
||||
headerRow.appendChild(header2); |
||||
headerRow.appendChild(header3); |
||||
headerRow.appendChild(header4); |
||||
headerRow.appendChild(header5); |
||||
|
||||
headerRow.style.backgroundColor = "Black"; |
||||
headerRow.style.color = "White"; |
||||
headerRow.style.textAlign = "center"; |
||||
headerRow.style.width = "100%"; |
||||
headerRow.style.padding = "0"; |
||||
grid.appendChild(headerRow); |
||||
|
||||
if(this.data) |
||||
for (var i = 0; i < this.data.length; i++) { |
||||
const data = this.data[i]; |
||||
var dataRow = document.createElement('tr'); |
||||
var data1 = document.createElement('td'); |
||||
data1.style.textAlign = "center"; |
||||
data1.innerHTML = i+1; |
||||
var data2 = document.createElement('td'); |
||||
data2.innerHTML = ` ${data.author}`; |
||||
var data3 = document.createElement('td'); |
||||
data3.innerHTML = ` <a href=${data.reference} target="_blank"><font color="skyblue"><b>${data.title}</b></font></a>`; |
||||
var data4 = document.createElement('td'); |
||||
data4.innerHTML = data.description; |
||||
var data5 = document.createElement('td'); |
||||
data5.style.textAlign = "center"; |
||||
|
||||
var installBtn = document.createElement('button'); |
||||
|
||||
this.install_buttons.push(installBtn); |
||||
|
||||
switch(data.installed) { |
||||
case 'True': |
||||
installBtn.innerHTML = 'Installed'; |
||||
installBtn.style.backgroundColor = 'green'; |
||||
installBtn.disabled = true; |
||||
break; |
||||
case 'False': |
||||
installBtn.innerHTML = 'Install'; |
||||
installBtn.style.backgroundColor = 'black'; |
||||
break; |
||||
default: |
||||
installBtn.innerHTML = 'Try Install'; |
||||
installBtn.style.backgroundColor = 'brown'; |
||||
} |
||||
|
||||
installBtn.addEventListener('click', function() { |
||||
install_custom_node(data); |
||||
}); |
||||
|
||||
data5.appendChild(installBtn); |
||||
|
||||
dataRow.style.backgroundColor = "#444444"; |
||||
dataRow.style.color = "White"; |
||||
dataRow.style.textAlign = "left"; |
||||
|
||||
dataRow.appendChild(data1); |
||||
dataRow.appendChild(data2); |
||||
dataRow.appendChild(data3); |
||||
dataRow.appendChild(data4); |
||||
dataRow.appendChild(data5); |
||||
grid.appendChild(dataRow); |
||||
} |
||||
|
||||
const panel = document.createElement('div'); |
||||
panel.style.height = "400px"; |
||||
panel.style.width = "1000px"; |
||||
panel.style.overflowY = "scroll"; |
||||
|
||||
panel.appendChild(grid); |
||||
this.element.appendChild(panel); |
||||
} |
||||
|
||||
async createControls() { |
||||
var close_button = document.createElement("button"); |
||||
close_button.innerHTML = "Close"; |
||||
close_button.onclick = () => { this.close(); } |
||||
close_button.style.display = "inline-block"; |
||||
|
||||
this.message_box = $el('div', {id:'custom-installer-message'}, [$el('br'), '']); |
||||
this.message_box.style.height = '60px'; |
||||
this.message_box.style.verticalAlign = 'middle'; |
||||
|
||||
this.element.appendChild(this.message_box); |
||||
this.element.appendChild(close_button); |
||||
} |
||||
|
||||
async show() { |
||||
try { |
||||
this.clear(); |
||||
this.data = (await getCustomNodes()).custom_nodes; |
||||
|
||||
while (this.element.children.length) { |
||||
this.element.removeChild(this.element.children[0]); |
||||
} |
||||
|
||||
await this.createGrid(); |
||||
this.createControls(); |
||||
this.element.style.display = "block"; |
||||
} |
||||
catch(exception) { |
||||
app.ui.dialog.show(`Failed to get custom node list. / ${exception}`); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// -----------
|
||||
class ModelInstaller extends ComfyDialog { |
||||
static instance = null; |
||||
|
||||
install_buttons = []; |
||||
message_box = null; |
||||
data = null; |
||||
|
||||
clear() { |
||||
this.install_buttons = []; |
||||
this.message_box = null; |
||||
this.data = null; |
||||
} |
||||
|
||||
constructor() { |
||||
super(); |
||||
this.element = $el("div.comfy-modal", { parent: document.body }, []); |
||||
} |
||||
|
||||
createControls() { |
||||
return [ |
||||
$el("button", { |
||||
type: "button", |
||||
textContent: "Close", |
||||
onclick: () => { this.close(); } |
||||
}) |
||||
]; |
||||
} |
||||
|
||||
startInstall(target) { |
||||
this.message_box.innerHTML = `<BR><font color="green">Installing '${target.name}'</font>`; |
||||
|
||||
for(let i in this.install_buttons) { |
||||
this.install_buttons[i].disabled = true; |
||||
this.install_buttons[i].style.backgroundColor = 'gray'; |
||||
} |
||||
} |
||||
|
||||
stopInstall() { |
||||
this.message_box.innerHTML = "<BR>To apply the installed model, please click the 'Refresh' button on the main menu."; |
||||
|
||||
for(let i in this.install_buttons) { |
||||
switch(this.data[i].installed) |
||||
{ |
||||
case 'True': |
||||
this.install_buttons[i].innerHTML = 'Installed'; |
||||
this.install_buttons[i].style.backgroundColor = 'green'; |
||||
this.install_buttons[i].disabled = true; |
||||
break; |
||||
default: |
||||
this.install_buttons[i].innerHTML = 'Install'; |
||||
this.install_buttons[i].style.backgroundColor = 'black'; |
||||
this.install_buttons[i].disabled = false; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
async createGrid(models_json) { |
||||
var grid = document.createElement('table'); |
||||
grid.setAttribute('id', 'external-models-grid'); |
||||
|
||||
grid.style.position = "relative"; |
||||
grid.style.display = "inline-block"; |
||||
grid.style.width = "100%" |
||||
|
||||
var headerRow = document.createElement('tr'); |
||||
var header1 = document.createElement('th'); |
||||
header1.innerHTML = ' ID '; |
||||
header1.style.width = "20px"; |
||||
var header2 = document.createElement('th'); |
||||
header2.innerHTML = 'Type'; |
||||
header2.style.width = "100px"; |
||||
var header3 = document.createElement('th'); |
||||
header3.innerHTML = 'Base'; |
||||
header3.style.width = "50px"; |
||||
var header4 = document.createElement('th'); |
||||
header4.innerHTML = 'Name'; |
||||
header4.style.width = "200px"; |
||||
var header5 = document.createElement('th'); |
||||
header5.innerHTML = 'Filename'; |
||||
header5.style.width = "250px"; |
||||
header5.style.tableLayout = "fixed"; |
||||
var header6 = document.createElement('th'); |
||||
header6.innerHTML = 'description'; |
||||
header6.style.width = "380px"; |
||||
var header_down = document.createElement('th'); |
||||
header_down.innerHTML = 'Download'; |
||||
header_down.style.width = "50px"; |
||||
|
||||
headerRow.appendChild(header1); |
||||
headerRow.appendChild(header2); |
||||
headerRow.appendChild(header3); |
||||
headerRow.appendChild(header4); |
||||
headerRow.appendChild(header5); |
||||
headerRow.appendChild(header6); |
||||
headerRow.appendChild(header_down); |
||||
|
||||
headerRow.style.backgroundColor = "Black"; |
||||
headerRow.style.color = "White"; |
||||
headerRow.style.textAlign = "center"; |
||||
headerRow.style.width = "100%"; |
||||
headerRow.style.padding = "0"; |
||||
grid.appendChild(headerRow); |
||||
|
||||
if(this.data) |
||||
for (var i = 0; i < this.data.length; i++) { |
||||
const data = this.data[i]; |
||||
var dataRow = document.createElement('tr'); |
||||
var data1 = document.createElement('td'); |
||||
data1.style.textAlign = "center"; |
||||
data1.innerHTML = i+1; |
||||
var data2 = document.createElement('td'); |
||||
data2.innerHTML = ` ${data.type}`; |
||||
var data3 = document.createElement('td'); |
||||
data3.innerHTML = ` ${data.base}`; |
||||
var data4 = document.createElement('td'); |
||||
data4.innerHTML = ` <a href=${data.reference} target="_blank"><font color="skyblue"><b>${data.name}</b></font></a>`; |
||||
var data5 = document.createElement('td'); |
||||
data5.innerHTML = ` ${data.filename}`; |
||||
data5.style.wordBreak = "break-all"; |
||||
var data6 = document.createElement('td'); |
||||
data6.innerHTML = data.description; |
||||
data6.style.wordBreak = "break-all"; |
||||
var data_install = document.createElement('td'); |
||||
var installBtn = document.createElement('button'); |
||||
data_install.style.textAlign = "center"; |
||||
|
||||
installBtn.innerHTML = 'Install'; |
||||
this.install_buttons.push(installBtn); |
||||
|
||||
switch(data.installed) { |
||||
case 'True': |
||||
installBtn.innerHTML = 'Installed'; |
||||
installBtn.style.backgroundColor = 'green'; |
||||
installBtn.disabled = true; |
||||
break; |
||||
default: |
||||
installBtn.innerHTML = 'Install'; |
||||
installBtn.style.backgroundColor = 'black'; |
||||
break; |
||||
} |
||||
|
||||
installBtn.addEventListener('click', function() { |
||||
install_model(data); |
||||
}); |
||||
|
||||
data_install.appendChild(installBtn); |
||||
|
||||
dataRow.style.backgroundColor = "#444444"; |
||||
dataRow.style.color = "White"; |
||||
dataRow.style.textAlign = "left"; |
||||
|
||||
dataRow.appendChild(data1); |
||||
dataRow.appendChild(data2); |
||||
dataRow.appendChild(data3); |
||||
dataRow.appendChild(data4); |
||||
dataRow.appendChild(data5); |
||||
dataRow.appendChild(data6); |
||||
dataRow.appendChild(data_install); |
||||
grid.appendChild(dataRow); |
||||
} |
||||
|
||||
const panel = document.createElement('div'); |
||||
panel.style.height = "400px"; |
||||
panel.style.width = "1050px"; |
||||
panel.style.overflowY = "scroll"; |
||||
|
||||
panel.appendChild(grid); |
||||
this.element.appendChild(panel); |
||||
} |
||||
|
||||
async createControls() { |
||||
var close_button = document.createElement("button"); |
||||
close_button.innerHTML = "Close"; |
||||
close_button.onclick = () => { this.close(); } |
||||
close_button.style.display = "inline-block"; |
||||
|
||||
this.message_box = $el('div', {id:'custom-download-message'}, [$el('br'), '']); |
||||
this.message_box.style.height = '60px'; |
||||
this.message_box.style.verticalAlign = 'middle'; |
||||
|
||||
this.element.appendChild(this.message_box); |
||||
this.element.appendChild(close_button); |
||||
} |
||||
|
||||
async show() { |
||||
try { |
||||
this.clear(); |
||||
this.data = (await getModelList()).models; |
||||
|
||||
while (this.element.children.length) { |
||||
this.element.removeChild(this.element.children[0]); |
||||
} |
||||
|
||||
await this.createGrid(); |
||||
this.createControls(); |
||||
this.element.style.display = "block"; |
||||
} |
||||
catch(exception) { |
||||
app.ui.dialog.show(`Failed to get external model list. / ${exception}`); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// -----------
|
||||
class ManagerMenuDialog extends ComfyDialog { |
||||
static instance = null; |
||||
|
||||
createButtons() { |
||||
const res = |
||||
[ |
||||
$el("tr.td", {width:"100%"}, [$el("font", {size:6, color:"white"}, ["Manager Menu"])]), |
||||
$el("br", {}, []), |
||||
$el("button", { |
||||
type: "button", |
||||
textContent: "Install Custom Nodes", |
||||
onclick: |
||||
() => { |
||||
if(!CustomNodesInstaller.instance) |
||||
CustomNodesInstaller.instance = new CustomNodesInstaller(app); |
||||
CustomNodesInstaller.instance.show(); |
||||
} |
||||
}), |
||||
|
||||
$el("button", { |
||||
type: "button", |
||||
textContent: "Install Models", |
||||
onclick: |
||||
() => { |
||||
if(!ModelInstaller.instance) |
||||
ModelInstaller.instance = new ModelInstaller(app); |
||||
ModelInstaller.instance.show(); |
||||
} |
||||
}), |
||||
|
||||
$el("button", { |
||||
type: "button", |
||||
textContent: "Close", |
||||
onclick: () => this.close(), |
||||
}) |
||||
]; |
||||
|
||||
console.log(res); |
||||
res[0].style.backgroundColor = "black"; |
||||
res[0].style.textAlign = "center"; |
||||
res[0].style.height = "45px"; |
||||
return res; |
||||
} |
||||
|
||||
constructor() { |
||||
super(); |
||||
this.element = $el("div.comfy-modal", { parent: document.body }, |
||||
[ $el("div.comfy-modal-content", |
||||
[...this.createButtons()]), |
||||
]); |
||||
} |
||||
|
||||
show() { |
||||
this.element.style.display = "block"; |
||||
} |
||||
} |
||||
|
||||
app.registerExtension({ |
||||
name: "Comfy.ManagerMenu", |
||||
|
||||
async setup() { |
||||
const menu = document.querySelector(".comfy-menu"); |
||||
const separator = document.createElement("hr"); |
||||
|
||||
separator.style.margin = "20px 0"; |
||||
separator.style.width = "100%"; |
||||
menu.append(separator); |
||||
|
||||
const managerButton = document.createElement("button"); |
||||
managerButton.textContent = "Manager"; |
||||
managerButton.onclick = () => { |
||||
if(!ManagerMenuDialog.instance) |
||||
ManagerMenuDialog.instance = new ManagerMenuDialog(); |
||||
ManagerMenuDialog.instance.show(); |
||||
} |
||||
menu.append(managerButton); |
||||
} |
||||
}); |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 179 KiB |
@ -0,0 +1,414 @@
|
||||
{ |
||||
"models": [ |
||||
{ |
||||
"name": "v1-5-pruned-emaonly.ckpt", |
||||
"type": "checkpoints", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Stable Diffusion 1.5 base model", |
||||
"reference": "https://huggingface.co/runwayml/stable-diffusion-v1-5", |
||||
"filename": "v1-5-pruned-emaonly.ckpt", |
||||
"url": "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.ckpt" |
||||
}, |
||||
{ |
||||
"name": "v2-1_512-ema-pruned.safetensors", |
||||
"type": "checkpoints", |
||||
"base": "SD2", |
||||
"save_path": "default", |
||||
"description": "Stable Diffusion 2 base model (512)", |
||||
"reference": "https://huggingface.co/stabilityai/stable-diffusion-2-1-base", |
||||
"filename": "v2-1_512-ema-pruned.safetensors", |
||||
"url": "https://huggingface.co/stabilityai/stable-diffusion-2-1-base/resolve/main/v2-1_512-ema-pruned.safetensors" |
||||
}, |
||||
{ |
||||
"name": "v2-1_768-ema-pruned.safetensors", |
||||
"type": "checkpoints", |
||||
"base": "SD2", |
||||
"save_path": "default", |
||||
"description": "Stable Diffusion 2 base model (768)", |
||||
"reference": "https://huggingface.co/stabilityai/stable-diffusion-2-1", |
||||
"filename": "v2-1_768-ema-pruned.safetensors", |
||||
"url": "https://huggingface.co/stabilityai/stable-diffusion-2-1/resolve/main/v2-1_768-ema-pruned.safetensors" |
||||
}, |
||||
{ |
||||
"name": "AbyssOrangeMix2 (hard)", |
||||
"type": "checkpoints", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "AbyssOrangeMix2 - hard version (anime style)", |
||||
"reference": "https://huggingface.co/WarriorMama777/OrangeMixs", |
||||
"filename": "AbyssOrangeMix2_hard.safetensors", |
||||
"url": "https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix2/AbyssOrangeMix2_hard.safetensors" |
||||
}, |
||||
{ |
||||
"name": "AbyssOrangeMix3 A1", |
||||
"type": "checkpoints", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "AbyssOrangeMix3 - A1 (anime style)", |
||||
"reference": "https://huggingface.co/WarriorMama777/OrangeMixs", |
||||
"filename": "AOM3A1_orangemixs.safetensors", |
||||
"url": "https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix3/AOM3A1_orangemixs.safetensors" |
||||
}, |
||||
{ |
||||
"name": "AbyssOrangeMix3 A3", |
||||
"type": "checkpoints", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "AbyssOrangeMix - A3 (anime style)", |
||||
"reference": "https://huggingface.co/WarriorMama777/OrangeMixs", |
||||
"filename": "AOM3A3_orangemixs.safetensors", |
||||
"url": "https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix3/AOM3A3_orangemixs.safetensors" |
||||
}, |
||||
{ |
||||
"name": "Anything v3 (fp16; pruned)", |
||||
"type": "checkpoints", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Anything v3 (anime style)", |
||||
"reference": "https://huggingface.co/Linaqruf/anything-v3.0", |
||||
"filename": "anything-v3-fp16-pruned.safetensors", |
||||
"url": "https://huggingface.co/Linaqruf/anything-v3.0/resolve/main/anything-v3-fp16-pruned.safetensors" |
||||
}, |
||||
{ |
||||
"name": "Waifu Diffusion 1.5 (fp16)", |
||||
"type": "checkpoints", |
||||
"base": "SD2.1", |
||||
"save_path": "default", |
||||
"description": "Waifu Diffusion 1.5", |
||||
"reference": "ttps://huggingface.co/waifu-diffusion/wd-1-5-beta2", |
||||
"filename": "wd-1-5-beta2-fp16.safetensors", |
||||
"url": "https://huggingface.co/waifu-diffusion/wd-1-5-beta2/resolve/main/checkpoints/wd-1-5-beta2-fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "illuminatiDiffusionV1_v11 unCLIP model", |
||||
"type": "unclip", |
||||
"base": "SD2.1", |
||||
"save_path": "default", |
||||
"description": "Mix model (SD2.1 unCLIP + illuminatiDiffusionV1_v11)", |
||||
"reference": "https://huggingface.co/comfyanonymous/illuminatiDiffusionV1_v11_unCLIP", |
||||
"filename": "illuminatiDiffusionV1_v11-unclip-h-fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/illuminatiDiffusionV1_v11_unCLIP/resolve/main/illuminatiDiffusionV1_v11-unclip-h-fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "Waifu Diffusion 1.5 unCLIP model", |
||||
"type": "unclip", |
||||
"base": "SD2.1", |
||||
"save_path": "default", |
||||
"description": "Mix model (SD2.1 unCLIP + Waifu Diffusion 1.5)", |
||||
"reference": "https://huggingface.co/comfyanonymous/wd-1.5-beta2_unCLIP", |
||||
"filename": "wd-1-5-beta2-aesthetic-unclip-h-fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/wd-1.5-beta2_unCLIP/resolve/main/wd-1-5-beta2-aesthetic-unclip-h-fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "vae-ft-mse-840000-ema-pruned", |
||||
"type": "VAE", |
||||
"base": "VAE", |
||||
"save_path": "default", |
||||
"description": "vae-ft-mse-840000-ema-pruned", |
||||
"reference": "https://huggingface.co/stabilityai/sd-vae-ft-mse-original", |
||||
"filename": "vae-ft-mse-840000-ema-pruned.safetensors", |
||||
"url": "https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.safetensors" |
||||
}, |
||||
{ |
||||
"name": "orangemix.vae", |
||||
"type": "VAE", |
||||
"base": "VAE", |
||||
"save_path": "default", |
||||
"description": "orangemix vae model", |
||||
"reference": "https://huggingface.co/WarriorMama777/OrangeMixs", |
||||
"filename": "orangemix.vae.pt", |
||||
"url": "https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt" |
||||
}, |
||||
{ |
||||
"name": "kl-f8-anime2", |
||||
"type": "VAE", |
||||
"base": "VAE", |
||||
"save_path": "default", |
||||
"description": "kl-f8-anime2 vae model", |
||||
"reference": "https://huggingface.co/hakurei/waifu-diffusion-v1-4", |
||||
"filename": "kl-f8-anime2.ckpt", |
||||
"url": "https://huggingface.co/hakurei/waifu-diffusion-v1-4/resolve/main/vae/kl-f8-anime2.ckpt" |
||||
}, |
||||
{ |
||||
"name": "Theovercomer8's Contrast Fix (SD2.1)", |
||||
"type": "lora", |
||||
"base": "SD2.1", |
||||
"save_path": "default", |
||||
"description": "LORA: Theovercomer8's Contrast Fix (SD2.1)", |
||||
"reference": "https://civitai.com/models/8765/theovercomer8s-contrast-fix-sd15sd21-768", |
||||
"filename": "theovercomer8sContrastFix_sd21768.safetensors", |
||||
"url": "https://civitai.com/api/download/models/10350" |
||||
}, |
||||
{ |
||||
"name": "Theovercomer8's Contrast Fix (SD1.5)", |
||||
"type": "lora", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "LORA: Theovercomer8's Contrast Fix (SD1.5)", |
||||
"reference": "https://civitai.com/models/8765/theovercomer8s-contrast-fix-sd15sd21-768", |
||||
"filename": "theovercomer8sContrastFix_sd15.safetensors", |
||||
"url": "https://civitai.com/api/download/models/10638" |
||||
}, |
||||
{ |
||||
"name": "T2I-Adapter (depth)", |
||||
"type": "T2I-Adapter", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "ControlNet T2I-Adapter for depth", |
||||
"reference": "https://huggingface.co/TencentARC/T2I-Adapter", |
||||
"filename": "t2iadapter_depth_sd14v1.pth", |
||||
"url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_depth_sd14v1.pth" |
||||
}, |
||||
{ |
||||
"name": "T2I-Adapter (seg)", |
||||
"type": "T2I-Adapter", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "ControlNet T2I-Adapter for seg", |
||||
"reference": "https://huggingface.co/TencentARC/T2I-Adapter", |
||||
"filename": "t2iadapter_seg_sd14v1.pth", |
||||
"url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_seg_sd14v1.pth" |
||||
}, |
||||
{ |
||||
"name": "T2I-Adapter (sketch)", |
||||
"type": "T2I-Adapter", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "ControlNet T2I-Adapter for sketch", |
||||
"reference": "https://huggingface.co/TencentARC/T2I-Adapter", |
||||
"filename": "t2iadapter_sketch_sd14v1.pth", |
||||
"url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_sketch_sd14v1.pth" |
||||
}, |
||||
{ |
||||
"name": "T2I-Adapter (keypose)", |
||||
"type": "T2I-Adapter", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "ControlNet T2I-Adapter for keypose", |
||||
"reference": "https://huggingface.co/TencentARC/T2I-Adapter", |
||||
"filename": "t2iadapter_keypose_sd14v1.pth", |
||||
"url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_keypose_sd14v1.pth" |
||||
}, |
||||
{ |
||||
"name": "T2I-Adapter (openpose)", |
||||
"type": "T2I-Adapter", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "ControlNet T2I-Adapter for openpose", |
||||
"reference": "https://huggingface.co/TencentARC/T2I-Adapter", |
||||
"filename": "t2iadapter_openpose_sd14v1.pth", |
||||
"url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_openpose_sd14v1.pth" |
||||
}, |
||||
{ |
||||
"name": "T2I-Adapter (color)", |
||||
"type": "T2I-Adapter", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "ControlNet T2I-Adapter for color", |
||||
"reference": "https://huggingface.co/TencentARC/T2I-Adapter", |
||||
"filename": "t2iadapter_color_sd14v1.pth", |
||||
"url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_color_sd14v1.pth" |
||||
}, |
||||
{ |
||||
"name": "T2I-Adapter (canny)", |
||||
"type": "T2I-Adapter", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "ControlNet T2I-Adapter for canny", |
||||
"reference": "https://huggingface.co/TencentARC/T2I-Adapter", |
||||
"filename": "t2iadapter_canny_sd14v1.pth", |
||||
"url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_canny_sd14v1.pth" |
||||
}, |
||||
{ |
||||
"name": "T2I-Style model", |
||||
"type": "T2I-Style", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "ControlNet T2I-Adapter style model. Need to download CLIPVision model.", |
||||
"reference": "https://huggingface.co/TencentARC/T2I-Adapter", |
||||
"filename": "t2iadapter_style_sd14v1.pth", |
||||
"url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_style_sd14v1.pth" |
||||
}, |
||||
{ |
||||
"name": "CLIPVision model", |
||||
"type": "clip_vision", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "CLIPVision model (needed for styles model)", |
||||
"reference": "https://huggingface.co/openai/clip-vit-large-patch14", |
||||
"filename": "pytorch_model.bin", |
||||
"url": "https://huggingface.co/openai/clip-vit-large-patch14/resolve/main/pytorch_model.bin" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (ip2p; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (ip2p)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11e_sd15_ip2p_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_ip2p_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (shuffle; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (shuffle)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11e_sd15_shuffle_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (canny; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (canny)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11e_sd15_shuffle_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (depth; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (depth)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11f1p_sd15_depth_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/maincontrol_v11f1p_sd15_depth_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (inpaint; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (inpaint)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11p_sd15_inpaint_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_inpaint_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (lineart; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (lineart)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11p_sd15_lineart_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_lineart_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (mlsd; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (mlsd)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11p_sd15_mlsd_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_mlsd_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (normalbae; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (normalbae)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11p_sd15_normalbae_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_normalbae_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (openpose; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (openpose)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11p_sd15_openpose_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_openpose_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (scribble; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (scribble)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11p_sd15_scribble_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_scribble_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (seg; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (seg)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11p_sd15_seg_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_seg_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (softedge; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (softedge)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11p_sd15_softedge_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_softedge_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (anime; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (anime)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11p_sd15s2_lineart_anime_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15s2_lineart_anime_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "ControlNet-v1-1 (shuffle; fp16)", |
||||
"type": "controlnet", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "Safetensors/FP16 versions of the new ControlNet-v1-1 checkpoints (tile)", |
||||
"reference": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors", |
||||
"filename": "control_v11u_sd15_tile_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11u_sd15_tile_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "GLIGEN textbox (fp16; pruned)", |
||||
"type": "gligen", |
||||
"base": "SD1.5", |
||||
"save_path": "default", |
||||
"description": "GLIGEN textbox model", |
||||
"reference": "https://huggingface.co/comfyanonymous/GLIGEN_pruned_safetensors", |
||||
"filename": "control_v11u_sd15_tile_fp16.safetensors", |
||||
"url": "https://huggingface.co/comfyanonymous/GLIGEN_pruned_safetensors/resolve/main/gligen_sd14_textbox_pruned_fp16.safetensors" |
||||
}, |
||||
{ |
||||
"name": "RealESRGAN x2", |
||||
"type": "upscale", |
||||
"base": "upscale", |
||||
"save_path": "default", |
||||
"description": "RealESRGAN x2 upscaler model", |
||||
"reference": "https://huggingface.co/sberbank-ai/Real-ESRGAN", |
||||
"filename": "RealESRGAN_x2.pth", |
||||
"url": "https://huggingface.co/sberbank-ai/Real-ESRGAN/resolve/main/RealESRGAN_x2.pth" |
||||
}, |
||||
{ |
||||
"name": "RealESRGAN x4", |
||||
"type": "upscale", |
||||
"base": "upscale", |
||||
"save_path": "default", |
||||
"description": "RealESRGAN x4 upscaler model", |
||||
"reference": "https://huggingface.co/sberbank-ai/Real-ESRGAN", |
||||
"filename": "RealESRGAN_x4.pth", |
||||
"url": "https://huggingface.co/sberbank-ai/Real-ESRGAN/resolve/main/RealESRGAN_x4.pth" |
||||
} |
||||
] |
||||
} |
@ -1,288 +0,0 @@
|
||||
{ |
||||
"cells": [ |
||||
{ |
||||
"cell_type": "markdown", |
||||
"metadata": { |
||||
"id": "aaaaaaaaaa" |
||||
}, |
||||
"source": [ |
||||
"Git clone the repo and install the requirements. (ignore the pip errors about protobuf)" |
||||
] |
||||
}, |
||||
{ |
||||
"cell_type": "code", |
||||
"execution_count": null, |
||||
"metadata": { |
||||
"id": "bbbbbbbbbb" |
||||
}, |
||||
"outputs": [], |
||||
"source": [ |
||||
"#@title Environment Setup\n", |
||||
"\n", |
||||
"from pathlib import Path\n", |
||||
"\n", |
||||
"OPTIONS = {}\n", |
||||
"\n", |
||||
"USE_GOOGLE_DRIVE = False #@param {type:\"boolean\"}\n", |
||||
"UPDATE_COMFY_UI = True #@param {type:\"boolean\"}\n", |
||||
"WORKSPACE = 'ComfyUI'\n", |
||||
"OPTIONS['USE_GOOGLE_DRIVE'] = USE_GOOGLE_DRIVE\n", |
||||
"OPTIONS['UPDATE_COMFY_UI'] = UPDATE_COMFY_UI\n", |
||||
"\n", |
||||
"if OPTIONS['USE_GOOGLE_DRIVE']:\n", |
||||
" !echo \"Mounting Google Drive...\"\n", |
||||
" %cd /\n", |
||||
" \n", |
||||
" from google.colab import drive\n", |
||||
" drive.mount('/content/drive')\n", |
||||
"\n", |
||||
" WORKSPACE = \"/content/drive/MyDrive/ComfyUI\"\n", |
||||
" %cd /content/drive/MyDrive\n", |
||||
"\n", |
||||
"![ ! -d $WORKSPACE ] && echo -= Initial setup ComfyUI =- && git clone https://github.com/comfyanonymous/ComfyUI\n", |
||||
"%cd $WORKSPACE\n", |
||||
"\n", |
||||
"if OPTIONS['UPDATE_COMFY_UI']:\n", |
||||
" !echo -= Updating ComfyUI =-\n", |
||||
" !git pull\n", |
||||
"\n", |
||||
"!echo -= Install dependencies =-\n", |
||||
"!pip install xformers!=0.0.18 -r requirements.txt --extra-index-url https://download.pytorch.org/whl/cu118" |
||||
] |
||||
}, |
||||
{ |
||||
"attachments": {}, |
||||
"cell_type": "markdown", |
||||
"metadata": {}, |
||||
"source": [ |
||||
"Rich custom nodes install" |
||||
] |
||||
}, |
||||
{ |
||||
"cell_type": "code", |
||||
"execution_count": null, |
||||
"metadata": {}, |
||||
"outputs": [], |
||||
"source": [ |
||||
"# ComfyUI-Impact-Pack\n", |
||||
"!wget -c https://github.com/ltdrdata/ComfyUI-Impact-Pack/raw/Main/comfyui-impact-pack.py ./custom_nodes/\n", |
||||
"\n", |
||||
"# ComfyUI-CLIPSeg\n", |
||||
"!wget -c https://github.com/biegert/ComfyUI-CLIPSeg/raw/main/custom_nodes/clipseg.py ./custom_nodes/\n", |
||||
"!pip install -r https://raw.githubusercontent.com/biegert/ComfyUI-CLIPSeg/main/requirements.txt\n", |
||||
"\n", |
||||
"# ComfyUI_Cutoff\n", |
||||
"!git clone https://github.com/BlenderNeko/ComfyUI_Cutoff custom_nodes/ComfyUI_Cutoff\n", |
||||
"\n", |
||||
"# ComfyUI_node_Lilly\n", |
||||
"!git clone https://github.com/lilly1987/ComfyUI_node_Lilly custom_nodes/ComfyUI_node_Lilly\n", |
||||
"\n", |
||||
"# ComfyUI CLIP BLIP Node\n", |
||||
"!git clone https://github.com/paulo-coronado/comfy_clip_blip_node custom_nodes/comfy_clip_blip_node\n", |
||||
"\n" |
||||
] |
||||
}, |
||||
{ |
||||
"cell_type": "markdown", |
||||
"metadata": {}, |
||||
"source": [ |
||||
"Download some models/checkpoints/vae or custom comfyui nodes (uncomment the commands for the ones you want)" |
||||
] |
||||
}, |
||||
{ |
||||
"cell_type": "code", |
||||
"execution_count": null, |
||||
"metadata": { |
||||
"id": "dddddddddd" |
||||
}, |
||||
"outputs": [], |
||||
"source": [ |
||||
"# Checkpoints\n", |
||||
"\n", |
||||
"# SD1.5\n", |
||||
"!wget -c https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.ckpt -P ./models/checkpoints/\n", |
||||
"\n", |
||||
"# SD2\n", |
||||
"#!wget -c https://huggingface.co/stabilityai/stable-diffusion-2-1-base/resolve/main/v2-1_512-ema-pruned.safetensors -P ./models/checkpoints/\n", |
||||
"#!wget -c https://huggingface.co/stabilityai/stable-diffusion-2-1/resolve/main/v2-1_768-ema-pruned.safetensors -P ./models/checkpoints/\n", |
||||
"\n", |
||||
"# Some SD1.5 anime style\n", |
||||
"#!wget -c https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix2/AbyssOrangeMix2_hard.safetensors -P ./models/checkpoints/\n", |
||||
"#!wget -c https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix3/AOM3A1_orangemixs.safetensors -P ./models/checkpoints/\n", |
||||
"#!wget -c https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix3/AOM3A3_orangemixs.safetensors -P ./models/checkpoints/\n", |
||||
"#!wget -c https://huggingface.co/Linaqruf/anything-v3.0/resolve/main/anything-v3-fp16-pruned.safetensors -P ./models/checkpoints/\n", |
||||
"\n", |
||||
"# Waifu Diffusion 1.5 (anime style SD2.x 768-v)\n", |
||||
"#!wget -c https://huggingface.co/waifu-diffusion/wd-1-5-beta2/resolve/main/checkpoints/wd-1-5-beta2-fp16.safetensors -P ./models/checkpoints/\n", |
||||
"\n", |
||||
"\n", |
||||
"# unCLIP models\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/illuminatiDiffusionV1_v11_unCLIP/resolve/main/illuminatiDiffusionV1_v11-unclip-h-fp16.safetensors -P ./models/checkpoints/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/wd-1.5-beta2_unCLIP/resolve/main/wd-1-5-beta2-aesthetic-unclip-h-fp16.safetensors -P ./models/checkpoints/\n", |
||||
"\n", |
||||
"\n", |
||||
"# VAE\n", |
||||
"!wget -c https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.safetensors -P ./models/vae/\n", |
||||
"#!wget -c https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/VAEs/orangemix.vae.pt -P ./models/vae/\n", |
||||
"#!wget -c https://huggingface.co/hakurei/waifu-diffusion-v1-4/resolve/main/vae/kl-f8-anime2.ckpt -P ./models/vae/\n", |
||||
"\n", |
||||
"\n", |
||||
"# Loras\n", |
||||
"#!wget -c https://civitai.com/api/download/models/10350 -O ./models/loras/theovercomer8sContrastFix_sd21768.safetensors #theovercomer8sContrastFix SD2.x 768-v\n", |
||||
"#!wget -c https://civitai.com/api/download/models/10638 -O ./models/loras/theovercomer8sContrastFix_sd15.safetensors #theovercomer8sContrastFix SD1.x\n", |
||||
"\n", |
||||
"\n", |
||||
"# T2I-Adapter\n", |
||||
"#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_depth_sd14v1.pth -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_seg_sd14v1.pth -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_sketch_sd14v1.pth -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_keypose_sd14v1.pth -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_openpose_sd14v1.pth -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_color_sd14v1.pth -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_canny_sd14v1.pth -P ./models/controlnet/\n", |
||||
"\n", |
||||
"# T2I Styles Model\n", |
||||
"#!wget -c https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_style_sd14v1.pth -P ./models/style_models/\n", |
||||
"\n", |
||||
"# CLIPVision model (needed for styles model)\n", |
||||
"#!wget -c https://huggingface.co/openai/clip-vit-large-patch14/resolve/main/pytorch_model.bin -O ./models/clip_vision/clip_vit14.bin\n", |
||||
"\n", |
||||
"\n", |
||||
"# ControlNet\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_ip2p_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11e_sd15_shuffle_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_canny_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11f1p_sd15_depth_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_inpaint_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_lineart_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_mlsd_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_normalbae_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_openpose_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_scribble_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_seg_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15_softedge_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11p_sd15s2_lineart_anime_fp16.safetensors -P ./models/controlnet/\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/ControlNet-v1-1_fp16_safetensors/resolve/main/control_v11u_sd15_tile_fp16.safetensors -P ./models/controlnet/\n", |
||||
"\n", |
||||
"\n", |
||||
"# Controlnet Preprocessor nodes by Fannovel16\n", |
||||
"#!cd custom_nodes && git clone https://github.com/Fannovel16/comfy_controlnet_preprocessors; cd comfy_controlnet_preprocessors && python install.py\n", |
||||
"\n", |
||||
"\n", |
||||
"# GLIGEN\n", |
||||
"#!wget -c https://huggingface.co/comfyanonymous/GLIGEN_pruned_safetensors/resolve/main/gligen_sd14_textbox_pruned_fp16.safetensors -P ./models/gligen/\n", |
||||
"\n", |
||||
"\n", |
||||
"# ESRGAN upscale model\n", |
||||
"#!wget -c https://huggingface.co/sberbank-ai/Real-ESRGAN/resolve/main/RealESRGAN_x2.pth -P ./models/upscale_models/\n", |
||||
"#!wget -c https://huggingface.co/sberbank-ai/Real-ESRGAN/resolve/main/RealESRGAN_x4.pth -P ./models/upscale_models/\n", |
||||
"\n", |
||||
"\n" |
||||
] |
||||
}, |
||||
{ |
||||
"cell_type": "markdown", |
||||
"metadata": { |
||||
"id": "kkkkkkkkkkkkkk" |
||||
}, |
||||
"source": [ |
||||
"### Run ComfyUI with localtunnel (Recommended Way)\n", |
||||
"\n", |
||||
"\n" |
||||
] |
||||
}, |
||||
{ |
||||
"cell_type": "code", |
||||
"execution_count": null, |
||||
"metadata": { |
||||
"id": "jjjjjjjjjjjjj" |
||||
}, |
||||
"outputs": [], |
||||
"source": [ |
||||
"!npm install -g localtunnel\n", |
||||
"\n", |
||||
"import subprocess\n", |
||||
"import threading\n", |
||||
"import time\n", |
||||
"import socket\n", |
||||
"def iframe_thread(port):\n", |
||||
" while True:\n", |
||||
" time.sleep(0.5)\n", |
||||
" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", |
||||
" result = sock.connect_ex(('127.0.0.1', port))\n", |
||||
" if result == 0:\n", |
||||
" break\n", |
||||
" sock.close()\n", |
||||
" print(\"\\nComfyUI finished loading, trying to launch localtunnel (if it gets stuck here localtunnel is having issues)\")\n", |
||||
" p = subprocess.Popen([\"lt\", \"--port\", \"{}\".format(port)], stdout=subprocess.PIPE)\n", |
||||
" for line in p.stdout:\n", |
||||
" print(line.decode(), end='')\n", |
||||
"\n", |
||||
"\n", |
||||
"threading.Thread(target=iframe_thread, daemon=True, args=(8188,)).start()\n", |
||||
"\n", |
||||
"!python main.py --dont-print-server" |
||||
] |
||||
}, |
||||
{ |
||||
"cell_type": "markdown", |
||||
"metadata": { |
||||
"id": "gggggggggg" |
||||
}, |
||||
"source": [ |
||||
"### Run ComfyUI with colab iframe (use only in case the previous way with localtunnel doesn't work)\n", |
||||
"\n", |
||||
"You should see the ui appear in an iframe. If you get a 403 error, it's your firefox settings or an extension that's messing things up.\n", |
||||
"\n", |
||||
"If you want to open it in another window use the link.\n", |
||||
"\n", |
||||
"Note that some UI features like live image previews won't work because the colab iframe blocks websockets." |
||||
] |
||||
}, |
||||
{ |
||||
"cell_type": "code", |
||||
"execution_count": null, |
||||
"metadata": { |
||||
"id": "hhhhhhhhhh" |
||||
}, |
||||
"outputs": [], |
||||
"source": [ |
||||
"import threading\n", |
||||
"import time\n", |
||||
"import socket\n", |
||||
"def iframe_thread(port):\n", |
||||
" while True:\n", |
||||
" time.sleep(0.5)\n", |
||||
" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", |
||||
" result = sock.connect_ex(('127.0.0.1', port))\n", |
||||
" if result == 0:\n", |
||||
" break\n", |
||||
" sock.close()\n", |
||||
" from google.colab import output\n", |
||||
" output.serve_kernel_port_as_iframe(port, height=1024)\n", |
||||
" print(\"to open it in a window you can open this link here:\")\n", |
||||
" output.serve_kernel_port_as_window(port)\n", |
||||
"\n", |
||||
"threading.Thread(target=iframe_thread, daemon=True, args=(8188,)).start()\n", |
||||
"\n", |
||||
"!python main.py --dont-print-server" |
||||
] |
||||
} |
||||
], |
||||
"metadata": { |
||||
"accelerator": "GPU", |
||||
"colab": { |
||||
"provenance": [] |
||||
}, |
||||
"gpuClass": "standard", |
||||
"kernelspec": { |
||||
"display_name": "Python 3", |
||||
"name": "python3" |
||||
}, |
||||
"language_info": { |
||||
"name": "python" |
||||
} |
||||
}, |
||||
"nbformat": 4, |
||||
"nbformat_minor": 0 |
||||
} |
Loading…
Reference in new issue