Dmitry1313 commited on
Commit
e482ece
·
verified ·
1 Parent(s): 9aead7d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +145 -0
app.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+ import tempfile
4
+ import uuid
5
+ import json
6
+ import time
7
+ import requests
8
+ from fastapi import FastAPI, File, UploadFile, HTTPException
9
+ from fastapi.responses import Response, JSONResponse
10
+ import uvicorn
11
+ import logging
12
+
13
+ logging.basicConfig(level=logging.INFO)
14
+ logger = logging.getLogger(__name__)
15
+
16
+ app = FastAPI()
17
+
18
+ # Запускаем ComfyUI в фоновом режиме
19
+ comfy_process = None
20
+
21
+ @app.on_event("startup")
22
+ async def startup_event():
23
+ global comfy_process
24
+ logger.info("Starting ComfyUI...")
25
+ comfy_process = subprocess.Popen(
26
+ ["python", "/comfyui/main.py", "--listen", "0.0.0.0", "--port", "8188"],
27
+ stdout=subprocess.PIPE,
28
+ stderr=subprocess.PIPE
29
+ )
30
+ # Даём время на запуск
31
+ time.sleep(10)
32
+ logger.info("ComfyUI started")
33
+
34
+ @app.on_event("shutdown")
35
+ async def shutdown_event():
36
+ if comfy_process:
37
+ comfy_process.terminate()
38
+
39
+ def load_workflow():
40
+ """Загружает workflow из файла или создаёт базовый"""
41
+ # Здесь можно загрузить ваш workflow.json
42
+ # Пока используем простой workflow
43
+ return {
44
+ "3": {
45
+ "class_type": "LoadImage",
46
+ "inputs": {
47
+ "image": "source.jpg"
48
+ }
49
+ },
50
+ "4": {
51
+ "class_type": "LoadImage",
52
+ "inputs": {
53
+ "image": "target.jpg"
54
+ }
55
+ },
56
+ "5": {
57
+ "class_type": "ReActorFaceSwap",
58
+ "inputs": {
59
+ "source_image": ["3", 0],
60
+ "target_image": ["4", 0],
61
+ "face_restorer": "gfpgan",
62
+ "face_restorer_weight": 0.8,
63
+ "swap_model": "inswapper_128.onnx",
64
+ "detect_model": "yolov8n-face.pt",
65
+ "save_original": False,
66
+ "output_image": ["6", 0]
67
+ }
68
+ },
69
+ "6": {
70
+ "class_type": "SaveImage",
71
+ "inputs": {
72
+ "filename_prefix": "output",
73
+ "images": ["5", 0]
74
+ }
75
+ }
76
+ }
77
+
78
+ @app.post("/swap")
79
+ async def swap_face(
80
+ source: UploadFile = File(...),
81
+ target: UploadFile = File(...)
82
+ ):
83
+ temp_dir = tempfile.mkdtemp()
84
+ try:
85
+ # Сохраняем входные файлы
86
+ source_path = os.path.join(temp_dir, "source.jpg")
87
+ target_path = os.path.join(temp_dir, "target.jpg")
88
+
89
+ with open(source_path, "wb") as f:
90
+ f.write(await source.read())
91
+ with open(target_path, "wb") as f:
92
+ f.write(await target.read())
93
+
94
+ # Копируем файлы в папку ComfyUI
95
+ comfy_input_dir = "/comfyui/input"
96
+ os.makedirs(comfy_input_dir, exist_ok=True)
97
+
98
+ shutil.copy(source_path, os.path.join(comfy_input_dir, "source.jpg"))
99
+ shutil.copy(target_path, os.path.join(comfy_input_dir, "target.jpg"))
100
+
101
+ # Загружаем workflow
102
+ workflow = load_workflow()
103
+
104
+ # Отправляем задачу в ComfyUI
105
+ response = requests.post(
106
+ "http://127.0.0.1:8188/prompt",
107
+ json={"prompt": workflow}
108
+ )
109
+
110
+ if response.status_code != 200:
111
+ raise HTTPException(500, f"ComfyUI error: {response.text}")
112
+
113
+ prompt_id = response.json()["prompt_id"]
114
+
115
+ # Ждём завершения
116
+ while True:
117
+ status = requests.get(f"http://127.0.0.1:8188/history/{prompt_id}")
118
+ if status.status_code == 200 and status.json():
119
+ history = status.json()
120
+ if prompt_id in history:
121
+ output_images = history[prompt_id]["outputs"]
122
+ # Находим выходное изображение
123
+ for node_id, node_output in output_images.items():
124
+ if "images" in node_output:
125
+ image_info = node_output["images"][0]
126
+ image_path = os.path.join("/comfyui/output", image_info["filename"])
127
+ if os.path.exists(image_path):
128
+ with open(image_path, "rb") as f:
129
+ image_data = f.read()
130
+ return Response(content=image_data, media_type="image/jpeg")
131
+ time.sleep(1)
132
+
133
+ except Exception as e:
134
+ logger.exception("Error")
135
+ raise HTTPException(500, str(e))
136
+ finally:
137
+ import shutil
138
+ shutil.rmtree(temp_dir, ignore_errors=True)
139
+
140
+ @app.get("/health")
141
+ async def health():
142
+ return {"status": "ok"}
143
+
144
+ if __name__ == "__main__":
145
+ uvicorn.run(app, host="0.0.0.0", port=7860)