File size: 6,357 Bytes
4e4abcd d220d04 f00a40d d220d04 65de330 d220d04 4e4abcd fbbc034 4e4abcd c30ea17 f00a40d c30ea17 f00a40d c30ea17 f00a40d c30ea17 f00a40d c30ea17 1da4fca c30ea17 1da4fca c30ea17 d220d04 65de330 d220d04 1da4fca d220d04 1da4fca d220d04 65de330 1da4fca 4e4abcd a67e1df 1da4fca 65de330 1da4fca 65de330 1da4fca 4e4abcd c30ea17 1da4fca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | 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)) # फ़ैल हुआ तो एरर सेव करो |