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)) # फ़ैल हुआ तो एरर सेव करो