mirror of
https://github.com/storytold/storyteller-ml.git
synced 2026-10-09 00:09:55 +00:00
Merge pull request #50 from storytold/feature/comfyui-sidecar
comfyUI previews
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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())
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user