Merge pull request #50 from storytold/feature/comfyui-sidecar

comfyUI previews
This commit is contained in:
salt
2024-03-22 21:00:57 -07:00
committed by GitHub
9 changed files with 691 additions and 0 deletions
@@ -0,0 +1,70 @@
# Adapted from
# https://github.com/actions/starter-workflows/ci/docker-publish.yml
# If using base images, don't forget to add READ access, eg. from a package settings page like:
# https://github.com/orgs/storytold/packages/container/docker-base-images-rust-ssl/settings/actions_access
name: Build Comfy Preview Server Docker Image
on:
push:
paths:
- 'workflows/preview_server/**'
branches:
# NB: Default-branch doesn't work, despite Github's documentation.
#- $default-branch
- master
env:
IMAGE_NAME: comfy-previews
jobs:
# Push image to GitHub Packages.
# See also https://docs.docker.com/docker-hub/builds/
push:
#runs-on: ubuntu-latest
runs-on: github-ubuntu-64core # NB: Premium GitHub runner with more cores
if: github.event_name == 'push'
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v2
with:
lfs: true # Ensure Git LFS files are checked out
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
#username: ${{ github.repository_owner }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build image
run: cd workflows/preview_server/ && docker build . --file Dockerfile --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}"
- name: Push image to GitHub Container Registry
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
# Change all uppercase to lowercase
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
# Strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
# Use Docker `latest` tag convention
[ "$VERSION" == "$default-branch" ] && VERSION=latest
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION
SHORT_SHA=$(echo ${GITHUB_SHA} | cut -c1-12)
docker tag $IMAGE_NAME $IMAGE_ID:$SHORT_SHA
docker push $IMAGE_ID:$SHORT_SHA
+52
View File
@@ -0,0 +1,52 @@
# NB(bt, 2022-12-12): The version of containerized CUDA must match (or be less than?) that of the host system running this container.
# Juggling these dependencies, plus the underlying Ubuntu system (which controls Python versions), is tricky.
# Nvidia does not provide a CUDA 11.6 with Ubuntu 22.04, which mirrors my own desktop machine. Their CUDA 11.6 + Ubuntu 20.04 image has
# a stale Python (3.8), so we have to use the DeadSnakes PPA to install a more modern version.
# Gross.
FROM nvidia/cuda:11.8.0-devel-ubuntu22.04
# See: https://github.com/opencontainers/image-spec/blob/master/annotations.md
LABEL org.opencontainers.image.title='Storyteller ML: Voice Conversion'
LABEL org.opencontainers.image.authors='adrien@storyteller.ai'
# tzdata install hangs without presetting the time zone
ENV TZ=UTC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# Needed to install "future" release of Python 3.10 under Ubuntu 20.04, which only natively packages Python 3.8.
# We seem to be stuck on Ubuntu 22.04 because containerizd CUDA 11.6 is the only version we can run on my host machine,
# and Nvidia does not supply a (CUDA 11.6, Ubuntu 22.04) docker base image.
RUN apt-get update \
&& apt install software-properties-common -y \
&& add-apt-repository ppa:deadsnakes/ppa
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y \
curl \
ffmpeg \
libmagic-dev \
libmagic1 \
python3-pip \
python3.10 \
python3.10-venv \
unzip \
wget \
git \
--no-install-recommends
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
# Copy files to container
COPY --chown=appuser:appgroup initialize_comfy_extensions.py /app/initialize_comfy_extensions.py
COPY --chown=appuser:appgroup install.py /app/install.py
COPY --chown=appuser:appgroup repos.json /app/repos.json
COPY --chown=appuser:appgroup server_requirements.txt.txt /app/server_requirements.txt.txt
COPY --chown=appuser:appgroup required_requirements.txt /app/required_requirements.txt
COPY --chown=appuser:appgroup preview_server.py /app/preview_server.py
RUN pip3 install --no-cache-dir --upgrade pip setuptools wheel requests argparse
RUN chmod -R 777 /app
# protobuf use python implementation (weird error without)
ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
+126
View File
@@ -0,0 +1,126 @@
[
{
"location": "ComfyUI/models/loras/v3_sd15_adapter.ckpt",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/v3_sd15_adapter.ckpt"
},
{
"location": "ComfyUI/models/embeddings/badhandv4.pt",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/badhandv4.pt"
},
{
"location": "ComfyUI/models/embeddings/easynegative.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/easynegative.safetensors"
},
{
"location": "ComfyUI/models/controlnet/v3_sd15_sparsectrl_scribble.ckpt",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/v3_sd15_sparsectrl_scribble.ckpt"
},
{
"location": "ComfyUI/models/controlnet/control_v11f1e_sd15_tile.bin",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/control_v11f1e_sd15_tile.bin"
},
{
"location": "ComfyUI/models/controlnet/control_v11p_sd15_softedge.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/control_v11p_sd15_softedge.safetensors"
},
{
"location": "ComfyUI/models/controlnet/control_v11p_sd15s2_lineart_anime.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/control_v11p_sd15s2_lineart_anime.safetensors"
},
{
"location": "ComfyUI/models/controlnet/control_v11p_sd15_lineart.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/control_v11p_sd15_lineart.safetensors"
},
{
"location": "ComfyUI/models/controlnet/control_v11f1p_sd15_depth.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/control_v11f1p_sd15_depth.safetensors"
},
{
"location": "ComfyUI/models/controlnet/control_v11p_sd15_openpose.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/control_v11p_sd15_openpose.safetensors"
},
{
"location": "ComfyUI/models/controlnet/animatediff_controlnet.ckpt",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/animatediff_controlnet.ckpt"
},
{
"location": "ComfyUI/models/controlnet/control_v2p_sd15_mediapipe_face.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/control_v2p_sd15_mediapipe_face.safetensors"
},
{
"location": "ComfyUI/models/controlnet/ControlNetHED.pth",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/ControlNetHED.pth"
},
{
"location": "ComfyUI/models/ipadapter/ip-adapter_sd15_light.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/ip-adapter_sd15_light.safetensors"
},
{
"location": "ComfyUI/models/clip_vision/CLIP-ViT-H-14-laion2B-s32B-b79K.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/model.safetensors"
},
{
"location": "ComfyUI/custom_nodes/ComfyUI-AnimateDiff-Evolved/models/v3_sd15_mm.ckpt",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/v3_sd15_mm.ckpt"
},
{
"location": "ComfyUI/custom_nodes/comfyui_controlnet_aux/ckpts/hr16/DWPose-TorchScript-BatchSize5/dw-ll_ucoco_384_bs5.torchscript.pt",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/dw-ll_ucoco_384_bs5.torchscript.pt"
},
{
"location": "ComfyUI/custom_nodes/comfyui_controlnet_aux/ckpts/yzd-v/DWPose/yolox_l.onnx",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/yolox_l.onnx"
},
{
"location": "ComfyUI/custom_nodes/comfyui_controlnet_aux/ckpts/LiheYoung/Depth-Anything/checkpoints/depth_anything_vitl14.pth",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/depth_anything_vitl14.pth"
},
{
"location": "ComfyUI/custom_nodes/comfyui_controlnet_aux/ckpts/lllyasviel/Annotators/sk_model2.pth",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/sk_model2.pth"
},
{
"location": "ComfyUI/custom_nodes/comfyui_controlnet_aux/ckpts/lllyasviel/Annotators/sk_model.pth",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/sk_model.pth"
},
{
"location": "ComfyUI/custom_nodes/comfyui_controlnet_aux/ckpts/lllyasviel/Annotators/netG.pth",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/netG.pth"
},
{
"location": "ComfyUI/custom_nodes/comfyui_controlnet_aux/ckpts/lllyasviel/Annotators/ControlNetHED.pth",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/ControlNetHED.pth"
},
{
"location": "ComfyUI/custom_nodes/ComfyUI-Frame-Interpolation/ckpts/rife/rife47.pth",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/rife47.pth"
},
{
"location": "ComfyUI/input/example.png",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/example.png"
},
{
"location": "ComfyUI/custom_nodes/ComfyUI-AnimateDiff-Evolved/models/sd15_t2v_beta_motion.ckpt",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/sd15_t2v_beta_motion.ckpt"
},
{
"location": "ComfyUI/models/loras/LCM_LoRA_Weights_SD15.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/LCM_LoRA_Weights_SD15.safetensors"
},
{
"location": "ComfyUI/models/controlnet/control_v11p_sd15_canny.safetensors",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/control_v11p_sd15_canny.safetensors"
},
{
"location": "ComfyUI/models/grounding-dino/GroundingDINO_SwinT_OGC.cfg.py",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/GroundingDINO_SwinT_OGC.py"
},
{
"location": "ComfyUI/models/grounding-dino/groundingdino_swint_ogc.pth",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/groundingdino_swint_ogc.pth"
},
{
"location": "ComfyUI/models/vae/vae-ft-mse-840000-ema-pruned.ckpt",
"url": "https://storage.googleapis.com/vocodes-public/comfyui-deps/vae-ft-mse-840000-ema-pruned.ckpt"
}
]
@@ -0,0 +1,46 @@
import os
import sys
import asyncio
import threading
# Init all the nodes
current_script_dir = os.path.dirname(os.path.realpath(__file__))
comfy_path = os.path.dirname(os.path.abspath(__file__))
comfy_path = os.path.join(comfy_path, 'ComfyUI')
# change to ComfyUI directory
os.chdir(comfy_path)
# add ComfyUI to path
sys.path.append(comfy_path)
from server import PromptServer
from execution import PromptQueue
from main import init_custom_nodes, cuda_malloc_warning, prompt_worker, execute_prestartup_script
import folder_paths
execute_prestartup_script()
async def run():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
server = PromptServer(loop)
q = PromptQueue(server)
init_custom_nodes()
cuda_malloc_warning()
server.add_routes()
threading.Thread(target=prompt_worker, daemon=True, args=(q, server,)).start()
folder_paths.add_model_folder_path("checkpoints", os.path.join(folder_paths.get_output_directory(), "checkpoints"))
folder_paths.add_model_folder_path("clip", os.path.join(folder_paths.get_output_directory(), "clip"))
folder_paths.add_model_folder_path("vae", os.path.join(folder_paths.get_output_directory(), "vae"))
await server.start('127.0.0.1', 8188)
if __name__ == "__main__":
asyncio.run(run())
+101
View File
@@ -0,0 +1,101 @@
import subprocess
import json
import os
from pathlib import Path
import requests
# set cwd to script location
os.chdir(os.path.dirname(os.path.realpath(__file__)))
json_file_path = 'repos.json'
venv_python = os.path.join('ComfyUI', 'venv', 'Scripts' if os.name == 'nt' else 'bin', 'python')
def run_command(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
# Print stdout live
for line in iter(process.stdout.readline, ''):
print(line, end='')
# Wait for the process to terminate and get the exit code
process.wait()
# Check if the process exited with an error
if process.returncode != 0:
# Print any errors from stderr
for line in iter(process.stderr.readline, ''):
print(line, end='')
print(f"Error executing command: {command}")
def setup_repo(repo_info):
url, commit, folder = repo_info['url'], repo_info['commit'], repo_info['folder']
# save the current working directory
original_cwd = os.getcwd()
try:
run_command(f"git clone {url} {folder}")
os.chdir(folder)
run_command(f"git checkout {commit}")
finally:
os.chdir(original_cwd)
def setup_venv_and_install_requirements():
run_command("python3 -m venv ComfyUI/venv")
print('=============# Installing ComfyUI Requirements #=============')
run_command(f"{venv_python} -m pip install -r ComfyUI/requirements.txt")
print('=============# Installing extension missing requirements #=============')
run_command(f"{venv_python} -m pip install -r required_requirements.txt")
def run_comfyui_setup():
run_command(f"{venv_python} initialize_comfy_extensions.py")
def install_dependencies(json_file_path='dependencies.json'):
# Load the dependency JSON
with open(json_file_path, 'r') as file:
dependencies = json.load(file)
for dep in dependencies:
# Extract location and URL
location = dep['location']
url = dep['url']
# Convert the location to a Path object and create parent directories if they don't exist
path = Path(location)
path.parent.mkdir(parents=True, exist_ok=True)
if path.is_file():
print(f"{path} is already installed")
continue
# Download the file
response = requests.get(url)
if response.status_code == 200:
# Write the content to the file in the specified location
with open(path, 'wb') as file:
file.write(response.content)
print(f"Installed {path}")
else:
print(f"Failed to download {url}")
def main():
with open(json_file_path, 'r') as file:
repos = json.load(file)
for repo_info in repos:
print(f"installing {repo_info['url']} at commit {repo_info['commit']} to {repo_info['folder']}")
setup_repo(repo_info)
setup_venv_and_install_requirements()
install_dependencies()
run_comfyui_setup()
if __name__ == "__main__":
main()
open('ALREADY_SETUP.flag', 'w').close()
+146
View File
@@ -0,0 +1,146 @@
import os
import signal
import subprocess
import time
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import FileResponse
import shutil
from pathlib import Path
import asyncio
import uuid
import os
import json
import requests
import random
app = FastAPI()
lock = asyncio.Lock() # Create an asyncio lock
SERVER_IP = os.environ.get("SERVER_IP", "127.0.0.1:8188")
TIMEOUT_SECONDS = os.environ.get("TIMEOUT_SECONDS", 1000)
PROMPT_ENDPOINT = f"http://{SERVER_IP}/prompt"
PROMPT_FILE = os.environ.get("PROMPT_FILE", "prompt.json")
COMFY_ROOT_DIRECTORY = os.environ.get("COMFY_ROOT_DIRECTORY",
"/home/salt/clone/storyteller/storyteller-ml/workflows/comfy/ComfyUI")
SERVER_START_TIMEOUT = int(os.environ.get("SERVER_START_TIMEOUT", 60))
def terminate_process(proc):
proc.terminate()
try:
proc.wait(timeout=10)
except subprocess.TimeoutExpired:
proc.kill()
def signal_handler(signum, frame):
print("Signal received, shutting down.")
terminate_process(comfyui_process)
exit(0)
@app.post("/preview/")
async def upload_video(video: UploadFile = File(...)):
async with lock: # Acquire the lock
try:
# Save uploaded video to a temporary directory
video_filename = f"temp_videos/{uuid.uuid4()}.mp4" # Use a unique filename
Path("temp_videos").mkdir(parents=True, exist_ok=True) # Ensure the directory exists
with open(video_filename, "wb") as buffer:
shutil.copyfileobj(video.file, buffer)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to save video: {str(e)}")
# Process video and generate preview
preview_image_path = await process_video(video_filename)
return FileResponse(preview_image_path, media_type='image/jpeg')
async def process_video(video_path: str) -> Path:
json_prompt = json.load(open(PROMPT_FILE))
# generate random seed (otherwise video will cache completely and not generate a new output)
json_prompt["173"]["inputs"]["seed"] = random.randint(0, 1000000)
input_video_path = Path(COMFY_ROOT_DIRECTORY) / "input/input.mp4"
preview_image_path = Path(COMFY_ROOT_DIRECTORY) / "output/vid2vid/SparseImagePreview_00001_.png"
shutil.move(video_path, input_video_path)
if os.path.exists(preview_image_path):
os.remove(preview_image_path)
response = requests.get(PROMPT_ENDPOINT, timeout=5)
if response.status_code == 200:
print("Server is healthy")
else:
print("Server is unhealthy")
print(f"Status code: {response.status_code}")
print(f"Response: {response.text}")
raise HTTPException(status_code=500, detail="Server is unhealthy")
# make sure there are no jobs already
queue_json = response.json()
if queue_json["exec_info"]["queue_remaining"]:
print("There are jobs in the queue already. Exiting...")
raise HTTPException(status_code=500, detail="There are jobs in the queue already (this shouldn't happen)")
else:
print("Queue is empty")
p = {"prompt": json_prompt}
data = json.dumps(p).encode('utf-8')
response = requests.post(PROMPT_ENDPOINT, data=data)
if response.status_code == 200:
print("Job enqueued successfully")
else:
print("Job failed to queue")
print(f"Status code: {response.status_code}")
print(f"Response: {response.text}")
raise HTTPException(status_code=500, detail=f"Failed to queue job")
start_time = time.time()
while True:
response = requests.get(PROMPT_ENDPOINT, timeout=5)
queue_json = response.json()
if queue_json["exec_info"]["queue_remaining"]:
pass
else:
print("Job is done")
break
if time.time() - start_time > TIMEOUT_SECONDS:
print("Timeout reached and job didn't finish!")
raise HTTPException(status_code=500, detail="Timeout reached and job didn't finish!")
time.sleep(1)
return preview_image_path
if __name__ == "__main__":
import uvicorn
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
comfyui_process = subprocess.Popen(["venv/bin/python", "main.py"], cwd=COMFY_ROOT_DIRECTORY)
# block until comfyUI server is up
start_time = time.time()
started = False
while time.time() - start_time < SERVER_START_TIMEOUT:
try:
response = requests.get(PROMPT_ENDPOINT, timeout=5)
if response.status_code == 200:
print("Server is healthy")
started = True
break
except requests.exceptions.ConnectionError:
print(f"Server is not up yet. Time elapsed: {time.time() - start_time:.2f}")
time.sleep(1)
if not started:
print(f"Server failed to start in {SERVER_START_TIMEOUT} seconds")
exit(1)
print("ComfyUI server running, starting FastAPI server")
uvicorn.run(app, host="127.0.0.1", port=8000)
# cleanup
terminate_process(comfyui_process)
+132
View File
@@ -0,0 +1,132 @@
[
{
"url": "https://github.com/comfyanonymous/ComfyUI.git",
"commit": "eda87043862f743b0a0467735f8531f7c4709b3a",
"folder": "ComfyUI"
},
{
"url": "https://github.com/ltdrdata/ComfyUI-Manager.git",
"commit": "6c553d1228978352767f4914c4dd7787b00f6769",
"folder": "ComfyUI/custom_nodes/ComfyUI-Manager"
},
{
"url": "https://github.com/ltdrdata/ComfyUI-Impact-Pack.git",
"commit": "e374bd304a4a5b44d0deae2b2afaf4d5faad4810",
"folder": "ComfyUI/custom_nodes/ComfyUI-Impact-Pack"
},
{
"url": "https://github.com/Fannovel16/comfyui_controlnet_aux.git",
"commit": "33d6e86b65c40e5f97052262c6900f413684ccde",
"folder": "ComfyUI/custom_nodes/comfyui_controlnet_aux"
},
{
"url": "https://github.com/Fannovel16/ComfyUI-Frame-Interpolation.git",
"commit": "5e11679995c68f33891c306a393915feefe234b5",
"folder": "ComfyUI/custom_nodes/ComfyUI-Frame-Interpolation"
},
{
"url": "https://github.com/jags111/efficiency-nodes-comfyui.git",
"commit": "f6d01dc5449e2cc6e29da92b3b337e49c0dce112",
"folder": "ComfyUI/custom_nodes/efficiency-nodes-comfyui"
},
{
"url": "https://github.com/Derfuu/Derfuu_ComfyUI_ModdedNodes.git",
"commit": "2ace4c463d5b2063de35e46ebb9bd3f10e2d34b4",
"folder": "ComfyUI/custom_nodes/Derfuu_ComfyUI_ModdedNodes"
},
{
"url": "https://github.com/WASasquatch/was-node-suite-comfyui.git",
"commit": "6c3fed70655b737dc9b59da1cadb3c373c08d8ed",
"folder": "ComfyUI/custom_nodes/was-node-suite-comfyui"
},
{
"url": "https://github.com/pythongosssss/ComfyUI-Custom-Scripts.git",
"commit": "b4a9cebf24b50c4b538945ae86c17a9dc24052a8",
"folder": "ComfyUI/custom_nodes/ComfyUI-Custom-Scripts"
},
{
"url": "https://github.com/melMass/comfy_mtb.git",
"commit": "54ff6583ded0ed4054f8e5d7fadf0b2350259dce",
"folder": "ComfyUI/custom_nodes/comfy_mtb"
},
{
"url": "https://github.com/FizzleDorf/ComfyUI_FizzNodes.git",
"commit": "2ad19c1c3ad424b732fa0bc16ffb02284676a5da",
"folder": "ComfyUI/custom_nodes/ComfyUI_FizzNodes"
},
{
"url": "https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git",
"commit": "98768c7c3c45ac1e803071c5ad8e675e360e9e73",
"folder": "ComfyUI/custom_nodes/ComfyUI-Advanced-ControlNet"
},
{
"url": "https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git",
"commit": "9ccea911a63e2119778fa91b2692a8470a48e9da",
"folder": "ComfyUI/custom_nodes/ComfyUI-AnimateDiff-Evolved"
},
{
"url": "https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git",
"commit": "f94597739f20dac331f9918a245149b6b00a60f2",
"folder": "ComfyUI/custom_nodes/ComfyUI-VideoHelperSuite"
},
{
"url": "https://github.com/theUpsider/ComfyUI-Logic.git",
"commit": "fb8897351f715ea75eebf52e74515b6d07c693b8",
"folder": "ComfyUI/custom_nodes/ComfyUI-Logic"
},
{
"url": "https://github.com/rgthree/rgthree-comfy.git",
"commit": "9021670e9ff887d40e031334fc9f3e92c599d161",
"folder": "ComfyUI/custom_nodes/rgthree-comfy"
},
{
"url": "https://github.com/giriss/comfy-image-saver.git",
"commit": "65e6903eff274a50f8b5cd768f0f96baf37baea1",
"folder": "ComfyUI/custom_nodes/comfy-image-saver"
},
{
"url": "https://github.com/kijai/ComfyUI-KJNodes.git",
"commit": "df86fd77ac7f832b35ddaa748e4cf421ce9bf9e1",
"folder": "ComfyUI/custom_nodes/ComfyUI-KJNodes"
},
{
"url": "https://github.com/Ttl/ComfyUi_NNLatentUpscale.git",
"commit": "08105da31dbd7a54569661e135835e73bd8064b0",
"folder": "ComfyUI/custom_nodes/ComfyUi_NNLatentUpscale"
},
{
"url": "https://github.com/cubiq/ComfyUI_IPAdapter_plus.git",
"commit": "6a411dcb2c6c3b91a3aac97adfb080a77ade7d38",
"folder": "ComfyUI/custom_nodes/ComfyUI_IPAdapter_plus"
},
{
"url": "https://github.com/cubiq/ComfyUI_essentials.git",
"commit": "0283ce45272fc0737e3420c0aa2c5c30a74f7a36",
"folder": "ComfyUI/custom_nodes/ComfyUI_essentials"
},
{
"url": "https://github.com/storyicon/comfyui_segment_anything.git",
"commit": "681d977c2cc244de729fd9e08145ff365c609262",
"folder": "ComfyUI/custom_nodes/comfyui_segment_anything"
},
{
"url": "https://github.com/Jcd1230/rembg-comfyui-node.git",
"commit": "fac7df6c3f42e158a2829b511b37f13e4cc834eb",
"folder": "ComfyUI/custom_nodes/rembg-comfyui-node"
},
{
"url": "https://github.com/crystian/ComfyUI-Crystools.git",
"commit": "8c257748b98f59357ac20cebd4b4b67c0a9e53fe",
"folder": "ComfyUI/custom_nodes/ComfyUI-Crystools"
},
{
"url": "https://github.com/Fannovel16/ComfyUI-Video-Matting.git",
"commit": "178bf956ddb817d065b1b073ec04582ad60335bb",
"folder": "ComfyUI/custom_nodes/ComfyUI-Video-Matting"
},
{
"url": "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes.git",
"commit": "d78b780ae43fcf8c6b7c6505e6ffb4584281ceca",
"folder": "ComfyUI/custom_nodes/ComfyUI_Comfyroll_CustomNodes"
}
]
@@ -0,0 +1,14 @@
numexpr
numba
opencv-python
color_matcher
mediapipe
piexif
segment_anything
scikit-image
rembg[gpu]
timm
addict
yapf
deepdiff
pynvml
@@ -0,0 +1,4 @@
requests~=2.31.0
uvicorn~=0.29.0
fastapi~=0.110.0
python-multipart~=0.0.9