Merge branch 'ltdrdata:main' into main

This commit is contained in:
smthemex 2024-05-11 10:18:21 +08:00 committed by GitHub
commit cb90a906ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 5647 additions and 1559 deletions

View File

@ -31,10 +31,32 @@ To install ComfyUI-Manager in addition to an existing installation of ComfyUI, y
![portable-install](misc/portable-install.png)
### Installation[method3] (Installation for linux+venv: ComfyUI + ComfyUI-Manager)
### Installation[method3] (Installation through comfy-cli: install ComfyUI and ComfyUI-Manager at once.)
> RECOMMENDED: comfy-cli provides various features to manage ComfyUI from the CLI.
* **prerequisite: python 3, git**
Windows:
```commandline
python -m venv venv
venv\Scripts\activate
pip install comfy-cli
comfy install
```
Linux/OSX:
```commandline
python -m venv venv
. venv/bin/activate
pip install comfy-cli
comfy install
```
### Installation[method4] (Installation for linux+venv: ComfyUI + ComfyUI-Manager)
To install ComfyUI with ComfyUI-Manager on Linux using a venv environment, you can follow these steps:
* **prerequisite: python-is-python3, python3-venv**
* **prerequisite: python-is-python3, python3-venv, git**
1. Download [scripts/install-comfyui-venv-linux.sh](https://github.com/ltdrdata/ComfyUI-Manager/raw/main/scripts/install-comfyui-venv-linux.sh) into empty install directory
- ComfyUI will be installed in the subdirectory of the specified directory, and the directory will contain the generated executable script.
@ -324,7 +346,7 @@ When you run the `scan.sh` script:
* https://github.com/StartHua/Comfyui_GPT_Story
* https://github.com/NielsGercama/comfyui_customsampling
* https://github.com/wrightdaniel2017/ComfyUI-VideoLipSync
* https://github.com/bxdsjs/ComfyUI-Image-preprocessing
## Roadmap

View File

@ -204,6 +204,11 @@
"id":"https://github.com/blepping/ComfyUI-sonar",
"tags":"sonar",
"description": "This extension provides some alternative functionalities of the [a/stable-diffusion-webui-sonar](https://github.com/Kahsolt/stable-diffusion-webui-sonar) extension."
},
{
"id":"https://github.com/AIFSH/ComfyUI-RVC",
"tags":"sonar",
"description": "a comfyui custom node for [a/Retrieval-based-Voice-Conversion-WebUI](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git), you can Voice-Conversion in comfyui now!"
}
]
}

225
cm-cli.py
View File

@ -6,6 +6,8 @@ import json
import asyncio
import subprocess
import shutil
import concurrent
import threading
sys.path.append(os.path.dirname(__file__))
sys.path.append(os.path.join(os.path.dirname(__file__), "glob"))
@ -23,10 +25,12 @@ if not (len(sys.argv) == 2 and sys.argv[1] in ['save-snapshot', 'restore-depende
f" [install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel <channel name>] ?[--mode [remote|local|cache]]\n"
f" [update|disable|enable|fix] all ?[--channel <channel name>] ?[--mode [remote|local|cache]]\n"
f" [simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel <channel name>] ?[--mode [remote|local|cache]]\n"
f" save-snapshot\n"
f" restore-snapshot <snapshot>\n"
f" save-snapshot ?[--output <snapshot .json/.yaml>]\n"
f" restore-snapshot <snapshot .json/.yaml> ?[--pip-non-url] ?[--pip-non-local-url] ?[--pip-local-url]\n"
f" cli-only-mode [enable|disable]\n"
f" restore-dependencies\n"
f" deps-in-workflow --workflow <workflow .json/.png> --output <output .json>\n"
f" install-deps <deps .json>\n"
f" clear\n")
exit(-1)
@ -105,10 +109,36 @@ def restore_dependencies():
i += 1
def restore_snapshot(snapshot_name):
def install_deps():
if not os.path.exists(sys.argv[2]):
print(f"File not found: {sys.argv[2]}")
exit(-1)
else:
with open(sys.argv[2], 'r', encoding="UTF-8", errors="ignore") as json_file:
json_obj = json.load(json_file)
for k in json_obj['custom_nodes'].keys():
state = core.simple_check_custom_node(k)
if state == 'installed':
continue
elif state == 'not-installed':
core.gitclone_install([k], instant_execution=True)
else: # disabled
core.gitclone_set_active([k], False)
print("Dependency installation and activation complete.")
def restore_snapshot():
global processed_install
if not os.path.exists(snapshot_name):
snapshot_name = sys.argv[2]
extras = [x for x in sys.argv if x in ['--pip-non-url', '--pip-local-url', '--pip-non-local-url']]
print(f"pips restore mode: {extras}")
if os.path.exists(snapshot_name):
snapshot_path = os.path.abspath(snapshot_name)
else:
snapshot_path = os.path.join(core.comfyui_manager_path, 'snapshots', snapshot_name)
if not os.path.exists(snapshot_path):
print(f"ERROR: `{snapshot_path}` is not exists.")
@ -140,7 +170,7 @@ def restore_snapshot(snapshot_name):
is_failed = True
print(f"Restore snapshot.")
cmd_str = [sys.executable, git_script_path, '--apply-snapshot', snapshot_path]
cmd_str = [sys.executable, git_script_path, '--apply-snapshot', snapshot_path] + extras
output = subprocess.check_output(cmd_str, cwd=custom_nodes_path, text=True)
msg_lines = output.split('\n')
extract_infos(msg_lines)
@ -224,6 +254,10 @@ def load_custom_nodes():
repo_name = y.split('/')[-1]
res[repo_name] = x
if 'id' in x:
if x['id'] not in res:
res[x['id']] = x
return res
@ -252,14 +286,14 @@ custom_node_map = load_custom_nodes()
def lookup_node_path(node_name, robust=False):
# Currently, the node_name is used directly as the node_path, but in the future, I plan to allow nicknames.
if '..' in node_name:
print(f"ERROR: invalid node name '{node_name}'")
exit(-1)
if node_name in custom_node_map:
node_path = os.path.join(custom_nodes_path, node_name)
node_url = custom_node_map[node_name]['files'][0]
repo_name = node_url.split('/')[-1]
node_path = os.path.join(custom_nodes_path, repo_name)
return node_path, custom_node_map[node_name]
elif robust:
node_path = os.path.join(custom_nodes_path, node_name)
@ -341,9 +375,55 @@ def update_node(node_name, is_all=False, cnt_msg=''):
files = node_item['files'] if node_item is not None else [node_path]
res = core.gitclone_update(files, skip_script=True, msg_prefix=f"[{cnt_msg}] ")
post_install(node_path)
if not res:
print(f"ERROR: An error occurred while uninstalling '{node_name}'.")
print(f"ERROR: An error occurred while updating '{node_name}'.")
return None
return node_path
def update_parallel():
global nodes
is_all = False
if 'all' in nodes:
is_all = True
nodes = [x for x in custom_node_map.keys() if os.path.exists(os.path.join(custom_nodes_path, x)) or os.path.exists(os.path.join(custom_nodes_path, x) + '.disabled')]
nodes = [x for x in nodes if x.lower() not in ['comfy', 'comfyui', 'all']]
total = len(nodes)
lock = threading.Lock()
processed = []
i = 0
def process_custom_node(x):
nonlocal i
nonlocal processed
with lock:
i += 1
try:
node_path = update_node(x, is_all=is_all, cnt_msg=f'{i}/{total}')
with lock:
processed.append(node_path)
except Exception as e:
print(f"ERROR: {e}")
traceback.print_exc()
with concurrent.futures.ThreadPoolExecutor(4) as executor:
for item in nodes:
executor.submit(process_custom_node, item)
i = 1
for node_path in processed:
print(f"[{i}/{total}] Post update: {node_path}")
post_install(node_path)
i += 1
def update_comfyui():
@ -362,17 +442,14 @@ def enable_node(node_name, is_all=False, cnt_msg=''):
node_path, node_item = lookup_node_path(node_name, robust=True)
files = node_item['files'] if node_item is not None else [node_path]
for x in files:
if os.path.exists(x+'.disabled'):
current_name = x+'.disabled'
os.rename(current_name, x)
print(f"{cnt_msg} [ENABLED] {node_name:50}")
elif os.path.exists(x):
print(f"{cnt_msg} [SKIPPED] {node_name:50} => Already enabled")
elif not is_all:
print(f"{cnt_msg} [SKIPPED] {node_name:50} => Not installed")
if os.path.exists(node_path+'.disabled'):
current_name = node_path+'.disabled'
os.rename(current_name, node_path)
print(f"{cnt_msg} [ENABLED] {node_name:50}")
elif os.path.exists(node_path):
print(f"{cnt_msg} [SKIPPED] {node_name:50} => Already enabled")
elif not is_all:
print(f"{cnt_msg} [SKIPPED] {node_name:50} => Not installed")
def disable_node(node_name, is_all=False, cnt_msg=''):
@ -381,18 +458,15 @@ def disable_node(node_name, is_all=False, cnt_msg=''):
node_path, node_item = lookup_node_path(node_name, robust=True)
files = node_item['files'] if node_item is not None else [node_path]
for x in files:
if os.path.exists(x):
current_name = x
new_name = x+'.disabled'
os.rename(current_name, new_name)
print(f"{cnt_msg} [DISABLED] {node_name:50}")
elif os.path.exists(x+'.disabled'):
print(f"{cnt_msg} [ SKIPPED] {node_name:50} => Already disabled")
elif not is_all:
print(f"{cnt_msg} [ SKIPPED] {node_name:50} => Not installed")
if os.path.exists(node_path):
current_name = node_path
new_name = node_path+'.disabled'
os.rename(current_name, new_name)
print(f"{cnt_msg} [DISABLED] {node_name:50}")
elif os.path.exists(node_path+'.disabled'):
print(f"{cnt_msg} [ SKIPPED] {node_name:50} => Already disabled")
elif not is_all:
print(f"{cnt_msg} [ SKIPPED] {node_name:50} => Not installed")
def show_list(kind, simple=False):
@ -419,7 +493,8 @@ def show_list(kind, simple=False):
if simple:
print(f"{k:50}")
else:
print(f"{prefix} {k:50}(author: {v['author']})")
short_id = v.get('id', "")
print(f"{prefix} {k:50} {short_id:20} (author: {v['author']})")
# unregistered nodes
candidates = os.listdir(os.path.realpath(custom_nodes_path))
@ -451,7 +526,7 @@ def show_list(kind, simple=False):
if simple:
print(f"{k:50}")
else:
print(f"{prefix} {k:50}(author: N/A)")
print(f"{prefix} {k:50} {'':20} (author: N/A)")
def show_snapshot(simple_mode=False):
@ -486,6 +561,61 @@ def cancel():
os.remove(restore_snapshot_path)
def save_snapshot():
output_path = None
for i in range(len(sys.argv)):
if sys.argv[i] == '--output':
if len(sys.argv) >= i:
output_path = sys.argv[i+1]
return core.save_snapshot_with_postfix('snapshot', output_path)
def auto_save_snapshot():
return core.save_snapshot_with_postfix('cli-autosave')
def deps_in_workflow():
input_path = None
output_path = None
for i in range(len(sys.argv)):
if sys.argv[i] == '--workflow' and len(sys.argv) > i and not sys.argv[i+1].startswith('-'):
input_path = sys.argv[i+1]
elif sys.argv[i] == '--output' and len(sys.argv) > i and not sys.argv[i+1].startswith('-'):
output_path = sys.argv[i+1]
if input_path is None:
print(f"missing arguments: --workflow <path>")
exit(-1)
elif not os.path.exists(input_path):
print(f"File not found: {input_path}")
exit(-1)
if output_path is None:
print(f"missing arguments: --output <path>")
exit(-1)
used_exts, unknown_nodes = asyncio.run(core.extract_nodes_from_workflow(input_path, mode=mode, channel_url=channel))
custom_nodes = {}
for x in used_exts:
custom_nodes[x] = { 'state': core.simple_check_custom_node(x),
'hash': '-'
}
res = {
'custom_nodes': custom_nodes,
'unknown_nodes': list(unknown_nodes)
}
with open(output_path, "w", encoding='utf-8') as output_file:
json.dump(res, output_file, indent=4)
print(f"Workflow dependencies are being saved into {output_path}.")
def for_each_nodes(act, allow_all=True):
global nodes
@ -520,20 +650,32 @@ elif op == 'uninstall':
for_each_nodes(uninstall_node)
elif op == 'update':
if 'all' in nodes:
auto_save_snapshot()
for x in nodes:
if x.lower() in ['comfyui', 'comfy', 'all']:
update_comfyui()
break
for_each_nodes(update_node, allow_all=True)
update_parallel()
elif op == 'disable':
if 'all' in nodes:
auto_save_snapshot()
for_each_nodes(disable_node, allow_all=True)
elif op == 'enable':
if 'all' in nodes:
auto_save_snapshot()
for_each_nodes(enable_node, allow_all=True)
elif op == 'fix':
if 'all' in nodes:
auto_save_snapshot()
for_each_nodes(fix_node, allow_all=True)
elif op == 'show':
@ -565,16 +707,23 @@ elif op == 'cli-only-mode':
else:
print(f"\ninvalid value for cli-only-mode: {sys.argv[2]}\n")
elif op == "deps-in-workflow":
deps_in_workflow()
elif op == 'save-snapshot':
path = core.save_snapshot_with_postfix('snapshot')
path = save_snapshot()
print(f"Current snapshot is saved as `{path}`")
elif op == 'restore-snapshot':
restore_snapshot(sys.argv[2])
restore_snapshot()
elif op == 'restore-dependencies':
restore_dependencies()
elif op == 'install-deps':
auto_save_snapshot()
install_deps()
elif op == 'clear':
cancel()

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,8 @@
```
-= ComfyUI-Manager CLI (V2.22) =-
-= ComfyUI-Manager CLI (V2.24) =-
python cm-cli.py [OPTIONS]
@ -12,12 +13,11 @@ OPTIONS:
[install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel <channel name>] ?[--mode [remote|local|cache]]
[update|disable|enable|fix] all ?[--channel <channel name>] ?[--mode [remote|local|cache]]
[simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel <channel name>] ?[--mode [remote|local|cache]]
save-snapshot
restore-snapshot <snapshot>
save-snapshot ?[--output <snapshot .json/.yaml>]
restore-snapshot <snapshot .json/.yaml> ?[--pip-non-url] ?[--pip-non-local-url] ?[--pip-local-url]
cli-only-mode [enable|disable]
restore-dependencies
clear
```
## How To Use?
@ -52,7 +52,7 @@ OPTIONS:
Executing a command like `python cm-cli.py show installed` will display detailed information about the installed custom nodes.
```
-= ComfyUI-Manager CLI (V2.21.1) =-
-= ComfyUI-Manager CLI (V2.24) =-
FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json
[ ENABLED ] ComfyUI-Manager (author: Dr.Lt.Data)
@ -69,7 +69,7 @@ FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main
Using a command like `python cm-cli.py simple-show installed` will simply display information about the installed custom nodes.
```
-= ComfyUI-Manager CLI (V2.21.1) =-
-= ComfyUI-Manager CLI (V2.24) =-
FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json
ComfyUI-Manager
@ -112,11 +112,17 @@ ComfyUI-Loopchain
* `enable`: Enables the specified custom nodes.
* `fix`: Attempts to fix dependencies for the specified custom nodes.
### 4. Snapshot Management
* `python cm-cli.py save-snapshot`: Saves the current snapshot.
* `python cm-cli.py restore-snapshot <snapshot>`: Restores to the specified snapshot.
* If a file exists at the snapshot path, it loads that snapshot.
* If no file exists at the snapshot path, it implicitly assumes the snapshot is located in ComfyUI-Manager/snapshots.
* `python cm-cli.py save-snapshot [--output <snapshot .json/.yaml>]`: Saves the current snapshot.
* With `--output`, you can save a file in .yaml format to any specified path.
* `python cm-cli.py restore-snapshot <snapshot .json/.yaml>`: Restores to the specified snapshot.
* If a file exists at the snapshot path, that snapshot is loaded.
* If no file exists at the snapshot path, it is implicitly assumed to be in ComfyUI-Manager/snapshots.
* `--pip-non-url`: Restore for pip packages registered on PyPI.
* `--pip-non-local-url`: Restore for pip packages registered at web URLs.
* `--pip-local-url`: Restore for pip packages specified by local paths.
### 5. CLI Only Mode

View File

@ -4,7 +4,8 @@
```
-= ComfyUI-Manager CLI (V2.21.1) =-
-= ComfyUI-Manager CLI (V2.24) =-
python cm-cli.py [OPTIONS]
@ -12,12 +13,11 @@ OPTIONS:
[install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel <channel name>] ?[--mode [remote|local|cache]]
[update|disable|enable|fix] all ?[--channel <channel name>] ?[--mode [remote|local|cache]]
[simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel <channel name>] ?[--mode [remote|local|cache]]
save-snapshot
restore-snapshot <snapshot>
save-snapshot ?[--output <snapshot .json/.yaml>]
restore-snapshot <snapshot .json/.yaml> ?[--pip-non-url] ?[--pip-non-local-url] ?[--pip-local-url]
cli-only-mode [enable|disable]
restore-dependencies
clear
```
## How To Use?
@ -53,7 +53,7 @@ OPTIONS:
`python cm-cli.py show installed` 와 같은 코맨드를 실행하면 설치된 커스텀 노드의 정보를 상세하게 보여줍니다.
```
-= ComfyUI-Manager CLI (V2.21.1) =-
-= ComfyUI-Manager CLI (V2.24) =-
FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json
[ ENABLED ] ComfyUI-Manager (author: Dr.Lt.Data)
@ -70,7 +70,7 @@ FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main
`python cm-cli.py simple-show installed` 와 같은 코맨드를 이용해서 설치된 커스텀 노드의 정보를 간단하게 보여줍니다.
```
-= ComfyUI-Manager CLI (V2.21.1) =-
-= ComfyUI-Manager CLI (V2.24) =-
FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json
ComfyUI-Manager
@ -115,10 +115,14 @@ ComfyUI-Loopchain
### 4. 스냅샷 관리 기능
* `python cm-cli.py save-snapshot`: 현재의 snapshot을 저장합니다.
* `python cm-cli.py restore-snapshot <snapshot>`: 지정된 snapshot으로 복구합니다.
* `python cm-cli.py save-snapshot ?[--output <snapshot .json/.yaml>]`: 현재의 snapshot을 저장합니다.
* --output 으로 임의의 경로에 .yaml 파일과 format으로 저장할 수 있습니다.
* `python cm-cli.py restore-snapshot <snapshot .json/.yaml>`: 지정된 snapshot으로 복구합니다.
* snapshot 경로에 파일이 존재하는 경우 해당 snapshot을 로드합니다.
* snapshot 경로에 파일이 존재하지 않는 경우 묵시적으로, ComfyUI-Manager/snapshots 에 있다고 가정합니다.
* `--pip-non-url`: PyPI 에 등록된 pip 패키지들에 대해서 복구를 수행
* `--pip-non-local-url`: web URL에 등록된 pip 패키지들에 대해서 복구를 수행
* `--pip-local-url`: local 경로를 지정하고 있는 pip 패키지들에 대해서 복구를 수행
### 5. CLI only mode

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,13 @@
import subprocess
import sys
import os
import traceback
import git
import configparser
import re
import json
import yaml
from torchvision.datasets.utils import download_url
from tqdm.auto import tqdm
from git.remote import RemoteProgress
@ -12,6 +16,12 @@ config_path = os.path.join(os.path.dirname(__file__), "config.ini")
nodelist_path = os.path.join(os.path.dirname(__file__), "custom-node-list.json")
working_directory = os.getcwd()
if os.path.basename(working_directory) != 'custom_nodes':
print(f"WARN: This script should be executed in custom_nodes dir")
print(f"DBG: INFO {working_directory}")
print(f"DBG: INFO {sys.argv}")
# exit(-1)
class GitProgress(RemoteProgress):
def __init__(self):
@ -132,7 +142,7 @@ def gitpull(path):
def checkout_comfyui_hash(target_hash):
repo_path = os.path.join(working_directory, '..') # ComfyUI dir
repo_path = os.path.abspath(os.path.join(working_directory, '..')) # ComfyUI dir
repo = git.Repo(repo_path)
commit_hash = repo.head.commit.hexsha
@ -278,8 +288,21 @@ def apply_snapshot(target):
try:
path = os.path.join(os.path.dirname(__file__), 'snapshots', f"{target}")
if os.path.exists(path):
with open(path, 'r', encoding="UTF-8") as json_file:
info = json.load(json_file)
if not target.endswith('.json') and not target.endswith('.yaml'):
print(f"Snapshot file not found: `{path}`")
print("APPLY SNAPSHOT: False")
return None
with open(path, 'r', encoding="UTF-8") as snapshot_file:
if target.endswith('.json'):
info = json.load(snapshot_file)
elif target.endswith('.yaml'):
info = yaml.load(snapshot_file, Loader=yaml.SafeLoader)
info = info['custom_nodes']
else:
# impossible case
print("APPLY SNAPSHOT: False")
return None
comfyui_hash = info['comfyui']
git_custom_node_infos = info['git_custom_nodes']
@ -290,14 +313,81 @@ def apply_snapshot(target):
invalidate_custom_node_file(file_custom_node_infos)
print("APPLY SNAPSHOT: True")
return
if 'pips' in info:
return info['pips']
else:
return None
print(f"Snapshot file not found: `{path}`")
print("APPLY SNAPSHOT: False")
return None
except Exception as e:
print(e)
traceback.print_exc()
print("APPLY SNAPSHOT: False")
return None
def restore_pip_snapshot(pips, options):
non_url = []
local_url = []
non_local_url = []
for k, v in pips.items():
if v == "":
non_url.append(v)
else:
if v.startswith('file:'):
local_url.append(v)
else:
non_local_url.append(v)
failed = []
if '--pip-non-url' in options:
# try all at once
res = 1
try:
res = subprocess.check_call([sys.executable, '-m', 'pip', 'install'] + non_url)
except:
pass
# fallback
if res != 0:
for x in non_url:
res = 1
try:
res = subprocess.check_call([sys.executable, '-m', 'pip', 'install', x])
except:
pass
if res != 0:
failed.append(x)
if '--pip-non-local-url' in options:
for x in non_local_url:
res = 1
try:
res = subprocess.check_call([sys.executable, '-m', 'pip', 'install', x])
except:
pass
if res != 0:
failed.append(x)
if '--pip-local-url' in options:
for x in local_url:
res = 1
try:
res = subprocess.check_call([sys.executable, '-m', 'pip', 'install', x])
except:
pass
if res != 0:
failed.append(x)
print(f"Installation failed for pip packages: {failed}")
def setup_environment():
config = configparser.ConfigParser()
@ -319,7 +409,15 @@ try:
elif sys.argv[1] == "--pull":
gitpull(sys.argv[2])
elif sys.argv[1] == "--apply-snapshot":
apply_snapshot(sys.argv[2])
options = set()
for x in sys.argv:
if x in ['--pip-non-url', '--pip-local-url', '--pip-non-local-url']:
options.add(x)
pips = apply_snapshot(sys.argv[2])
if pips and len(options) > 0:
restore_pip_snapshot(pips, options)
sys.exit(0)
except Exception as e:
print(e)

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,8 @@ import aiohttp
import threading
import json
import time
import yaml
import zipfile
glob_path = os.path.join(os.path.dirname(__file__)) # ComfyUI-Manager/glob
sys.path.append(glob_path)
@ -21,7 +23,7 @@ sys.path.append(glob_path)
import cm_global
from manager_util import *
version = [2, 23, 1]
version = [2, 30]
version_str = f"V{version[0]}.{version[1]}" + (f'.{version[2]}' if len(version) > 2 else '')
comfyui_manager_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
@ -179,8 +181,7 @@ class ManagerFuncs:
print(f"[ComfyUI-Manager] Unexpected behavior: `{cmd}`")
return 0
out = subprocess.check_call(cmd, cwd=cwd)
print(out)
subprocess.check_call(cmd, cwd=cwd)
return 0
@ -312,7 +313,7 @@ def __win_check_git_update(path, do_fetch=False, do_update=False):
else:
command = [sys.executable, git_script_path, "--check", path]
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=custom_nodes_path)
output, _ = process.communicate()
output = output.decode('utf-8').strip()
@ -364,7 +365,7 @@ def __win_check_git_update(path, do_fetch=False, do_update=False):
def __win_check_git_pull(path):
command = [sys.executable, git_script_path, "--pull", path]
process = subprocess.Popen(command)
process = subprocess.Popen(command, cwd=custom_nodes_path)
process.wait()
@ -513,7 +514,7 @@ def gitclone_install(files, instant_execution=False, msg_prefix=''):
# Clone the repository from the remote URL
if not instant_execution and platform.system() == 'Windows':
res = manager_funcs.run_script([sys.executable, git_script_path, "--clone", custom_nodes_path, url])
res = manager_funcs.run_script([sys.executable, git_script_path, "--clone", custom_nodes_path, url], cwd=custom_nodes_path)
if res != 0:
return False
else:
@ -598,6 +599,9 @@ def is_file_created_within_one_day(file_path):
async def get_data_by_mode(mode, filename, channel_url=None):
if channel_url in get_channel_dict():
channel_url = get_channel_dict()[channel_url]
try:
if mode == "local":
uri = os.path.join(comfyui_manager_path, filename)
@ -854,6 +858,7 @@ def update_path(repo_path, instant_execution=False):
else:
return "skipped"
def lookup_customnode_by_url(data, target):
for x in data['custom_nodes']:
if target in x['files']:
@ -868,6 +873,17 @@ def lookup_customnode_by_url(data, target):
return None
def simple_check_custom_node(url):
dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "")
dir_path = os.path.join(custom_nodes_path, dir_name)
if os.path.exists(dir_path):
return 'installed'
elif os.path.exists(dir_path+'.disabled'):
return 'disabled'
return 'not-installed'
def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do_update=False):
item['installed'] = 'None'
@ -926,6 +942,24 @@ def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do
item['installed'] = 'False'
def get_installed_pip_packages():
# extract pip package infos
pips = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'], text=True).split('\n')
res = {}
for x in pips:
if x.strip() == "":
continue
if ' @ ' in x:
spec_url = x.split(' @ ')
res[spec_url[0]] = spec_url[1]
else:
res[x] = ""
return res
def get_current_snapshot():
# Get ComfyUI hash
repo_path = comfy_path
@ -975,22 +1009,178 @@ def get_current_snapshot():
file_custom_nodes.append(item)
pip_packages = get_installed_pip_packages()
return {
'comfyui': comfyui_commit_hash,
'git_custom_nodes': git_custom_nodes,
'file_custom_nodes': file_custom_nodes,
'pips': pip_packages,
}
def save_snapshot_with_postfix(postfix):
now = datetime.now()
def save_snapshot_with_postfix(postfix, path=None):
if path is None:
now = datetime.now()
date_time_format = now.strftime("%Y-%m-%d_%H-%M-%S")
file_name = f"{date_time_format}_{postfix}"
date_time_format = now.strftime("%Y-%m-%d_%H-%M-%S")
file_name = f"{date_time_format}_{postfix}"
path = os.path.join(comfyui_manager_path, 'snapshots', f"{file_name}.json")
with open(path, "w") as json_file:
json.dump(get_current_snapshot(), json_file, indent=4)
path = os.path.join(comfyui_manager_path, 'snapshots', f"{file_name}.json")
else:
file_name = path.replace('\\', '/').split('/')[-1]
file_name = file_name.split('.')[-2]
return file_name+'.json'
snapshot = get_current_snapshot()
if path.endswith('.json'):
with open(path, "w") as json_file:
json.dump(snapshot, json_file, indent=4)
return file_name + '.json'
elif path.endswith('.yaml'):
with open(path, "w") as yaml_file:
snapshot = {'custom_nodes': snapshot}
yaml.dump(snapshot, yaml_file, allow_unicode=True)
return path
async def extract_nodes_from_workflow(filepath, mode='local', channel_url='default'):
# prepare json data
workflow = None
if filepath.endswith('.json'):
with open(filepath, "r", encoding="UTF-8", errors="ignore") as json_file:
try:
workflow = json.load(json_file)
except:
print(f"Invalid workflow file: {filepath}")
exit(-1)
elif filepath.endswith('.png'):
from PIL import Image
with Image.open(filepath) as img:
if 'workflow' not in img.info:
print(f"The specified .png file doesn't have a workflow: {filepath}")
exit(-1)
else:
try:
workflow = json.loads(img.info['workflow'])
except:
print(f"This is not a valid .png file containing a ComfyUI workflow: {filepath}")
exit(-1)
if workflow is None:
print(f"Invalid workflow file: {filepath}")
exit(-1)
# extract nodes
used_nodes = set()
def extract_nodes(sub_workflow):
for x in sub_workflow['nodes']:
node_name = x.get('type')
# skip virtual nodes
if node_name in ['Reroute', 'Note']:
continue
if node_name is not None and not node_name.startswith('workflow/'):
used_nodes.add(node_name)
if 'nodes' in workflow:
extract_nodes(workflow)
if 'extra' in workflow:
if 'groupNodes' in workflow['extra']:
for x in workflow['extra']['groupNodes'].values():
extract_nodes(x)
# lookup dependent custom nodes
ext_map = await get_data_by_mode(mode, 'extension-node-map.json', channel_url)
rext_map = {}
preemption_map = {}
patterns = []
for k, v in ext_map.items():
if k == 'https://github.com/comfyanonymous/ComfyUI':
for x in v[0]:
if x not in preemption_map:
preemption_map[x] = []
preemption_map[x] = k
continue
for x in v[0]:
if x not in rext_map:
rext_map[x] = []
rext_map[x].append(k)
if 'preemptions' in v[1]:
for x in v[1]['preemptions']:
if x not in preemption_map:
preemption_map[x] = []
preemption_map[x] = k
if 'nodename_pattern' in v[1]:
patterns.append((v[1]['nodename_pattern'], k))
# identify used extensions
used_exts = set()
unknown_nodes = set()
for node_name in used_nodes:
ext = preemption_map.get(node_name)
if ext is None:
ext = rext_map.get(node_name)
if ext is not None:
ext = ext[0]
if ext is None:
for pat_ext in patterns:
if re.search(pat_ext[0], node_name):
ext = pat_ext[1]
break
if ext == 'https://github.com/comfyanonymous/ComfyUI':
pass
elif ext is not None:
if 'Fooocus' in ext:
print(f">> {node_name}")
used_exts.add(ext)
else:
unknown_nodes.add(node_name)
return used_exts, unknown_nodes
def unzip(model_path):
if not os.path.exists(model_path):
print(f"[ComfyUI-Manager] unzip: File not found: {model_path}")
return False
base_dir = os.path.dirname(model_path)
filename = os.path.basename(model_path)
target_dir = os.path.join(base_dir, filename[:-4])
os.makedirs(target_dir, exist_ok=True)
with zipfile.ZipFile(model_path, 'r') as zip_ref:
zip_ref.extractall(target_dir)
# Check if there's only one directory inside the target directory
contents = os.listdir(target_dir)
if len(contents) == 1 and os.path.isdir(os.path.join(target_dir, contents[0])):
nested_dir = os.path.join(target_dir, contents[0])
# Move each file and sub-directory in the nested directory up to the target directory
for item in os.listdir(nested_dir):
shutil.move(os.path.join(nested_dir, item), os.path.join(target_dir, item))
# Remove the now empty nested directory
os.rmdir(nested_dir)
os.remove(model_path)
return True

View File

@ -508,7 +508,12 @@ def check_model_installed(json_obj):
item['installed'] = 'None'
if model_path is not None:
if os.path.exists(model_path):
if model_path.endswith('.zip'):
if os.path.exists(model_path[:-4]):
item['installed'] = 'True'
else:
item['installed'] = 'False'
elif os.path.exists(model_path):
item['installed'] = 'True'
else:
item['installed'] = 'False'
@ -872,7 +877,6 @@ async def update_comfyui(request):
return web.Response(status=200)
except Exception as e:
print(f"ComfyUI update fail: {e}", file=sys.stderr)
pass
return web.Response(status=400)
@ -916,10 +920,17 @@ async def install_model(request):
model_url.startswith('https://github.com') or model_url.startswith('https://huggingface.co') or model_url.startswith('https://heibox.uni-heidelberg.de')):
model_dir = get_model_dir(json_data)
download_url(model_url, model_dir, filename=json_data['filename'])
if model_path.endswith('.zip'):
res = core.unzip(model_path)
else:
res = True
return web.json_response({}, content_type='application/json')
if res:
return web.json_response({}, content_type='application/json')
else:
res = download_url_with_agent(model_url, model_path)
if res and model_path.endswith('.zip'):
res = core.unzip(model_path)
else:
print(f"Model installation error: invalid model type - {json_data['type']}")
@ -927,7 +938,6 @@ async def install_model(request):
return web.json_response({}, content_type='application/json')
except Exception as e:
print(f"[ERROR] {e}", file=sys.stderr)
pass
return web.Response(status=400)
@ -1074,14 +1084,17 @@ def restart(self):
pass
if '__COMFY_CLI_SESSION__' in os.environ:
with open(os.path.join(os.environ['__COMFY_CLI_SESSION__'], '.reboot'), 'w') as file:
with open(os.path.join(os.environ['__COMFY_CLI_SESSION__'] + '.reboot'), 'w') as file:
pass
print(f"\nRestarting...\n\n")
exit(0)
print(f"\nRestarting... [Legacy Mode]\n\n")
return os.execv(sys.executable, [sys.executable] + sys.argv)
if sys.platform.startswith('win32'):
return os.execv(sys.executable, ['"' + sys.executable + '"', '"' + sys.argv[0] + '"'] + sys.argv[1:])
else:
return os.execv(sys.executable, [sys.executable] + sys.argv)
def sanitize_filename(input_string):

View File

@ -615,7 +615,7 @@ async function updateAll(update_check_checkbox, manager_dialog) {
const response1 = await api.fetchApi('/comfyui_manager/update_comfyui');
const response2 = await api.fetchApi(`/customnode/update_all?mode=${mode}`);
if (response1.status != 200 && response2.status != 201) {
if (response1.status == 400 || response2.status == 400) {
app.ui.dialog.show('Failed to update ComfyUI or several extensions.<BR><BR>See terminal log.<BR>');
app.ui.dialog.element.style.zIndex = 10010;
return false;

View File

@ -2511,6 +2511,106 @@
"reference": "https://huggingface.co/xinyu1205/recognize_anything_model",
"filename": "tag2text_swin_14m.pth",
"url": "https://huggingface.co/xinyu1205/recognize_anything_model/resolve/main/tag2text_swin_14m.pth"
},
{
"name": "Zero123 3D object Model",
"type": "Zero123",
"base": "Zero123",
"save_path": "checkpoints/zero123",
"description": "model that been trained on 10M+ 3D objects from Objaverse-XL, used for generated rotated CamView",
"reference": "https://objaverse.allenai.org/docs/zero123-xl/",
"filename": "zero123-xl.ckpt",
"url": "https://huggingface.co/kealiu/zero123-xl/resolve/main/zero123-xl.ckpt"
},
{
"name": "Zero123 3D object Model",
"type": "Zero123",
"base": "Zero123",
"save_path": "checkpoints/zero123",
"description": "Stable Zero123 is a model for view-conditioned image generation based on [a/Zero123](https://github.com/cvlab-columbia/zero123).",
"reference": "https://huggingface.co/stabilityai/stable-zero123",
"filename": "stable_zero123.ckpt",
"url": "https://huggingface.co/stabilityai/stable-zero123/resolve/main/stable_zero123.ckpt"
},
{
"name": "Zero123 3D object Model",
"type": "Zero123",
"base": "Zero123",
"save_path": "checkpoints/zero123",
"description": "Zero123 original checkpoints in 105000 steps.",
"reference": "https://huggingface.co/cvlab/zero123-weights",
"filename": "zero123-105000.ckpt",
"url": "https://huggingface.co/cvlab/zero123-weights/resolve/main/105000.ckpt"
},
{
"name": "Zero123 3D object Model",
"type": "Zero123",
"base": "Zero123",
"save_path": "checkpoints/zero123",
"description": "Zero123 original checkpoints in 165000 steps.",
"reference": "https://huggingface.co/cvlab/zero123-weights",
"filename": "zero123-165000.ckpt",
"url": "https://huggingface.co/cvlab/zero123-weights/resolve/main/165000.ckpt"
},
{
"name": "InstantID/ip-adapter",
"type": "instantid",
"base": "SDXL",
"save_path": "instantid/SDXL",
"description": "ip-adapter model for cubiq/InstantID",
"reference": "https://huggingface.co/InstantX/InstantID",
"filename": "ip-adapter.bin",
"url": "https://huggingface.co/InstantX/InstantID/resolve/main/ip-adapter.bin"
},
{
"name": "InstantID/ControlNet",
"type": "controlnet",
"base": "SDXL",
"save_path": "controlnet/SDXL/instantid",
"description": "instantid controlnet model for cubiq/InstantID",
"reference": "https://huggingface.co/InstantX/InstantID",
"filename": "diffusion_pytorch_model.safetensors",
"url": "https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors"
},
{
"name": "MonsterMMORPG/insightface (for InstantID)",
"type": "insightface",
"base": "SDXL",
"save_path": "insightface/models",
"description": "MonsterMMORPG insightface model for cubiq/InstantID",
"reference": "https://huggingface.co/MonsterMMORPG/tools/tree/main",
"filename": "antelopev2.zip",
"url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/antelopev2.zip"
},
{
"name": "IC-Light/fc",
"type": "IC-Light",
"base": "SD1.5",
"save_path": "unet/IC-Light",
"description": "The default relighting model, conditioned on text and foreground",
"reference": "https://huggingface.co/lllyasviel/ic-light",
"filename": "iclight_sd15_fc.safetensors",
"url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fc.safetensors"
},
{
"name": "IC-Light/fbc",
"type": "IC-Light",
"base": "SD1.5",
"save_path": "unet/IC-Light",
"description": "Relighting model conditioned with text, foreground, and background",
"reference": "https://huggingface.co/lllyasviel/ic-light",
"filename": "iclight_sd15_fbc.safetensors",
"url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fbc.safetensors"
},
{
"name": "IC-Light/fcon",
"type": "IC-Light",
"base": "SD1.5",
"save_path": "unet/IC-Light",
"description": "Same as iclight_sd15_fc.safetensors, but trained with offset noise",
"reference": "https://huggingface.co/lllyasviel/ic-light",
"filename": "iclight_sd15_fcon.safetensors",
"url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fcon.safetensors"
}
]
}

View File

@ -8,9 +8,108 @@
"install_type": "git-clone",
"description": "If you see this message, your ComfyUI-Manager is outdated.\nDev channel provides only the list of the developing nodes. If you want to find the complete node list, please go to the Default channel."
},
{
"author": "huchenlei",
"title": "ComfyUI-IC-Light",
"id": "ic-light-huchenlei",
"reference": "https://github.com/huchenlei/ComfyUI-IC-Light",
"files": [
"https://github.com/huchenlei/ComfyUI-IC-Light"
],
"install_type": "git-clone",
"description": "ComfyUI native implementation of [a/IC-Light](https://github.com/lllyasviel/IC-Light). [w/It is not possible to install both because kijai's ComfyUI-IC-Light and another repository have the same name.]"
},
{
"author": "Levy1417",
"title": "Universal-Data-Processing-Kit [UNSAFE]",
"reference": "https://github.com/Levy1417/Universal-Data-Processing-Kit",
"files": [
"https://github.com/Levy1417/Universal-Data-Processing-Kit"
],
"install_type": "git-clone",
"description": "Nodes:DPK - Any Eval, DPK - Extract Array, DPK - Run External Program, DPK - Any Literals, DPK - Set Node States, DPK - Realtime Text Preview, DPK - Dynamic Action, DPK - Object To Json, DPK - Json To Object\n[w/This extension includes the ability to execute arbitrary code and programs.]"
},
{
"author": "runtime44",
"title": "Runtime44 ComfyUI Nodes",
"reference": "https://github.com/runtime44/comfyui_r44_nodes",
"files": [
"https://github.com/runtime44/comfyui_r44_nodes"
],
"install_type": "git-clone",
"description": "Nodes: Runtime44Upscaler, Runtime44ColorMatch, Runtime44DynamicKSampler, Runtime44ImageOverlay, Runtime44ImageResizer, Runtime44ImageToNoise, Runtime44MaskSampler, Runtime44TiledMaskSampler, Runtime44IterativeUpscaleFactor, Runtime44ImageEnhance"
},
{
"author": "ericbeyer",
"title": "guidance_interval",
"reference": "https://github.com/ericbeyer/guidance_interval",
"files": [
"https://github.com/ericbeyer/guidance_interval"
],
"install_type": "git-clone",
"description": "Nodes:Guidance Interval\nNOTE: Because the sampling function is replaced, you must restart after executing this custom node to restore the original state."
},
{
"author": "GraftingRayman",
"title": "ComfyUI-GR",
"reference": "https://github.com/GraftingRayman/ComfyUI_GR_PromptSelector",
"files": [
"https://github.com/GraftingRayman/ComfyUI_GR_PromptSelector"
],
"install_type": "git-clone",
"description": "Nodes:GR Prompt Selector"
},
{
"author": "oztrkoguz",
"title": "Kosmos2_BBox_Cutter Models",
"reference": "https://github.com/oztrkoguz/ComfyUI_Kosmos2_BBox_Cutter",
"files": [
"https://github.com/oztrkoguz/ComfyUI_Kosmos2_BBox_Cutter"
],
"install_type": "git-clone",
"description": "Nodes:KosmosLoader, Kosmos2SamplerSimple, Write"
},
{
"author": "ZHO-ZHO-ZHO",
"title": "ComfyUI-PuLID-ZHO [WIP]",
"reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PuLID-ZHO",
"files": [
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-PuLID-ZHO"
],
"install_type": "git-clone",
"description": "Unofficial implementation of [a/PuLID](https://github.com/ToTheBeginning/PuLID)diffusers for ComfyUI"
},
{
"author": "longgui0318",
"title": "comfyui-one-more-step [WIP]",
"reference": "https://github.com/longgui0318/comfyui-one-more-step",
"files": [
"https://github.com/longgui0318/comfyui-one-more-step"
],
"install_type": "git-clone",
"description": "[a/(OMS)mhh0318/OneMoreStep](https://github.com/mhh0318/OneMoreStep) comfyui support ."
},
{
"author": "unknown",
"title": "CLIPTextEncodeAndEnhancev4 (shirazdesigner)",
"reference": "https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4",
"files": [
"https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4"
],
"install_type": "git-clone",
"description": "Nodes:CLIPTextEncodeAndEnhance.\nNOTE:Translation:This is a wrapper that simply makes it easy to install an existing node via git."
},
{
"author": "umisetokikaze",
"title": "comfyui_mergekit [WIP]",
"reference": "https://github.com/umisetokikaze/comfyui_mergekit",
"files": [
"https://github.com/umisetokikaze/comfyui_mergekit"
],
"install_type": "git-clone",
"description": "Nodes:DefineSaveName, SetModels, get_skip, LoadLR, LoadTarget, SetTokenizer, Merge, SetLayer, SetModels"
},
{
"author": "Video3DGenResearch",
"title": "ComfyUI Batch Input Node",
@ -411,16 +510,6 @@
"install_type": "git-clone",
"description": "Nodes:Musicgen"
},
{
"author": "Extraltodeus",
"title": "ComfyUI-variableCFGandAntiBurn [WIP]",
"reference": "https://github.com/Extraltodeus/ComfyUI-variableCFGandAntiBurn",
"files": [
"https://github.com/Extraltodeus/ComfyUI-variableCFGandAntiBurn"
],
"install_type": "git-clone",
"description": "Nodes:Continuous CFG rescaler (pre CFG), Intermediary latent merge (post CFG), Intensity/Brightness limiter (post CFG), Dynamic renoising (post CFG), Automatic CFG scale (pre/post CFG), CFG multiplier per channel (pre CFG), Self-Attention Guidance delayed activation mod (post CFG)"
},
{
"author": "shadowcz007",
"title": "comfyui-CLIPSeg",

View File

@ -146,6 +146,49 @@
"title_aux": "ComfyUI_Fooocus"
}
],
"https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1": [
[
"\u2b1b(TODO)AC_Super_Come_Ckpt",
"\u2b1c(TODO)AC_Super_Come_Lora",
"\u2b55AC_FUN_SUPER_LARGE",
"\ud83c\ude35AC_Super_Checkpoint",
"\ud83c\ude35AC_Super_Loras",
"\ud83c\udfabAC_Super_PreviewImage",
"\ud83c\udfb0AC_Super_Controlnet",
"\ud83d\udcb6AC_Super_EmptLatent",
"\ud83d\udcbcAC_Super_Lora&LCM",
"\ud83d\udcbeAC_Super_SaveImage",
"\ud83d\udcc4AC_Super_CLIPEN",
"\ud83d\udcc8AC_Super_UpKSampler",
"\ud83d\udcdfAC_Super_CKPT&LCM",
"\ud83d\ude80AC_Super_KSampler"
],
{
"title_aux": "ComfyUI_AC_FUNV8Beta1"
}
],
"https://github.com/ALatentPlace/ComfyUI_yanc": [
[
"> Clear Text",
"> Float to Int",
"> Int",
"> Int to Text",
"> Load Image",
"> Load Image From Folder",
"> Resolution by Aspect Ratio",
"> Rotate Image",
"> Save Image",
"> Scale Image to Side",
"> Text",
"> Text Combine",
"> Text Pick Random Line",
"> Text Random Weights",
"> Text Replace"
],
{
"title_aux": "YANC- Yet Another Node Collection"
}
],
"https://github.com/BadCafeCode/execution-inversion-demo-comfyui": [
[
"AccumulateNode",
@ -221,6 +264,64 @@
"title_aux": "ComfyUI_bd_customNodes"
}
],
"https://github.com/DeTK/ComfyUI-Switch": [
[
"NodeSwitch"
],
{
"title_aux": "ComfyUI Node Switcher"
}
],
"https://github.com/DrMWeigand/ComfyUI_LineBreakInserter": [
[
"LineBreakInserter"
],
{
"title_aux": "ComfyUI_LineBreakInserter"
}
],
"https://github.com/ExponentialML/ComfyUI_LiveDirector": [
[
"LiveDirector"
],
{
"title_aux": "ComfyUI_LiveDirector (WIP)"
}
],
"https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI": [
[
"Automatic wildcards",
"Conditioning (Cosine similarities)",
"Conditioning (Maximum absolute)",
"Conditioning (Maximum absolute) text inputs",
"Conditioning (Scale by absolute sum)",
"Conditioning merge clip g/l",
"Conditioning similar tokens recombine",
"Conditioning to text",
"Quick and dirty text encode",
"encode_all_tokens_SDXL"
],
{
"title_aux": "Conditioning-token-experiments-for-ComfyUI"
}
],
"https://github.com/GentlemanHu/ComfyUI-Notifier": [
[
"GentlemanHu_Notifier"
],
{
"title_aux": "ComfyUI-Notifier"
}
],
"https://github.com/GrindHouse66/ComfyUI-GH_Tools": [
[
"GHImg_Sizer",
"GHSimple_Scale"
],
{
"title_aux": "GH Tools for ComfyUI"
}
],
"https://github.com/IvanZhd/comfyui-codeformer": [
[
"RedBeanie_CustomImageInverter"
@ -237,6 +338,14 @@
"title_aux": "comfyui-terminal-command [UNSAFE]"
}
],
"https://github.com/Jiffies-64/ComfyUI-SaveImagePlus": [
[
"SaveImagePlus"
],
{
"title_aux": "ComfyUI-SaveImagePlus"
}
],
"https://github.com/Jordach/comfy-consistency-vae": [
[
"Comfy_ConsistencyVAE"
@ -253,6 +362,14 @@
"title_aux": "ComfyUI-ModelUnloader"
}
],
"https://github.com/LotzF/ComfyUI-Simple-Chat-GPT-completion": [
[
"ChatGPTCompletion"
],
{
"title_aux": "ComfyUI simple ChatGPT completion [UNSAFE]"
}
],
"https://github.com/MrAdamBlack/CheckProgress": [
[
"CHECK_PROGRESS"
@ -261,6 +378,14 @@
"title_aux": "CheckProgress [WIP]"
}
],
"https://github.com/MushroomFleet/DJZ-Nodes": [
[
"AspectSize"
],
{
"title_aux": "DJZ-Nodes"
}
],
"https://github.com/PluMaZero/ComfyUI-SpaceFlower": [
[
"SpaceFlower_HangulPrompt",
@ -270,6 +395,17 @@
"title_aux": "ComfyUI-SpaceFlower"
}
],
"https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt": [
[
"CLIPTextEncodePromptToPrompt",
"KSamplerPromptToPrompt",
"KSamplerPromptToPromptAttentionMapLogger",
"LocalBlendLayerPresetPromptToPrompt"
],
{
"title_aux": "ComfyUI Port for Google's Prompt-to-Prompt"
}
],
"https://github.com/Sai-ComfyUI/ComfyUI-MS-Nodes": [
[
"FloatMath",
@ -285,6 +421,25 @@
"title_aux": "ComfyUI-MS-Nodes [WIP]"
}
],
"https://github.com/SeedV/ComfyUI-SeedV-Nodes": [
[
"CheckpointLoaderSimpleShared //SeedV",
"Script"
],
{
"title_aux": "ComfyUI-SeedV-Nodes [UNSAFE]"
}
],
"https://github.com/Video3DGenResearch/comfyui-batch-input-node": [
[
"BatchImageAndPrompt",
"BatchInputCSV",
"BatchInputText"
],
{
"title_aux": "ComfyUI Batch Input Node"
}
],
"https://github.com/WSJUSA/Comfyui-StableSR": [
[
"ColorFix",
@ -298,12 +453,23 @@
"title_aux": "pre-comfyui-stablsr"
}
],
"https://github.com/WilliamStanford/visuallabs_comfyui_nodes": [
[
"CreateFadeMaskAdvancedVL",
"PointStringFromFloatArray",
"RescaleFloatArray",
"StringFromFloatArray"
],
{
"title_aux": "visuallabs_comfyui_nodes"
}
],
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText": [
[
"AnyTextNode_Zho"
],
{
"title_aux": "ComfyUI-AnyText\uff08WIP\uff09"
"title_aux": "ComfyUI-AnyText [WIP]"
}
],
"https://github.com/alt-key-project/comfyui-dream-video-batches": [
@ -353,14 +519,30 @@
"Checkpoint Selector Stacker \ud83d\udc69\u200d\ud83d\udcbb",
"Checkpoint Selector \ud83d\udc69\u200d\ud83d\udcbb",
"Checkpoint to String \ud83d\udc69\u200d\ud83d\udcbb",
"Crop Recombine \ud83d\udc69\u200d\ud83d\udcbb",
"Crop|IP|Inpaint \ud83d\udc69\u200d\ud83d\udcbb",
"Crop|IP|Inpaint|SDXL \ud83d\udc69\u200d\ud83d\udcbb",
"Decode GenData \ud83d\udc69\u200d\ud83d\udcbb",
"Encode GenData \ud83d\udc69\u200d\ud83d\udcbb",
"GenData Stacker \ud83d\udc69\u200d\ud83d\udcbb",
"IPAdapterApply",
"IPAdapterApplyEncoded",
"IPAdapterApplyFaceID",
"IPAdapterBatchEmbeds",
"IPAdapterEncoder",
"IPAdapterLoadEmbeds",
"IPAdapterModelLoader",
"IPAdapterSaveEmbeds",
"IPAdapterTilesMasked",
"InsightFaceLoader",
"LoRA Stack to String \ud83d\udc69\u200d\ud83d\udcbb",
"LoRA Stacker From Prompt \ud83d\udc69\u200d\ud83d\udcbb",
"Load Checkpoints From File \ud83d\udc69\u200d\ud83d\udcbb",
"Load GenData From Dir \ud83d\udc69\u200d\ud83d\udcbb",
"Parse GenData \ud83d\udc69\u200d\ud83d\udcbb",
"PrepImageForClipVision",
"PrepImageForInsightFace",
"Provide GenData \ud83d\udc69\u200d\ud83d\udcbb",
"Save Image From GenData \ud83d\udc69\u200d\ud83d\udcbb",
"VAE From String \ud83d\udc69\u200d\ud83d\udcbb",
"VAE to String \ud83d\udc69\u200d\ud83d\udcbb",
@ -370,23 +552,41 @@
"title_aux": "Gen Data Tester [WIP]"
}
],
"https://github.com/blepping/ComfyUI-sonar": [
"https://github.com/bruce007lee/comfyui-cleaner": [
[
"SamplerSonarEuler",
"SamplerSonarEulerA"
"cleaner"
],
{
"title_aux": "ComfyUI-sonar (WIP)"
"title_aux": "comfyui-cleaner"
}
],
"https://github.com/chaojie/ComfyUI-DynamiCrafter": [
[
"DynamiCrafter Simple",
"DynamiCrafterInterp Simple",
"DynamiCrafterInterpLoader",
"DynamiCrafterLoader"
],
{
"title_aux": "ComfyUI DynamiCrafter"
}
],
"https://github.com/comfyanonymous/ComfyUI": [
[
"AddNoise",
"AlignYourStepsScheduler",
"BasicGuider",
"BasicScheduler",
"CFGGuider",
"CLIPAttentionMultiply",
"CLIPLoader",
"CLIPMergeAdd",
"CLIPMergeSimple",
"CLIPMergeSubtract",
"CLIPSave",
"CLIPSetLastLayer",
"CLIPTextEncode",
"CLIPTextEncodeControlnet",
"CLIPTextEncodeSDXL",
"CLIPTextEncodeSDXLRefiner",
"CLIPVisionEncode",
@ -409,7 +609,10 @@
"ControlNetLoader",
"CropMask",
"DiffControlNetLoader",
"DifferentialDiffusion",
"DiffusersLoader",
"DisableNoise",
"DualCFGGuider",
"DualCLIPLoader",
"EmptyImage",
"EmptyLatentImage",
@ -429,6 +632,7 @@
"ImageColorToMask",
"ImageCompositeMasked",
"ImageCrop",
"ImageFromBatch",
"ImageInvert",
"ImageOnlyCheckpointLoader",
"ImageOnlyCheckpointSave",
@ -441,6 +645,7 @@
"ImageToMask",
"ImageUpscaleWithModel",
"InpaintModelConditioning",
"InstructPixToPixConditioning",
"InvertMask",
"JoinImageWithAlpha",
"KSampler",
@ -471,17 +676,25 @@
"MaskToImage",
"ModelMergeAdd",
"ModelMergeBlocks",
"ModelMergeSD1",
"ModelMergeSD2",
"ModelMergeSDXL",
"ModelMergeSimple",
"ModelMergeSubtract",
"ModelSamplingContinuousEDM",
"ModelSamplingDiscrete",
"ModelSamplingStableCascade",
"Morphology",
"PatchModelAddDownscale",
"PerpNeg",
"PerpNegGuider",
"PerturbedAttentionGuidance",
"PhotoMakerEncode",
"PhotoMakerLoader",
"PolyexponentialScheduler",
"PorterDuffImageComposite",
"PreviewImage",
"RandomNoise",
"RebatchImages",
"RebatchLatents",
"RepeatImageBatch",
@ -489,25 +702,40 @@
"RescaleCFG",
"SDTurboScheduler",
"SD_4XUpscale_Conditioning",
"SV3D_Conditioning",
"SVD_img2vid_Conditioning",
"SamplerCustom",
"SamplerCustomAdvanced",
"SamplerDPMAdaptative",
"SamplerDPMPP_2M_SDE",
"SamplerDPMPP_3M_SDE",
"SamplerDPMPP_SDE",
"SamplerEulerAncestral",
"SamplerLMS",
"SaveAnimatedPNG",
"SaveAnimatedWEBP",
"SaveImage",
"SaveImageWebsocket",
"SaveLatent",
"SelfAttentionGuidance",
"SetLatentNoiseMask",
"SolidMask",
"SplitImageWithAlpha",
"SplitSigmas",
"StableCascade_EmptyLatentImage",
"StableCascade_StageB_Conditioning",
"StableCascade_StageC_VAEEncode",
"StableCascade_SuperResolutionControlnet",
"StableZero123_Conditioning",
"StableZero123_Conditioning_Batched",
"StyleModelApply",
"StyleModelLoader",
"ThresholdMask",
"TomePatchModel",
"UNETLoader",
"UNetCrossAttentionMultiply",
"UNetSelfAttentionMultiply",
"UNetTemporalAttentionMultiply",
"UpscaleModelLoader",
"VAEDecode",
"VAEDecodeTiled",
@ -518,6 +746,7 @@
"VAESave",
"VPScheduler",
"VideoLinearCFGGuidance",
"VideoTriangleCFGGuidance",
"unCLIPCheckpointLoader",
"unCLIPConditioning"
],
@ -525,6 +754,62 @@
"title_aux": "ComfyUI"
}
],
"https://github.com/dezi-ai/ComfyUI-AnimateLCM": [
[
"ADE_AdjustPEFullStretch",
"ADE_AdjustPEManual",
"ADE_AdjustPESweetspotStretch",
"ADE_AnimateDiffCombine",
"ADE_AnimateDiffKeyframe",
"ADE_AnimateDiffLoRALoader",
"ADE_AnimateDiffLoaderGen1",
"ADE_AnimateDiffLoaderV1Advanced",
"ADE_AnimateDiffLoaderWithContext",
"ADE_AnimateDiffModelSettings",
"ADE_AnimateDiffModelSettingsAdvancedAttnStrengths",
"ADE_AnimateDiffModelSettingsSimple",
"ADE_AnimateDiffModelSettings_Release",
"ADE_AnimateDiffSamplingSettings",
"ADE_AnimateDiffSettings",
"ADE_AnimateDiffUniformContextOptions",
"ADE_AnimateDiffUnload",
"ADE_ApplyAnimateDiffModel",
"ADE_ApplyAnimateDiffModelSimple",
"ADE_BatchedContextOptions",
"ADE_EmptyLatentImageLarge",
"ADE_IterationOptsDefault",
"ADE_IterationOptsFreeInit",
"ADE_LoadAnimateDiffModel",
"ADE_LoopedUniformContextOptions",
"ADE_LoopedUniformViewOptions",
"ADE_MaskedLoadLora",
"ADE_MultivalDynamic",
"ADE_MultivalScaledMask",
"ADE_NoiseLayerAdd",
"ADE_NoiseLayerAddWeighted",
"ADE_NoiseLayerReplace",
"ADE_StandardStaticContextOptions",
"ADE_StandardStaticViewOptions",
"ADE_StandardUniformContextOptions",
"ADE_StandardUniformViewOptions",
"ADE_UseEvolvedSampling",
"ADE_ViewsOnlyContextOptions",
"AnimateDiffLoaderV1",
"CheckpointLoaderSimpleWithNoiseSelect"
],
{
"title_aux": "ComfyUI Animate LCM"
}
],
"https://github.com/dfl/comfyui-stylegan": [
[
"StyleGAN Generator",
"StyleGAN ModelLoader"
],
{
"title_aux": "comfyui-stylegan"
}
],
"https://github.com/dnl13/ComfyUI-dnl13-seg": [
[
"Automatic Segmentation (dnl13)",
@ -555,25 +840,41 @@
[
"ApplyVoiceFixer",
"BatchAudio",
"ClipAudio",
"BlendAudio",
"ClipAudioRegion",
"CombineImageWithAudio",
"ConcatAudio",
"ConvertAudio",
"FilterAudio",
"FlattenAudioBatch",
"HifiGANApply",
"HifiGANLoader",
"HifiGANModelParams",
"InvertAudioPhase",
"LoadAudio",
"MusicgenGenerate",
"MusicgenHFGenerate",
"MusicgenHFLoader",
"MusicgenLoader",
"NormalizeAudio",
"PreviewAudio",
"ResampleAudio",
"SaveAudio",
"SpectrogramImage",
"Tacotron2Generate",
"Tacotron2Loader",
"ToMelSpectrogram",
"TortoiseTTSGenerate",
"TortoiseTTSLoader",
"TrimAudio",
"TrimAudioSamples",
"TrimSilence",
"VALLEXGenerator",
"VALLEXLoader",
"VALLEXVoicePromptFromAudio",
"VALLEXVoicePromptLoader"
"VALLEXVoicePromptLoader",
"WaveGlowApply",
"WaveGlowLoader"
],
{
"title_aux": "ComfyUI-audio"
@ -606,9 +907,75 @@
"title_aux": "ComfyUI_stable_fast"
}
],
"https://github.com/houdinii/comfy-magick": [
[
"AdaptiveBlur",
"AdaptiveSharpen",
"AddNoise",
"BlueShift",
"Blur",
"Charcoal",
"Colorize",
"CropByAspectRatio",
"Despeckle",
"Edge",
"Emboss",
"FX",
"GaussianBlur",
"Implode",
"Kuwahara",
"MotionBlur",
"RotationalBlur",
"SelectiveBlur",
"Sepia",
"Shade",
"Sharpen",
"Sketch",
"Solarize",
"Spread",
"Stereogram",
"Swirl",
"Tint",
"UnsharpMask",
"Vignette",
"WaveletDenoise"
],
{
"title_aux": "comfy-magick [WIP]"
}
],
"https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui": [
[
"EasyBgRemover",
"EasyBgRemover_ModelLoader",
"EasyControlNetApply",
"EasyControlNetLoader",
"EasyEmptyLatentImage",
"EasyLatentToCondition",
"EasyLoadImage"
],
{
"title_aux": "ComfyUI_Easy_Nodes_hui"
}
],
"https://github.com/hy134300/comfyui-hb-node": [
[
"generate story",
"hy save image",
"latent to list",
"movie batch",
"movie generate",
"sound voice",
"text concat"
],
{
"title_aux": "comfyui-hb-node"
}
],
"https://github.com/ilovejohnwhite/UncleBillyGoncho": [
[
"CannyEdgePreprocessor",
"DiffusionEdge_Preprocessor",
"HintImageEnchance",
"ImageGenResolutionFromImage",
"ImageGenResolutionFromLatent",
@ -702,22 +1069,18 @@
"title_aux": "jn_node_suite_comfyui [WIP]"
}
],
"https://github.com/kadirnar/ComfyUI-Transformers": [
"https://github.com/kadirnar/ComfyUI-Adapter": [
[
"DepthEstimationPipeline"
"GarmentSegLoader"
],
{
"title_aux": "ComfyUI-Transformers"
"title_aux": "ComfyUI-Adapter [WIP]"
}
],
"https://github.com/kadirnar/comfyui_helpers": [
[
"CLIPSeg",
"CircularVAEDecode",
"CombineMasks",
"CustomKSamplerAdvancedTile",
"ImageLoaderAndProcessor",
"ImageToContrastMask",
"JDC_AutoContrast",
"JDC_BlendImages",
"JDC_BrownNoise",
@ -745,13 +1108,23 @@
],
"https://github.com/kappa54m/ComfyUI_Usability": [
[
"LoadImageByPath",
"LoadImageDedup"
"KLoadImageByPath",
"KLoadImageByPathAdvanced",
"KLoadImageDedup"
],
{
"title_aux": "ComfyUI_Usability (WIP)"
}
],
"https://github.com/kijai/ComfyUI-DeepSeek-VL": [
[
"deepseek_vl_inference",
"deepseek_vl_model_loader"
],
{
"title_aux": "ComfyUI nodes to use DeepSeek-VL"
}
],
"https://github.com/komojini/ComfyUI_Prompt_Template_CustomNodes/raw/main/prompt_with_template.py": [
[
"ObjectPromptWithTemplate",
@ -769,6 +1142,16 @@
"title_aux": "ssd-1b-comfyui"
}
],
"https://github.com/logtd/ComfyUI-MotionThiefExperiment": [
[
"ApplyRefMotionNode",
"MotionRefSettingsCustomNode",
"MotionRefSettingsDefaultNode"
],
{
"title_aux": "ComfyUI-MotionThiefExperiment"
}
],
"https://github.com/ltdrdata/ComfyUI-Workflow-Component": [
[
"ComboToString",
@ -787,6 +1170,22 @@
"title_aux": "ComfyUI-Workflow-Component [WIP]"
}
],
"https://github.com/marcueberall/ComfyUI-BuildPath": [
[
"Build Path Adv"
],
{
"title_aux": "ComfyUI-BuildPath"
}
],
"https://github.com/mut-ex/comfyui-gligengui-node": [
[
"GLIGEN_GUI"
],
{
"title_aux": "ComfyUI GLIGEN GUI Node"
}
],
"https://github.com/nidefawl/ComfyUI-nidefawl": [
[
"BlendImagesWithBoundedMasks",
@ -820,7 +1219,9 @@
"PromptUtilitiesFormatString",
"PromptUtilitiesJoinStringList",
"PromptUtilitiesLoadPreset",
"PromptUtilitiesLoadPresetAdvanced"
"PromptUtilitiesLoadPresetAdvanced",
"PromptUtilitiesRandomPreset",
"PromptUtilitiesRandomPresetAdvanced"
],
{
"title_aux": "ComfyUI-PromptUtilities"
@ -868,6 +1269,108 @@
"title_aux": "prism-tools"
}
],
"https://github.com/sdfxai/SDFXBridgeForComfyUI": [
[
"SDFXClipTextEncode"
],
{
"title_aux": "SDFXBridgeForComfyUI - ComfyUI Custom Node for SDFX Integration"
}
],
"https://github.com/shadowcz007/comfyui-CLIPSeg": [
[
"CLIPSeg_",
"CombineMasks_"
],
{
"title_aux": "comfyui-CLIPSeg"
}
],
"https://github.com/shadowcz007/comfyui-musicgen": [
[
"Musicgen"
],
{
"title_aux": "comfyui-musicgen"
}
],
"https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4": [
[
"CLIPTextEncodeAndEnhance"
],
{
"title_aux": "CLIPTextEncodeAndEnhancev4 (shirazdesigner)"
}
],
"https://github.com/stutya/ComfyUI-Terminal": [
[
"Terminal"
],
{
"title_aux": "ComfyUI-Terminal [UNSAFE]"
}
],
"https://github.com/sugarkwork/comfyui_psd": [
[
"SavePSD"
],
{
"title_aux": "comfyui_psd [WIP]"
}
],
"https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes": [
[
"ImageSizer",
"KSamplerSDXLAdvanced"
],
{
"title_aux": "my-useful-comfyui-custom-nodes"
}
],
"https://github.com/tuckerdarby/ComfyUI-TDNodes": [
[
"HandTrackerNode",
"InstanceDiffusionLoader",
"InstanceTrackerPrompt",
"KSamplerBatchedNode",
"KSamplerRAVE",
"KSamplerTF",
"TemporalNetPreprocessor",
"TrackerNode",
"VideoTrackerPromptNode"
],
{
"title_aux": "ComfyUI-TDNodes [WIP]"
}
],
"https://github.com/umisetokikaze/comfyui_mergekit": [
[
"DefineSaveName",
"LoadLR",
"LoadTarget",
"Merge",
"SetLayer",
"SetModels",
"SetTokenizer",
"get_skip"
],
{
"title_aux": "comfyui_mergekit [WIP]"
}
],
"https://github.com/unanan/ComfyUI-Dist": [
[
"LoadCheckpointFromLAN",
"LoadCheckpointFromURL",
"LoadImageFromLAN",
"LoadImageFromURL",
"LoadWorkflowFromLAN",
"LoadWorkflowFromURL"
],
{
"title_aux": "ComfyUI-Dist [WIP]"
}
],
"https://github.com/unanan/ComfyUI-clip-interrogator": [
[
"ComfyUIClipInterrogator",

View File

@ -0,0 +1,350 @@
{
"https://github.com/longgui0318/comfyui-one-more-step": {
"stars": 0,
"last_update": "2024-04-28 10:33:08"
},
"https://github.com/TemryL/ComfyUI-IDM-VTON": {
"stars": 11,
"last_update": "2024-04-28 23:39:01"
},
"https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4": {
"stars": 0,
"last_update": "2024-04-27 13:25:08"
},
"https://github.com/umisetokikaze/comfyui_mergekit": {
"stars": 0,
"last_update": "2024-04-28 07:21:00"
},
"https://github.com/Video3DGenResearch/comfyui-batch-input-node": {
"stars": 1,
"last_update": "2024-04-28 15:21:17"
},
"https://github.com/kijai/ComfyUI-DeepSeek-VL": {
"stars": 12,
"last_update": "2024-04-23 18:10:42"
},
"https://github.com/GentlemanHu/ComfyUI-Notifier": {
"stars": 1,
"last_update": "2024-04-26 04:22:25"
},
"https://github.com/nat-chan/comfyui-in-memory-transceiver": {
"stars": 1,
"last_update": "2024-04-24 04:11:05"
},
"https://github.com/DrMWeigand/ComfyUI_LineBreakInserter": {
"stars": 0,
"last_update": "2024-04-19 11:37:19"
},
"https://github.com/WilliamStanford/visuallabs_comfyui_nodes": {
"stars": 1,
"last_update": "2024-04-16 21:53:02"
},
"https://github.com/bruce007lee/comfyui-cleaner": {
"stars": 2,
"last_update": "2024-04-20 15:36:03"
},
"https://github.com/ExponentialML/ComfyUI_LiveDirector": {
"stars": 32,
"last_update": "2024-04-09 19:01:49"
},
"https://github.com/logtd/ComfyUI-MotionThiefExperiment": {
"stars": 34,
"last_update": "2024-04-09 01:00:51"
},
"https://github.com/hy134300/comfyui-hb-node": {
"stars": 0,
"last_update": "2024-04-09 09:56:22"
},
"https://github.com/gameltb/io_comfyui": {
"stars": 3,
"last_update": "2024-04-06 04:40:05"
},
"https://github.com/ALatentPlace/ComfyUI_yanc": {
"stars": 4,
"last_update": "2024-04-16 19:03:34"
},
"https://github.com/Jiffies-64/ComfyUI-SaveImagePlus": {
"stars": 0,
"last_update": "2024-04-01 10:52:59"
},
"https://github.com/kadirnar/ComfyUI-Adapter": {
"stars": 3,
"last_update": "2024-04-03 12:05:39"
},
"https://github.com/Beinsezii/comfyui-amd-go-fast": {
"stars": 3,
"last_update": "2024-03-31 01:17:57"
},
"https://github.com/sugarkwork/comfyui_psd": {
"stars": 0,
"last_update": "2024-03-26 08:24:56"
},
"https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt": {
"stars": 15,
"last_update": "2024-03-17 04:30:01"
},
"https://github.com/MushroomFleet/DJZ-Nodes": {
"stars": 3,
"last_update": "2024-03-18 11:18:42"
},
"https://github.com/stavsap/ComfyUI-React-SDK": {
"stars": 5,
"last_update": "2024-03-17 21:54:21"
},
"https://github.com/chaojie/ComfyUI-DynamiCrafter": {
"stars": 86,
"last_update": "2024-03-16 19:08:28"
},
"https://github.com/cubiq/Comfy_Dungeon": {
"stars": 134,
"last_update": "2024-04-26 11:00:58"
},
"https://github.com/dfl/comfyui-stylegan": {
"stars": 1,
"last_update": "2024-03-14 14:34:25"
},
"https://github.com/christian-byrne/elimination-nodes": {
"stars": 4,
"last_update": "2024-04-09 18:51:29"
},
"https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1": {
"stars": 12,
"last_update": "2024-03-08 10:11:44"
},
"https://github.com/houdinii/comfy-magick": {
"stars": 4,
"last_update": "2024-03-11 06:40:54"
},
"https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes": {
"stars": 0,
"last_update": "2024-03-05 13:31:31"
},
"https://github.com/DeTK/ComfyUI-Switch": {
"stars": 0,
"last_update": "2024-03-04 11:52:04"
},
"https://github.com/GrindHouse66/ComfyUI-GH_Tools": {
"stars": 0,
"last_update": "2024-03-10 13:27:14"
},
"https://github.com/sdfxai/SDFXBridgeForComfyUI": {
"stars": 2,
"last_update": "2024-04-12 14:09:45"
},
"https://github.com/SeedV/ComfyUI-SeedV-Nodes": {
"stars": 1,
"last_update": "2024-04-23 07:56:19"
},
"https://github.com/mut-ex/comfyui-gligengui-node": {
"stars": 24,
"last_update": "2024-02-28 02:46:05"
},
"https://github.com/unanan/ComfyUI-Dist": {
"stars": 4,
"last_update": "2024-02-28 10:03:50"
},
"https://github.com/NicholasKao1029/comfyui-hook": {
"stars": 0,
"last_update": "2024-03-07 05:50:56"
},
"https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI": {
"stars": 13,
"last_update": "2024-03-10 01:04:02"
},
"https://github.com/shadowcz007/comfyui-llamafile": {
"stars": 10,
"last_update": "2024-04-29 08:35:31"
},
"https://github.com/gameltb/ComfyUI_paper_playground": {
"stars": 7,
"last_update": "2024-04-06 10:30:44"
},
"https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui": {
"stars": 2,
"last_update": "2024-02-27 08:22:49"
},
"https://github.com/tuckerdarby/ComfyUI-TDNodes": {
"stars": 3,
"last_update": "2024-02-19 17:00:55"
},
"https://github.com/shadowcz007/comfyui-musicgen": {
"stars": 0,
"last_update": "2024-02-13 08:45:12"
},
"https://github.com/shadowcz007/comfyui-CLIPSeg": {
"stars": 0,
"last_update": "2024-02-08 02:16:24"
},
"https://github.com/dezi-ai/ComfyUI-AnimateLCM": {
"stars": 127,
"last_update": "2024-02-07 17:34:39"
},
"https://github.com/stutya/ComfyUI-Terminal": {
"stars": 0,
"last_update": "2024-02-05 16:47:28"
},
"https://github.com/marcueberall/ComfyUI-BuildPath": {
"stars": 0,
"last_update": "2024-02-06 07:57:33"
},
"https://github.com/LotzF/ComfyUI-Simple-Chat-GPT-completion": {
"stars": 0,
"last_update": "2024-02-04 21:15:22"
},
"https://github.com/kappa54m/ComfyUI_Usability": {
"stars": 0,
"last_update": "2024-02-05 14:49:45"
},
"https://github.com/17Retoucher/ComfyUI_Fooocus": {
"stars": 50,
"last_update": "2024-02-24 07:33:29"
},
"https://github.com/nkchocoai/ComfyUI-PromptUtilities": {
"stars": 6,
"last_update": "2024-02-21 14:47:42"
},
"https://github.com/BadCafeCode/execution-inversion-demo-comfyui": {
"stars": 3,
"last_update": "2024-03-23 23:53:13"
},
"https://github.com/unanan/ComfyUI-clip-interrogator": {
"stars": 18,
"last_update": "2024-02-01 09:46:57"
},
"https://github.com/prismwastaken/comfyui-tools": {
"stars": 0,
"last_update": "2024-03-05 14:34:56"
},
"https://github.com/poisenbery/NudeNet-Detector-Provider": {
"stars": 1,
"last_update": "2024-02-26 02:11:27"
},
"https://github.com/LarryJane491/ComfyUI-ModelUnloader": {
"stars": 1,
"last_update": "2024-01-14 08:22:39"
},
"https://github.com/AIGODLIKE/ComfyUI-Studio": {
"stars": 185,
"last_update": "2024-04-03 03:59:31"
},
"https://github.com/MrAdamBlack/CheckProgress": {
"stars": 1,
"last_update": "2024-01-10 08:02:18"
},
"https://github.com/birnam/ComfyUI-GenData-Pack": {
"stars": 0,
"last_update": "2024-03-25 01:25:23"
},
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText": {
"stars": 38,
"last_update": "2024-01-07 11:48:05"
},
"https://github.com/nidefawl/ComfyUI-nidefawl": {
"stars": 0,
"last_update": "2024-01-16 18:16:41"
},
"https://github.com/kadirnar/comfyui_helpers": {
"stars": 2,
"last_update": "2024-03-04 16:25:30"
},
"https://github.com/foglerek/comfyui-cem-tools": {
"stars": 1,
"last_update": "2024-01-13 23:22:07"
},
"https://github.com/talesofai/comfyui-supersave": {
"stars": 1,
"last_update": "2023-12-27 02:05:53"
},
"https://github.com/Sai-ComfyUI/ComfyUI-MS-Nodes": {
"stars": 2,
"last_update": "2024-02-22 08:34:44"
},
"https://github.com/eigenpunk/ComfyUI-audio": {
"stars": 44,
"last_update": "2024-03-03 21:14:14"
},
"https://github.com/Jaxkr/comfyui-terminal-command": {
"stars": 1,
"last_update": "2023-12-03 10:31:40"
},
"https://github.com/BlueDangerX/ComfyUI-BDXNodes": {
"stars": 1,
"last_update": "2023-12-10 04:01:19"
},
"https://github.com/ilovejohnwhite/UncleBillyGoncho": {
"stars": 0,
"last_update": "2024-02-29 00:16:42"
},
"https://github.com/IvanZhd/comfyui-codeformer": {
"stars": 0,
"last_update": "2023-12-02 20:51:52"
},
"https://github.com/alt-key-project/comfyui-dream-video-batches": {
"stars": 46,
"last_update": "2023-12-03 10:31:55"
},
"https://github.com/oyvindg/ComfyUI-TrollSuite": {
"stars": 0,
"last_update": "2023-11-21 01:46:07"
},
"https://github.com/romeobuilderotti/ComfyUI-EZ-Pipes": {
"stars": 3,
"last_update": "2023-11-15 22:00:49"
},
"https://github.com/wormley/comfyui-wormley-nodes": {
"stars": 0,
"last_update": "2023-11-12 19:05:11"
},
"https://github.com/dnl13/ComfyUI-dnl13-seg": {
"stars": 17,
"last_update": "2024-01-08 10:52:13"
},
"https://github.com/phineas-pta/comfy-trt-test": {
"stars": 77,
"last_update": "2024-03-10 21:17:56"
},
"https://github.com/Brandelan/ComfyUI_bd_customNodes": {
"stars": 1,
"last_update": "2023-10-09 00:40:26"
},
"https://github.com/Jordach/comfy-consistency-vae": {
"stars": 68,
"last_update": "2023-11-06 20:50:40"
},
"https://github.com/gameltb/ComfyUI_stable_fast": {
"stars": 174,
"last_update": "2024-04-01 13:30:57"
},
"https://github.com/jn-jairo/jn_node_suite_comfyui": {
"stars": 5,
"last_update": "2024-01-11 20:39:36"
},
"https://github.com/PluMaZero/ComfyUI-SpaceFlower": {
"stars": 4,
"last_update": "2023-12-09 05:55:15"
},
"https://github.com/laksjdjf/ssd-1b-comfyui": {
"stars": 1,
"last_update": "2023-10-27 20:05:06"
},
"https://github.com/flowtyone/comfyui-flowty-lcm": {
"stars": 62,
"last_update": "2023-10-23 12:08:55"
},
"https://github.com/doucx/ComfyUI_WcpD_Utility_Kit": {
"stars": 1,
"last_update": "2024-01-06 19:07:45"
},
"https://github.com/WSJUSA/Comfyui-StableSR": {
"stars": 32,
"last_update": "2023-10-18 12:40:30"
},
"https://github.com/ltdrdata/ComfyUI-Workflow-Component": {
"stars": 181,
"last_update": "2024-04-26 01:39:09"
},
"https://github.com/comfyanonymous/ComfyUI": {
"stars": 33530,
"last_update": "2024-04-29 00:08:28"
}
}

View File

@ -10,6 +10,36 @@
},
{
"author": "kijai",
"title": "ComfyUI wrapper nodes for IC-light [DEPRECATED]",
"reference": "https://github.com/kijai/ComfyUI-IC-Light-Wrapper",
"files": [
"https://github.com/kijai/ComfyUI-IC-Light-Wrapper"
],
"install_type": "git-clone",
"description": "Stopped. Original repo: [a/https://github.com/lllyasviel/IC-Light](https://github.com/lllyasviel/IC-Light)"
},
{
"author": "thedyze",
"title": "Save Image Extended for ComfyUI",
"reference": "https://github.com/thedyze/save-image-extended-comfyui",
"files": [
"https://github.com/thedyze/save-image-extended-comfyui"
],
"install_type": "git-clone",
"description": "Customize the information saved in file- and folder names. Use the values of sampler parameters as part of file or folder names. Save your positive & negative prompt as entries in a JSON (text) file, in each folder.\n[w/This custom node has not been maintained for a long time. Please use an alternative node from the default channel.]"
},
{
"author": "ExponentialML",
"title": "ComfyUI_ELLA [DEPRECATED]",
"reference": "https://github.com/ExponentialML/ComfyUI_ELLA",
"files": [
"https://github.com/ExponentialML/ComfyUI_ELLA"
],
"install_type": "git-clone",
"description": "ComfyUI Implementaion of ELLA: Equip Diffusion Models with LLM for Enhanced Semantic Alignment.[w/Officially implemented here: [a/https://github.com/TencentQQGYLab/ComfyUI-ELLA](https://github.com/TencentQQGYLab/ComfyUI-ELLA)]"
},
{
"author": "shinich39",
"title": "comfyui-text-pipe-39 [DEPRECATED]",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,35 @@
{
"models": [
{
"name": "MonsterMMORPG/insightface (for InstantID)",
"type": "insightface",
"base": "SDXL",
"save_path": "insightface/models",
"description": "MonsterMMORPG insightface model for cubiq/InstantID",
"reference": "https://huggingface.co/MonsterMMORPG/tools/tree/main",
"filename": "antelopev2.zip",
"url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/antelopev2.zip"
},
{
"name": "InstantID/ip-adapter",
"type": "instantid",
"base": "SDXL",
"save_path": "instantid/SDXL",
"description": "ip-adapter model for cubiq/InstantID",
"reference": "https://huggingface.co/InstantX/InstantID",
"filename": "ip-adapter.bin",
"url": "https://huggingface.co/InstantX/InstantID/resolve/main/ip-adapter.bin"
},
{
"name": "InstantID/ControlNet",
"type": "controlnet",
"base": "SDXL",
"save_path": "controlnet/SDXL/instantid",
"description": "instantid controlnet model for cubiq/InstantID",
"reference": "https://huggingface.co/InstantX/InstantID",
"filename": "diffusion_pytorch_model.safetensors",
"url": "https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors"
},
{
"name": "ip_plus_composition_sd15.safetensors",
"type": "IP-Adapter",
@ -671,27 +701,6 @@
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v3_sd15_adapter.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v3_sd15_adapter.ckpt"
},
{
"name": "Segmind-Vega",
"type": "checkpoints",
"base": "segmind-vega",
"save_path": "checkpoints/segmind-vega",
"description": "The Segmind-Vega Model is a distilled version of the Stable Diffusion XL (SDXL), offering a remarkable 70% reduction in size and an impressive 100% speedup while retaining high-quality text-to-image generation capabilities.",
"reference": "https://huggingface.co/segmind/Segmind-Vega",
"filename": "segmind-vega.safetensors",
"url": "https://huggingface.co/segmind/Segmind-Vega/resolve/main/segmind-vega.safetensors"
},
{
"name": "Segmind-VegaRT - Latent Consistency Model (LCM) LoRA of Segmind-Vega",
"type": "lora",
"base": "segmind-vega",
"save_path": "loras/segmind-vega",
"description": "Segmind-VegaRT a distilled consistency adapter for Segmind-Vega that allows to reduce the number of inference steps to only between 2 - 8 steps.",
"reference": "https://huggingface.co/segmind/Segmind-VegaRT",
"filename": "pytorch_lora_weights.safetensors",
"url": "https://huggingface.co/segmind/Segmind-VegaRT/resolve/main/pytorch_lora_weights.safetensors"
}
]
}

View File

@ -179,6 +179,16 @@
],
"install_type": "git-clone",
"description": "Nodes:Concatenate multiple text nodes."
},
{
"author": "nilor-corp",
"title": "nilor-nodes",
"reference": "https://github.com/nilor-corp/nilor-nodes",
"files": [
"https://github.com/nilor-corp/nilor-nodes"
],
"install_type": "git-clone",
"description": "Custom utility nodes for ComfyUI"
}
]
}

View File

@ -302,26 +302,26 @@ except Exception as e:
try:
import git
except:
except ModuleNotFoundError:
my_path = os.path.dirname(__file__)
requirements_path = os.path.join(my_path, "requirements.txt")
print(f"## ComfyUI-Manager: installing dependencies. (GitPython)")
result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '-r', requirements_path])
try:
import git
except:
result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '-r', requirements_path])
except subprocess.CalledProcessError as e:
print(f"## [ERROR] ComfyUI-Manager: Attempting to reinstall dependencies using an alternative method.")
result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '--user', '-r', requirements_path])
try:
import git
except:
result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '--user', '-r', requirements_path])
except subprocess.CalledProcessError as e:
print(f"## [ERROR] ComfyUI-Manager: Failed to install the GitPython package in the correct Python environment. Please install it manually in the appropriate environment. (You can seek help at https://app.element.io/#/room/%23comfyui_space%3Amatrix.org)")
try:
import git
print(f"## ComfyUI-Manager: installing dependencies done.")
except:
# maybe we should sys.exit() here? there is at least two screens worth of error messages still being pumped after our error messages
print(f"## [ERROR] ComfyUI-Manager: GitPython package seems to be installed, but failed to load somehow. Make sure you have a working git client installed")
print("** ComfyUI startup time:", datetime.datetime.now())

View File

@ -37,21 +37,35 @@ else:
print(f"TEMP DIR: {temp_dir}")
parse_cnt = 0
def extract_nodes(code_text):
global parse_cnt
try:
if parse_cnt % 100 == 0:
print(f".", end="", flush=True)
parse_cnt += 1
code_text = re.sub(r'\\[^"\']', '', code_text)
parsed_code = ast.parse(code_text)
assignments = (node for node in parsed_code.body if isinstance(node, ast.Assign))
for assignment in assignments:
if isinstance(assignment.targets[0], ast.Name) and assignment.targets[0].id == 'NODE_CLASS_MAPPINGS':
if isinstance(assignment.targets[0], ast.Name) and assignment.targets[0].id in ['NODE_CONFIG', 'NODE_CLASS_MAPPINGS']:
node_class_mappings = assignment.value
break
else:
node_class_mappings = None
if node_class_mappings:
s = set([key.s.strip() for key in node_class_mappings.keys if key is not None])
s = set()
for key in node_class_mappings.keys:
if key is not None and isinstance(key.value, str):
s.add(key.value.strip())
return s
else:
return set()
@ -78,20 +92,24 @@ def scan_in_file(filename, is_builtin=False):
nodes |= extract_nodes(code)
pattern2 = r'^[^=]*_CLASS_MAPPINGS\["(.*?)"\]'
keys = re.findall(pattern2, code)
for key in keys:
nodes.add(key.strip())
def extract_keys(pattern, code):
keys = re.findall(pattern, code)
return {key.strip() for key in keys}
pattern3 = r'^[^=]*_CLASS_MAPPINGS\[\'(.*?)\'\]'
keys = re.findall(pattern3, code)
for key in keys:
nodes.add(key.strip())
def update_nodes(nodes, new_keys):
nodes |= new_keys
pattern4 = r'@register_node\("(.+)",\s*\".+"\)'
keys = re.findall(pattern4, code)
for key in keys:
nodes.add(key.strip())
patterns = [
r'^[^=]*_CLASS_MAPPINGS\["(.*?)"\]',
r'^[^=]*_CLASS_MAPPINGS\[\'(.*?)\'\]',
r'@register_node\("(.+)",\s*\".+"\)',
r'"(\w+)"\s*:\s*{"class":\s*\w+\s*'
]
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = {executor.submit(extract_keys, pattern, code): pattern for pattern in patterns}
for future in concurrent.futures.as_completed(futures):
update_nodes(nodes, future.result())
matches = regex.findall(code)
for match in matches:
@ -208,7 +226,7 @@ def clone_or_pull_git_repository(git_url):
try:
repo = Repo(repo_dir)
origin = repo.remote(name="origin")
origin.pull(rebase=True)
origin.pull()
repo.git.submodule('update', '--init', '--recursive')
print(f"Pulling {repo_name}...")
except Exception as e:
@ -306,12 +324,8 @@ def update_custom_nodes():
json.dump(github_stats, file, ensure_ascii=False, indent=4)
print(f"Successfully written to {GITHUB_STATS_FILENAME}, removing {GITHUB_STATS_CACHE_FILENAME}.")
# try:
# os.remove(GITHUB_STATS_CACHE_FILENAME) # This cache file is just for avoiding failure of GitHub API fetch, so it is safe to remove.
# except:
# pass
print(f"Successfully written to {GITHUB_STATS_FILENAME}.")
with concurrent.futures.ThreadPoolExecutor(11) as executor:
if not skip_stat_update:
executor.submit(process_git_stats, git_url_titles_preemptions) # One single thread for `process_git_stats()`. Runs concurrently with `process_git_url_title()`.
@ -450,3 +464,4 @@ updated_node_info = update_custom_nodes()
print("\n# 'extension-node-map.json' file is generated.\n")
gen_json(updated_node_info)
print("\nDONE.\n")