|
|
import io |
|
|
import json |
|
|
import uuid |
|
|
import urllib.request |
|
|
import urllib.parse |
|
|
import websocket |
|
|
|
|
|
from fastapi import FastAPI, File, UploadFile, HTTPException |
|
|
from fastapi.responses import StreamingResponse |
|
|
|
|
|
|
|
|
|
|
|
COMFYUI_SERVER_ADDRESS = "127.0.0.1:8188" |
|
|
|
|
|
CLIENT_ID = str(uuid.uuid4()) |
|
|
|
|
|
|
|
|
app = FastAPI(title="Clarity AI Upscaler API") |
|
|
|
|
|
def get_image(filename, subfolder, folder_type): |
|
|
"""Lấy file ảnh từ máy chủ ComfyUI.""" |
|
|
data = {"filename": filename, "subfolder": subfolder, "type": folder_type} |
|
|
url_values = urllib.parse.urlencode(data) |
|
|
with urllib.request.urlopen(f"http://{COMFYUI_SERVER_ADDRESS}/view?{url_values}") as response: |
|
|
return response.read() |
|
|
|
|
|
def queue_prompt(prompt_workflow): |
|
|
"""Gửi yêu cầu thực thi quy trình đến ComfyUI.""" |
|
|
p = {"prompt": prompt_workflow, "client_id": CLIENT_ID} |
|
|
data = json.dumps(p).encode('utf-8') |
|
|
req = urllib.request.Request(f"http://{COMFYUI_SERVER_ADDRESS}/prompt", data=data) |
|
|
return json.loads(urllib.request.urlopen(req).read()) |
|
|
|
|
|
def upload_image(image_bytes: bytes, filename: str = "input_image.png"): |
|
|
"""Tải ảnh lên thư mục input của ComfyUI.""" |
|
|
import requests |
|
|
files = {"image": (filename, image_bytes, 'image/png'), "overwrite": (None, 'true')} |
|
|
response = requests.post(f"http://{COMFYUI_SERVER_ADDRESS}/upload/image", files=files) |
|
|
if response.status_code == 200: |
|
|
return response.json() |
|
|
else: |
|
|
raise HTTPException(status_code=500, detail=f"Failed to upload image: {response.text}") |
|
|
|
|
|
def get_history(prompt_id): |
|
|
"""Lấy lịch sử thực thi của một prompt.""" |
|
|
with urllib.request.urlopen(f"http://{COMFYUI_SERVER_ADDRESS}/history/{prompt_id}") as response: |
|
|
return json.loads(response.read()) |
|
|
|
|
|
def track_execution_and_get_output(prompt_id): |
|
|
"""Theo dõi tiến trình qua WebSocket và lấy ảnh kết quả.""" |
|
|
ws_url = f"ws://{COMFYUI_SERVER_ADDRESS}/ws?clientId={CLIENT_ID}" |
|
|
ws = websocket.WebSocket() |
|
|
ws.connect(ws_url) |
|
|
|
|
|
while True: |
|
|
out = ws.recv() |
|
|
if isinstance(out, str): |
|
|
message = json.loads(out) |
|
|
if message['type'] == 'executing': |
|
|
data = message['data'] |
|
|
if data['node'] is None and data['prompt_id'] == prompt_id: |
|
|
break |
|
|
else: |
|
|
continue |
|
|
ws.close() |
|
|
|
|
|
history = get_history(prompt_id)[prompt_id] |
|
|
for node_id, node_output in history['outputs'].items(): |
|
|
if 'images' in node_output: |
|
|
for image in node_output['images']: |
|
|
if image['type'] == 'output': |
|
|
image_data = get_image(image['filename'], image['subfolder'], image['type']) |
|
|
return image_data |
|
|
raise HTTPException(status_code=500, detail="Không tìm thấy ảnh kết quả.") |
|
|
|
|
|
@app.post("/upscale/", |
|
|
summary="Nâng cấp và tinh chỉnh hình ảnh", |
|
|
response_description="Hình ảnh đã được xử lý ở định dạng PNG") |
|
|
async def upscale_image(file: UploadFile = File(..., description="File ảnh cần xử lý.")): |
|
|
""" |
|
|
Nhận một file ảnh, xử lý nó thông qua quy trình ComfyUI, và trả về kết quả. |
|
|
""" |
|
|
try: |
|
|
|
|
|
with open("workflow_api.json", "r", encoding="utf-8") as f: |
|
|
prompt_workflow = json.load(f) |
|
|
|
|
|
|
|
|
image_bytes = await file.read() |
|
|
upload_response = upload_image(image_bytes) |
|
|
input_filename = upload_response['name'] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
prompt_workflow["17"]["inputs"]["image"] = input_filename |
|
|
|
|
|
|
|
|
queue_response = queue_prompt(prompt_workflow) |
|
|
prompt_id = queue_response['prompt_id'] |
|
|
|
|
|
|
|
|
result_image_bytes = track_execution_and_get_output(prompt_id) |
|
|
|
|
|
|
|
|
return StreamingResponse(io.BytesIO(result_image_bytes), media_type="image/png") |
|
|
|
|
|
except FileNotFoundError: |
|
|
raise HTTPException(status_code=500, detail="Không tìm thấy file workflow_api.json.") |
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=500, detail=f"Đã xảy ra lỗi: {str(e)}") |
|
|
|
|
|
|
|
|
|
|
|
|