viven-b1 / comfy_engine.py
diwash-barla1's picture
Update comfy_engine.py
1da4fca verified
Raw
History Blame Contribute Delete
6.36 kB
import json, uuid, os, asyncio, time
import httpx
import websockets
from urllib.parse import urlencode
from datetime import datetime
# AMD GPU सर्वर का IP
COMFY_HOST = os.getenv("COMFY_HOST", "134.199.132.159")
with open("workflow.json", "r", encoding="utf-8") as f:
WORKFLOW_TEMPLATE = json.load(f)
RESOLUTIONS = {
"360p": {"16:9": (640, 360), "9:16": (360, 640), "1:1": (512, 512), "21:9": (640, 272), "3:4": (384, 512)},
"480p": {"16:9": (848, 480), "9:16": (480, 848), "1:1": (640, 640), "21:9": (848, 360), "3:4": (480, 640)},
"720p": {"16:9": (1280, 720), "9:16": (720, 1280), "1:1": (768, 768), "21:9": (1280, 544), "3:4": (768, 1024)}
}
# ==========================================
# 🗄️ SMART HISTORY MANAGER (Live Tracking)
# ==========================================
def load_history():
if os.path.exists("history.json"):
try:
with open("history.json", "r", encoding="utf-8") as f:
return json.load(f)
except: pass
return []
def save_history(data):
with open("history.json", "w", encoding="utf-8") as f:
json.dump(data[:50], f, indent=4) # 50 वीडियोस की लिमिट
def init_task(task_id, prompt):
data = load_history()
# नया टास्क 'processing' स्टेटस के साथ सबसे ऊपर जोड़ें
new_entry = {
"id": task_id,
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"prompt": prompt,
"status": "processing",
"progress": 0,
"url": None
}
data.insert(0, new_entry)
save_history(data)
def update_task_progress(task_id, progress):
data = load_history()
for item in data:
if item["id"] == task_id:
item["progress"] = progress
break
save_history(data)
def complete_task(task_id, video_url=None, error=None):
data = load_history()
for item in data:
if item["id"] == task_id:
if error:
item["status"] = "failed"
item["error"] = error
else:
item["status"] = "done"
item["progress"] = 100
item["url"] = video_url
break
save_history(data)
# ==========================================
# ⚙️ CORE ENGINE LOGIC
# ==========================================
def inject_params(req: dict) -> dict:
p = json.loads(json.dumps(WORKFLOW_TEMPLATE))
p["89"]["inputs"]["text"] = req.get("prompt", "")
ratio = req.get("aspect_ratio", "16:9")
quality = req.get("quality", "480p")
width, height = RESOLUTIONS.get(quality, {}).get(ratio, (848, 480))
p["74"]["inputs"]["width"] = width
p["74"]["inputs"]["height"] = height
p["74"]["inputs"]["length"] = req.get("frames", 81)
p["88"]["inputs"]["fps"] = req.get("fps", 16)
# ❌ यहाँ से मैंने steps और cfg वाली दोनों लाइनें डिलीट कर दी हैं!
# अब यह कोड सीधा workflow.json की मास्टर सेटिंग्स उठाएगा।
return p
def extract_video_url(history: dict, token: str) -> str:
outputs = history.get("outputs", {})
for _, node_out in outputs.items():
for key in ("videos", "images", "files"):
if key in node_out and node_out[key]:
it = node_out[key][0]
q = urlencode(it)
return f"/api/video?{q}&token={token}"
raise RuntimeError("Video not found")
async def queue_prompt(req: dict):
token = str(uuid.uuid4())
client_id = str(uuid.uuid4())
prompt_data = inject_params(req)
async with httpx.AsyncClient() as client:
resp = await client.post(f"http://{COMFY_HOST}/prompt?token={token}",
json={"prompt": prompt_data, "client_id": client_id},
timeout=30.0)
prompt_id = resp.json().get("prompt_id")
if not prompt_id: raise Exception("Failed to queue on AMD Server")
return prompt_id, client_id, token, len(prompt_data)
# 🚀 THE BACKGROUND WATCHER (यह फोन बंद होने पर भी चलता रहेगा)
async def background_watcher(task_id, client_id, token, total_nodes):
seen = set()
start_t = time.time()
progress_fake = 0
ws_url = f"ws://{COMFY_HOST}/ws?clientId={client_id}&token={token}"
try:
async with websockets.connect(ws_url, ping_interval=20) as ws:
while True:
msg_raw = await ws.recv()
if isinstance(msg_raw, (bytes, bytearray)):
if progress_fake < 95 and (time.time() - start_t) > 2:
progress_fake = min(95, progress_fake + 1)
update_task_progress(task_id, progress_fake) # लाइव प्रोग्रेस सेव
continue
msg = json.loads(msg_raw)
if msg.get("type") == "executing":
node = msg.get("data", {}).get("node")
if node is None: break # रेंडरिंग ख़तम
if node not in seen:
seen.add(node)
p_real = int((len(seen) / total_nodes) * 100)
progress_fake = max(progress_fake, p_real)
update_task_progress(task_id, progress_fake) # लाइव प्रोग्रेस सेव
except Exception:
pass # अगर कनेक्शन टूटा तो भी कोई बात नहीं, हम हिस्ट्री चेक कर लेंगे!
# 🎬 फाइनल चेक और सेविंग
await asyncio.sleep(2)
try:
async with httpx.AsyncClient() as client:
h_resp = await client.get(f"http://{COMFY_HOST}/history/{task_id}?token={token}", timeout=30.0)
history = h_resp.json().get(task_id, {})
v_url = extract_video_url(history, token)
complete_task(task_id, video_url=v_url) # सक्सेस!
except Exception as e:
complete_task(task_id, error=str(e)) # फ़ैल हुआ तो एरर सेव करो