Opera8 commited on
Commit
d4fef3d
·
verified ·
1 Parent(s): 2e46f6e

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +84 -77
main.py CHANGED
@@ -2274,7 +2274,6 @@ def local_merge_videos(base_video_bytes, new_clip_bytes):
2274
 
2275
  async def helper_generate_image_for_video(prompt, action_name, width, height):
2276
  headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
2277
- # تلاش برای ساخت تصویر تا ۳ بار در صورت برخورد با محدودیت
2278
  for attempt in range(3):
2279
  try:
2280
  payload = {"prompt": prompt, "width": width, "height": height, "action_name": action_name}
@@ -2285,7 +2284,7 @@ async def helper_generate_image_for_video(prompt, action_name, width, height):
2285
  run_id = data.get("run_id")
2286
  if run_id:
2287
  waited = 0
2288
- while waited < 100: # انتظار حداکثر ۱۰۰ ثانیه برای تصویر
2289
  await asyncio.sleep(5)
2290
  waited += 5
2291
  try:
@@ -2301,58 +2300,6 @@ async def helper_generate_image_for_video(prompt, action_name, width, height):
2301
  await asyncio.sleep(5)
2302
  return None
2303
 
2304
- async def helper_optimize_video_prompt(image_bytes, user_prompt):
2305
- if not GEMINI_KEYS:
2306
- return None
2307
-
2308
- master_prompt = """You are an expert AI Animation Planner. Your absolute highest priority is to faithfully and creatively execute the user's specific request based on the provided image.
2309
-
2310
- 1. If the user prompt is empty or generic (like "animate this"), add subtle, high-quality, believable cinematic motion (e.g., slow zoom, water flowing, wind in hair).
2311
- 2. If the user gives specific directions, focus ENTIRELY on executing that command perfectly. If the action is not visible in-frame, use cinematic camera movements to reveal it.
2312
- 3. You must output ONLY a highly detailed, descriptive animation prompt in ENGLISH. Do not translate literally; ENHANCE the prompt for a text-to-video AI model.
2313
- 4. MUST Include keywords at the end: cinematic, photorealistic, high detail, smooth motion, 8k.
2314
-
2315
- CRITICAL RULE: DO NOT say "Here is the prompt" or give any conversational explanations. DO NOT output JSON. Output ONLY the raw English animation prompt text and NOTHING ELSE."""
2316
-
2317
- prompt_for_ai = user_prompt if user_prompt else "لطفاً این تصویر را به یک ویدیوی سینمایی بسیار جذاب و واقع‌گرایانه متحرک کن."
2318
- combined_prompt = f"{master_prompt}\n\nUser request: {prompt_for_ai}"
2319
-
2320
- base64_data = base64.b64encode(image_bytes).decode('utf-8')
2321
- mime_type = "image/jpeg"
2322
-
2323
- for attempt in range(2):
2324
- keys_to_try = get_next_gemini_keys(50)
2325
- async with aiohttp.ClientSession() as session:
2326
- for key in keys_to_try:
2327
- url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
2328
- payload = {
2329
- "contents": [{
2330
- "parts": [
2331
- {"text": combined_prompt},
2332
- {"inlineData": {"mimeType": mime_type, "data": base64_data}}
2333
- ]
2334
- }],
2335
- "generationConfig": {"temperature": 0.7, "maxOutputTokens": 1024}
2336
- }
2337
- try:
2338
- async with session.post(url, json=payload, timeout=20) as response:
2339
- if response.status == 200:
2340
- data = await response.json()
2341
- try:
2342
- enhanced_prompt = data["candidates"][0]["content"]["parts"][0]["text"]
2343
- enhanced_prompt = enhanced_prompt.replace("```text", "").replace("```", "").replace("```json", "").strip()
2344
-
2345
- if "پردازش متوقف شد" in enhanced_prompt or "سهمیه سرور موقتاً پر شده" in enhanced_prompt:
2346
- continue
2347
-
2348
- return enhanced_prompt
2349
- except (KeyError, IndexError):
2350
- continue
2351
- except Exception:
2352
- continue
2353
- await asyncio.sleep(2)
2354
- return None
2355
-
2356
  async def process_video_generation(client, chat_id, video_type, prompt, duration_int, image_bytes, txt_model_action=None, width=1024, height=1024):
2357
  str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
2358
  creds = get_user_credits(str_chat_id)
@@ -2374,12 +2321,63 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
2374
 
2375
  current_image_bytes = await asyncio.to_thread(force_jpeg, current_image_bytes)
2376
 
2377
- # پرامپت هوشمند
2378
- proc_msg = await update_status_msg(client, chat_id, proc_msg, "🧠 در حال درک تصویر و بهینه‌سازی دستور رامپت) شما توسط هوش مصنوعی...")
2379
- eng_prompt = await helper_optimize_video_prompt(current_image_bytes, prompt)
2380
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2381
  if eng_prompt:
2382
- proc_msg = await update_status_msg(client, chat_id, proc_msg, f"✅ دستور شما بهینه شد:\n\n`{eng_prompt}`\n\n🎬 در حال ارسال برای ساخت ویدیو نهایی...")
 
2383
  await asyncio.sleep(3)
2384
  else:
2385
  try:
@@ -2388,18 +2386,27 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
2388
  except:
2389
  eng_prompt = "cinematic motion, photorealistic, high detail, smooth animation, 8k"
2390
 
2391
- op_name = "متحرک‌سازی تصاویر" if video_type == "animate" else "ساخت ویدیو"
2392
- proc_msg = await update_status_msg(client, chat_id, proc_msg, f"🎬 عملیات {op_name} آغاز شد.\n⏱ زمان نهایی: {duration_int} ثانیه")
2393
-
2394
  for loop_idx in range(loops_needed):
2395
  new_clip_bytes = None
2396
- step_text_base = f"🎬 بخش {loop_idx + 1} از {loops_needed}"
2397
 
2398
- # تلاش مجدد تا ۳ بار برای هر رندر ۵ ثانیه‌ای
2399
  for attempt in range(3):
2400
  run_id = str(uuid.uuid4())
2401
- step_text = f"{step_text_base} (تلاش {attempt + 1}/3):\n"
2402
- proc_msg = await update_status_msg(client, chat_id, proc_msg, step_text + "۱. 📤 ارسال دستور مستقیم به اکشن‌های پردازشی...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2403
 
2404
  input_filename = f"{run_id}_input.jpg"
2405
  with open(f"static/images/{input_filename}", "wb") as f:
@@ -2407,8 +2414,6 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
2407
 
2408
  image_public_url = f"{RUBIKA_SPACE_URL}/static/images/{input_filename}"
2409
 
2410
- dispatch_url = f"https://api.github.com/repos/{GITHUB_USER}/{GITHUB_REPO}/dispatches"
2411
- dispatch_headers = {"Accept": "application/vnd.github.v3+json", "Authorization": f"token {GITHUB_TOKEN}"}
2412
  dispatch_payload = {
2413
  "event_type": "generate-video",
2414
  "client_payload": {
@@ -2423,15 +2428,18 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
2423
  try:
2424
  resp = await asyncio.to_thread(requests.post, dispatch_url, headers=dispatch_headers, json=dispatch_payload, timeout=20)
2425
  if resp.status_code != 204:
2426
- proc_msg = await update_status_msg(client, chat_id, proc_msg, f"❌ خطای گیت‌هاب در پذیرش دستور: {resp.text}")
2427
  await asyncio.sleep(4)
2428
  continue
2429
- except Exception as e:
2430
- proc_msg = await update_status_msg(client, chat_id, proc_msg, f"❌ خطای اتصال به اکشن: {str(e)[:50]}")
2431
  await asyncio.sleep(4)
2432
  continue
2433
 
2434
- proc_msg = await update_status_msg(client, chat_id, proc_msg, step_text + "۲. ⏳ سرور در حال رندر می‌باشد.\n(در صورت شلوغی سرور و خطای سهمیه، ربات تا ۳ بار اکشن جدید ایجاد می‌کند. منتظر دریافت فایل...)")
 
 
 
 
 
2435
 
2436
  waited = 0
2437
  while waited < 180: # انتظار تا 180 ثانیه (3 دقیقه)
@@ -2455,33 +2463,32 @@ async def process_video_generation(client, chat_id, video_type, prompt, duration
2455
  if new_clip_bytes:
2456
  break
2457
  else:
2458
- proc_msg = await update_status_msg(client, chat_id, proc_msg, step_text + "⚠️ محدودیت زمانی در رندر یا خطای ترافیک. ایجاد درخواست و اکشن جدید...")
2459
  await asyncio.sleep(5)
2460
 
2461
  if not new_clip_bytes:
2462
- return await update_status_msg(client, chat_id, proc_msg, "❌ پس از ۳ بار تلاش، زمان رندر بیش از حد مجاز طول کشید یا درخواست محدود شد. عملیات متوقف شد.")
2463
 
2464
  if base_video_bytes is not None:
2465
- proc_msg = await update_status_msg(client, chat_id, proc_msg, step_text_base + "\n۳. 🔄 در حال متصل کردن بخش جدید به ویدیوهای قبلی یکس لوکال)...")
2466
  base_video_bytes = await asyncio.to_thread(local_merge_videos, base_video_bytes, new_clip_bytes)
2467
  else:
2468
  base_video_bytes = new_clip_bytes
2469
 
2470
  if loop_idx < loops_needed - 1:
2471
  current_secs = (loop_idx + 1) * 5
2472
- proc_msg = await update_status_msg(client, chat_id, proc_msg, step_text_base + f"\n۴. 📸 فعلاً {current_secs} ثانیه ساخته شد. در حال استخراج فریم آخر جهت ساخت ادامه...")
2473
  current_image_bytes = await asyncio.to_thread(helper_extract_last_frame, base_video_bytes)
2474
  if not current_image_bytes:
2475
  await update_status_msg(client, chat_id, proc_msg, "⚠️ استخراج فریم با مشکل مواجه شد. عملیات در همین نقطه پایان یافت.")
2476
  break
2477
 
2478
- proc_msg = await update_status_msg(client, chat_id, proc_msg, "🚀 ویدیو کاملاً آماده شد! در حال آپلود سریع...")
2479
 
2480
  try:
2481
  file_name = f"video_{uuid.uuid4().hex}.mp4"
2482
  await asyncio.to_thread(sync_write_file, file_name, base_video_bytes)
2483
 
2484
- caption_text = f"🎞 ویدیو شما با موفقیت آماده شد!\n⏱ زمان: {duration_int} ثانیه\n✨ پرامپت: {prompt}"
2485
  upload_result = False
2486
 
2487
  for up_att in range(3):
 
2274
 
2275
  async def helper_generate_image_for_video(prompt, action_name, width, height):
2276
  headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
 
2277
  for attempt in range(3):
2278
  try:
2279
  payload = {"prompt": prompt, "width": width, "height": height, "action_name": action_name}
 
2284
  run_id = data.get("run_id")
2285
  if run_id:
2286
  waited = 0
2287
+ while waited < 100:
2288
  await asyncio.sleep(5)
2289
  waited += 5
2290
  try:
 
2300
  await asyncio.sleep(5)
2301
  return None
2302
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2303
  async def process_video_generation(client, chat_id, video_type, prompt, duration_int, image_bytes, txt_model_action=None, width=1024, height=1024):
2304
  str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
2305
  creds = get_user_credits(str_chat_id)
 
2321
 
2322
  current_image_bytes = await asyncio.to_thread(force_jpeg, current_image_bytes)
2323
 
2324
+ # 🧠 استفاده از Gemma 4 از طریق گیت‌هاب برای بهینه‌سازی پرامپت
2325
+ proc_msg = await update_status_msg(client, chat_id, proc_msg, "🧠 در حال درک تصویر و نگارش بهترین سناریو برای ویدیو توسط هوش مصنوعی...")
 
2326
 
2327
+ master_prompt = """You are an expert AI Animation Planner. Your absolute highest priority is to faithfully and creatively execute the user's specific request based on the provided image.
2328
+
2329
+ 1. If the user prompt is empty or generic (like "animate this"), add subtle, high-quality, believable cinematic motion (e.g., slow zoom, water flowing, wind in hair).
2330
+ 2. If the user gives specific directions, focus ENTIRELY on executing that command perfectly. If the action is not visible in-frame, use cinematic camera movements to reveal it.
2331
+ 3. You must output ONLY a highly detailed, descriptive animation prompt in ENGLISH. Do not translate literally; ENHANCE the prompt for a text-to-video AI model.
2332
+ 4. MUST Include keywords at the end: cinematic, photorealistic, high detail, smooth motion, 8k.
2333
+
2334
+ CRITICAL RULE: DO NOT say "Here is the prompt" or give any conversational explanations. DO NOT output JSON. Output ONLY the raw English animation prompt text and NOTHING ELSE."""
2335
+
2336
+ prompt_for_ai = prompt if prompt else "لطفاً این تصویر را به یک ویدیوی سینمایی بسیار جذاب و واقع‌گرایانه متحرک کن."
2337
+ combined_prompt = f"{master_prompt}\n\nUser request: {prompt_for_ai}"
2338
+
2339
+ gemma_run_id = f"gemma_{uuid.uuid4().hex[:8]}"
2340
+ gemma_filename = f"{gemma_run_id}.jpg"
2341
+ with open(f"static/images/{gemma_filename}", "wb") as f:
2342
+ f.write(current_image_bytes)
2343
+ gemma_image_url = f"{RUBIKA_SPACE_URL}/static/images/{gemma_filename}"
2344
+
2345
+ dispatch_url = f"https://api.github.com/repos/{GITHUB_USER}/{GITHUB_REPO}/dispatches"
2346
+ dispatch_headers = {"Accept": "application/vnd.github.v3+json", "Authorization": f"token {GITHUB_TOKEN}"}
2347
+ gemma_payload = {
2348
+ "event_type": "chat-gemma",
2349
+ "client_payload": {
2350
+ "prompt": combined_prompt,
2351
+ "file_url": gemma_image_url,
2352
+ "file_mime": "image/jpeg",
2353
+ "run_id": gemma_run_id,
2354
+ "space_url": RUBIKA_SPACE_URL
2355
+ }
2356
+ }
2357
+
2358
+ eng_prompt = None
2359
+ try:
2360
+ resp = await asyncio.to_thread(requests.post, dispatch_url, headers=dispatch_headers, json=gemma_payload, timeout=20)
2361
+ if resp.status_code == 204:
2362
+ waited = 0
2363
+ while waited < 90:
2364
+ txt_path = f"static/images/{gemma_run_id}.txt"
2365
+ if os.path.exists(txt_path):
2366
+ with open(txt_path, "r", encoding="utf-8") as f:
2367
+ eng_prompt = f.read().strip()
2368
+ os.remove(txt_path)
2369
+ break
2370
+ await asyncio.sleep(3)
2371
+ waited += 3
2372
+ except Exception as e:
2373
+ print("Gemma action error:", e)
2374
+
2375
+ try: os.remove(f"static/images/{gemma_filename}")
2376
+ except: pass
2377
+
2378
  if eng_prompt:
2379
+ eng_prompt = eng_prompt.replace("```text", "").replace("```", "").replace("```json", "").strip()
2380
+ proc_msg = await update_status_msg(client, chat_id, proc_msg, f"✅ سناریوی ویدیوی شما بهینه‌سازی شد:\n\n`{eng_prompt}`")
2381
  await asyncio.sleep(3)
2382
  else:
2383
  try:
 
2386
  except:
2387
  eng_prompt = "cinematic motion, photorealistic, high detail, smooth animation, 8k"
2388
 
 
 
 
2389
  for loop_idx in range(loops_needed):
2390
  new_clip_bytes = None
 
2391
 
 
2392
  for attempt in range(3):
2393
  run_id = str(uuid.uuid4())
2394
+
2395
+ # مدیریت هوشمند پیام‌های نمایشی بدون اصطلاحات فنی
2396
+ if loops_needed == 1:
2397
+ if attempt == 0:
2398
+ msg_txt = "🎬 در حال ارسال درخواست به سرورهای قدرتمند رندر ویدیو..."
2399
+ else:
2400
+ msg_txt = "⚠️ به دلیل شلوغی سرور، در حال تلاش مجدد با یک مسیر آزادتر..."
2401
+ else:
2402
+ start_sec = loop_idx * 5
2403
+ end_sec = (loop_idx + 1) * 5
2404
+ if attempt == 0:
2405
+ msg_txt = f"🎬 در حال رندر ثانیه‌های {start_sec} تا {end_sec} از ویدیو..."
2406
+ else:
2407
+ msg_txt = f"⚠️ تلاش مجدد برای رندر ثانیه‌های {start_sec} تا {end_sec}..."
2408
+
2409
+ proc_msg = await update_status_msg(client, chat_id, proc_msg, msg_txt)
2410
 
2411
  input_filename = f"{run_id}_input.jpg"
2412
  with open(f"static/images/{input_filename}", "wb") as f:
 
2414
 
2415
  image_public_url = f"{RUBIKA_SPACE_URL}/static/images/{input_filename}"
2416
 
 
 
2417
  dispatch_payload = {
2418
  "event_type": "generate-video",
2419
  "client_payload": {
 
2428
  try:
2429
  resp = await asyncio.to_thread(requests.post, dispatch_url, headers=dispatch_headers, json=dispatch_payload, timeout=20)
2430
  if resp.status_code != 204:
 
2431
  await asyncio.sleep(4)
2432
  continue
2433
+ except Exception:
 
2434
  await asyncio.sleep(4)
2435
  continue
2436
 
2437
+ if loops_needed == 1:
2438
+ wait_msg = "⏳ هوش مصنوعی در حال ساخت ویدیوی شماست.\n(این فرآیند معمولاً بین ۲ تا ۴ دقیقه زمان می‌برد. لطفاً صبور باشید...)"
2439
+ else:
2440
+ wait_msg = "⏳ هوش مصنوعی در حال پردازش و رندر این بخش می‌باشد...\n(ممکن است چند دقیقه زمان ببرد)"
2441
+
2442
+ proc_msg = await update_status_msg(client, chat_id, proc_msg, wait_msg)
2443
 
2444
  waited = 0
2445
  while waited < 180: # انتظار تا 180 ثانیه (3 دقیقه)
 
2463
  if new_clip_bytes:
2464
  break
2465
  else:
 
2466
  await asyncio.sleep(5)
2467
 
2468
  if not new_clip_bytes:
2469
+ return await update_status_msg(client, chat_id, proc_msg, "❌ متاسفانه به دلیل ترافیک سنگین سرورهای رندر، عملیات متوقف شد. لطفاً کمی بعد مجدداً تلاش کنید.")
2470
 
2471
  if base_video_bytes is not None:
2472
+ proc_msg = await update_status_msg(client, chat_id, proc_msg, "🔄 در حال متصل کردن ویدیوهای ساخته شده به یکدیگر...")
2473
  base_video_bytes = await asyncio.to_thread(local_merge_videos, base_video_bytes, new_clip_bytes)
2474
  else:
2475
  base_video_bytes = new_clip_bytes
2476
 
2477
  if loop_idx < loops_needed - 1:
2478
  current_secs = (loop_idx + 1) * 5
2479
+ proc_msg = await update_status_msg(client, chat_id, proc_msg, f" {current_secs} ثانیه از ویدیو ساخته شد!\n📸 در حال آماده‌سازی برای ساخت ثانیه‌های بعدی...")
2480
  current_image_bytes = await asyncio.to_thread(helper_extract_last_frame, base_video_bytes)
2481
  if not current_image_bytes:
2482
  await update_status_msg(client, chat_id, proc_msg, "⚠️ استخراج فریم با مشکل مواجه شد. عملیات در همین نقطه پایان یافت.")
2483
  break
2484
 
2485
+ proc_msg = await update_status_msg(client, chat_id, proc_msg, "🚀 ویدیو کاملاً آماده شد! در حال آپلود سریع در سرور روبیکا...")
2486
 
2487
  try:
2488
  file_name = f"video_{uuid.uuid4().hex}.mp4"
2489
  await asyncio.to_thread(sync_write_file, file_name, base_video_bytes)
2490
 
2491
+ caption_text = f"🎞 ویدیو شما با موفقیت آماده شد!\n⏱ زمان: {duration_int} ثانیه\n✨ پرامپت بهینه شده:\n{eng_prompt}"
2492
  upload_result = False
2493
 
2494
  for up_att in range(3):