add support for cogvide

This commit is contained in:
Kasisnu
2024-11-14 17:19:55 +05:30
parent 7e12c7c3a5
commit e95ea00436
@@ -4,13 +4,12 @@ import os
import json import json
import time import time
from typing import Dict, Any, Optional from typing import Dict, Any, Optional
from jsonpath_ng import jsonpath, parse from jsonpath_ng import parse
import shutil import shutil
from pathlib import Path from pathlib import Path
from enum import IntEnum, auto from enum import IntEnum, auto
import os import os
import subprocess import subprocess
import concurrent.futures
import signal import signal
import websockets import websockets
import httpx import httpx
@@ -18,7 +17,6 @@ import asyncio
import urllib import urllib
import uuid import uuid
import re import re
import imageio.v3 as iio
client_id = str(uuid.uuid4()) client_id = str(uuid.uuid4())
@@ -37,6 +35,7 @@ MAIN_IPA_WORKFLOW = os.environ.get("MAIN_IPA_WORKFLOW", "06-08-2024/yae_vid2vid_
FACE_DETAILER_WORKFLOW = os.environ.get("FACE_DETAILER_WORKFLOW", "3-06-2024/yae_vid2vid_FaceDetailer_1-07_API.json") FACE_DETAILER_WORKFLOW = os.environ.get("FACE_DETAILER_WORKFLOW", "3-06-2024/yae_vid2vid_FaceDetailer_1-07_API.json")
UPSCALER_WORKFLOW = os.environ.get("UPSCALER_WORKFLOW", "06-08-2024/yae_vid2vid_Upscale_25-07_API.json") UPSCALER_WORKFLOW = os.environ.get("UPSCALER_WORKFLOW", "06-08-2024/yae_vid2vid_Upscale_25-07_API.json")
CINEMATIC_WORKFLOW = os.environ.get("CINEMATIC_WORKFLOW", "3-06-2024/yae_vid2vid_better_main+upscaler_04-07_API.json") CINEMATIC_WORKFLOW = os.environ.get("CINEMATIC_WORKFLOW", "3-06-2024/yae_vid2vid_better_main+upscaler_04-07_API.json")
COG_V1_WORKFLOW = os.environ.get("COG_V1_WORKFLOW", "14-11-2024/yae_15-10_COG_API.json")
class PipelineType(IntEnum): class PipelineType(IntEnum):
BASE = auto() BASE = auto()
@@ -45,6 +44,7 @@ class PipelineType(IntEnum):
UPSCALER = auto() UPSCALER = auto()
CINEMATIC = auto() CINEMATIC = auto()
PREVIEW = auto() PREVIEW = auto()
COG_V1 = auto()
style_to_filename = { style_to_filename = {
@@ -114,9 +114,6 @@ def generated_frames_count(frames_dir):
async def extract_frames(input_video, output_directory): async def extract_frames(input_video, output_directory):
if not output_directory.exists(): if not output_directory.exists():
output_directory.mkdir(parents=True) output_directory.mkdir(parents=True)
# for idx, frame in enumerate(iio.imiter(input_video)):
# frame_idx = idx + 1
# iio.imwrite(f"{output_directory}/Frame_{frame_idx:05d}.jpg", frame)
command = [ command = [
'ffmpeg', 'ffmpeg',
'-i', str(input_video), '-i', str(input_video),
@@ -168,7 +165,6 @@ def ensure_output_directory_empty():
(Path(COMFY_ROOT_DIRECTORY) / "output").mkdir(parents=True) (Path(COMFY_ROOT_DIRECTORY) / "output").mkdir(parents=True)
def parse_args(): def parse_args():
parser = argparse.ArgumentParser(description='Run Comfy') parser = argparse.ArgumentParser(description='Run Comfy')
parser.add_argument('--prompt', type=str, help='location of the prompt json', required=False) parser.add_argument('--prompt', type=str, help='location of the prompt json', required=False)
parser.add_argument('--style', type=str, help='style name', required=False) parser.add_argument('--style', type=str, help='style name', required=False)
@@ -191,6 +187,8 @@ def parse_args():
parser.add_argument('--generate-previews', help='generate previews', required=False, default=False, action=argparse.BooleanOptionalAction) parser.add_argument('--generate-previews', help='generate previews', required=False, default=False, action=argparse.BooleanOptionalAction)
parser.add_argument('--preview-frames-directory', type=str, help='previews directory', required=False) parser.add_argument('--preview-frames-directory', type=str, help='previews directory', required=False)
parser.add_argument('--enable-cinematic', help='enable cinematic', required=False, default=False, action=argparse.BooleanOptionalAction) parser.add_argument('--enable-cinematic', help='enable cinematic', required=False, default=False, action=argparse.BooleanOptionalAction)
parser.add_argument('--enable-cogvideo', help='enable cog video', required=False, default=False, action=argparse.BooleanOptionalAction)
parser.add_argument('--skip-comfy-startup', action='store_true', help='controls if this script tries to start comfy', default=False) parser.add_argument('--skip-comfy-startup', action='store_true', help='controls if this script tries to start comfy', default=False)
parser.add_argument('--server-restart-trigger-file', type=str, help='server restart trigger file', required=False) parser.add_argument('--server-restart-trigger-file', type=str, help='server restart trigger file', required=False)
return parser.parse_args() return parser.parse_args()
@@ -258,7 +256,6 @@ def invoke_facefusion(input_audio, input_video, output_video):
subprocess.check_output(command) subprocess.check_output(command)
print("Facefusion completed successfully.") print("Facefusion completed successfully.")
async def main(): async def main():
if not args.skip_comfy_startup: if not args.skip_comfy_startup:
print("Starting comfy server") print("Starting comfy server")
@@ -280,11 +277,49 @@ async def main():
# interrupt_comfy_queue(SERVER_IP) # interrupt_comfy_queue(SERVER_IP)
wait_for_comfy_startup(SERVER_IP) wait_for_comfy_startup(SERVER_IP)
# print our process id, parent group id, comfyui process id, comfyui process group id, comfyui process group leader id, comfyui process group leader parent id
# print(f"Process ID: {os.getpid()}")
# print(f"Parent Group ID: {os.getpgrp()}")
# print(f"ComfyUI Process ID: {comfyui_process.pid}")
# print(f"ComfyUI Process Group ID: {os.getpgid(comfyui_process.pid)}")
# print(f"ComfyUI Process Group Leader ID: {os.getpgid(comfyui_process.pid)}")
# print(f"ComfyUI Process Group Leader Parent ID: {os.getppid()}")
pipeline_type = PipelineType.IPA pipeline_type = PipelineType.IPA
output_index = 0 output_index = 0
file_path = args.prompt file_path = args.prompt
prompt = None prompt = None
if args.enable_cogvideo:
print("Generating prompt json for COG V1")
workflow_filename = COG_V1_WORKFLOW
positive_prompt_filename = args.positive_prompt_filename
step_count = 25
strength = 1.4
if args.strength != 1.0:
# Could we even make better spaghetti?
strength = args.strength
positive_prompt = ''
if positive_prompt_filename:
positive_prompt = open(positive_prompt_filename).read()
ensure_output_directory_empty()
prompt = generate_prompt_for_cog_v1(
workflow_filename,
positive_prompt,
step_count,
strength
)
print("running pipeline" + str(pipeline_type))
await enqueue_prompt_and_wait(prompt)
left = Path(COMFY_ROOT_DIRECTORY) / "output" / f"vid2vid/CogVideoX-I2V_00001.mp4"
if left.exists():
print("Pipeline completed successfully to output file: " + str(left))
else:
print("Pipeline failed to produce output")
exit(1)
restore_last_pipeline_output(left)
return
if args.style is not None: if args.style is not None:
print("Generating prompt json") print("Generating prompt json")
style = args.style style = args.style
@@ -547,8 +582,6 @@ async def enqueue_prompt_and_wait(prompt):
# Wait for the job to finish # Wait for the job to finish
print(f"Waiting for job to finish (timeout: {TIMEOUT_SECONDS} seconds)") print(f"Waiting for job to finish (timeout: {TIMEOUT_SECONDS} seconds)")
execution_start_time = time.perf_counter() execution_start_time = time.perf_counter()
# import ipdb; ipdb.set_trace()
# max_size = 1048576 * 10 allows us to receive a really large payload from comfy
async with websockets.connect("ws://{}/ws?clientId={}".format(SERVER_IP, client_id), max_size=1048576 * 10) as ws: async with websockets.connect("ws://{}/ws?clientId={}".format(SERVER_IP, client_id), max_size=1048576 * 10) as ws:
await smart_wait(ws, prompt_id) await smart_wait(ws, prompt_id)
current_time = time.perf_counter() current_time = time.perf_counter()
@@ -557,6 +590,21 @@ async def enqueue_prompt_and_wait(prompt):
def generate_prompt_for_cog_v1(workflow_filename, positive_prompt, step_count, strength=1.4):
workflow_directory = Path(V2V_WORKFLOWS_DIRECTORY) / "workflows"
workflow_json = json.load(open(workflow_directory / workflow_filename))
modifications = {
"$.320.inputs.text": positive_prompt,
"$.464.inputs.value": step_count,
"$.465.inputs.value": strength,
}
json_prompt = apply_jsonpath_mods(modifications, workflow_json)
p = {"prompt": json_prompt, "client_id": client_id}
return p
def generate_prompt_for_style(style_name, def generate_prompt_for_style(style_name,
positive_prompt, positive_prompt,
negative_prompt, negative_prompt,