Opera8 commited on
Commit
173e2b4
·
verified ·
1 Parent(s): f6353b4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -26
app.py CHANGED
@@ -2347,7 +2347,6 @@ def enhance_prompt_on_cpu(image_path: str, prompt: str, mode: str):
2347
  """
2348
  این تابع روی CPU اجرا می‌شود و هیچ سهمیه‌ای از GPU کم نمی‌کند.
2349
  """
2350
- # اگر نیازی به بهینه سازی نیست
2351
  if mode not in ['تبدیل تصویر به ویدیو', 'تکمیل فریم‌های میانی'] or not image_path:
2352
  return prompt
2353
 
@@ -2357,7 +2356,6 @@ def enhance_prompt_on_cpu(image_path: str, prompt: str, mode: str):
2357
  with open(image_path, 'rb') as f:
2358
  files = {'image': f}
2359
  data = {'prompt': prompt, 'is_extension': 'false'}
2360
- # تایم اوت را بالا می بریم تا مطمئن شویم پاسخ می گیریم
2361
  response = requests.post(url, files=files, data=data, timeout=60)
2362
 
2363
  if response.status_code == 200:
@@ -2388,23 +2386,19 @@ def ui_lock_and_enhance(first_frame, prompt, mode):
2388
  """
2389
  مرحله ۱: قفل کردن UI و اجرای بهینه سازی روی CPU
2390
  """
2391
- # تغییر دکمه به حالت لودینگ
2392
  yield (
2393
  gr.Button(value="⏳ در حال بهینه سازی پرامپت (CPU)...", interactive=False),
2394
- gr.update(), # prompt_ui (no change yet)
2395
- gr.update(), # آپدیت تکست‌باکس مخفی
2396
- None # output clear
2397
  )
2398
 
2399
- # اجرای بهینه سازی (سنگین برای شبکه، سبک برای پردازنده)
2400
- # چون دکوراتور @spaces.GPU ندارد، سهمیه شما مصرف نمی شود.
2401
  enhanced = enhance_prompt_on_cpu(first_frame, prompt, mode)
2402
 
2403
- # آماده سازی برای مرحله بعد
2404
  yield (
2405
  gr.Button(value="🚀 در حال ساخت ویدیو (GPU)...", interactive=False),
2406
- gr.update(value=enhanced), # نمایش پرامپت جدید به کاربر در UI
2407
- enhanced, # پاس دادن پرامپت بهینه شده به تکست‌باکس مخفی برای استفاده در تولید
2408
  None
2409
  )
2410
 
@@ -2416,7 +2410,6 @@ def ui_generate_video(
2416
  ):
2417
  """
2418
  مرحله ۲: ساخت ویدیو با استفاده از GPU
2419
- در اینجا تمام زمان تخصیص داده شده صرف ساخت ویدیو می شود.
2420
  """
2421
  video_path = generate_video(
2422
  first_frame, end_frame, enhanced_prompt, duration, input_video,
@@ -2430,6 +2423,52 @@ def ui_generate_video(
2430
  )
2431
 
2432
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2433
  with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2434
  gr.HTML(
2435
  """
@@ -2453,13 +2492,14 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2453
  first_frame = gr.Image(label="تصویر اول (برای بهینه‌سازی پرامپت الزامی است)", type="filepath", height=256)
2454
  end_frame = gr.Image(label="تصویر آخر (اختیاری)", type="filepath", height=256, visible=False)
2455
  input_video = gr.Video(label="Motion Reference Video", height=256, visible=False)
2456
- relocate = gr.HTML(value="", html_template="<div></div>", js_on_load=r"""(() => { function moveIntoFooter() { const p = document.querySelector("#prompt_ui"), f = p ? p.querySelector(".ds-footer") : null; if (!f) return false; const d = document.querySelector("#duration_ui .cd-wrap"), r = document.querySelector("#resolution_ui .cd-wrap"), c = document.querySelector("#camera_ui .cd-wrap"); if (!d || !r || !c) return false; f.appendChild(d); f.appendChild(r); f.appendChild(c); return true; } const tick = () => { if (!moveIntoFooter()) requestAnimationFrame(tick); }; requestAnimationFrame(tick); })();""")
 
 
2457
  prompt_ui = PromptBox(value="این تصویر را با حرکت سینمایی و انیمیشن روان زنده کن", elem_id="prompt_ui")
2458
  audio_input = gr.File(label="Audio (Optional)", file_types=["audio"], type="filepath", elem_id="audio_input_hidden")
2459
  audio_ui = AudioDropUpload(target_audio_elem_id="audio_input_hidden", elem_id="audio_ui")
2460
  prompt = gr.Textbox(label="Prompt", value="این تصویر را با حرکت سینمایی و انیمیشن روان زنده کن", lines=3, max_lines=3, visible=False)
2461
 
2462
- # مقدار اولیه به False تغییر کرد تا تابع داخلی مدل دوباره تلاش نکند پرامپت را تغییر دهد
2463
  enhance_prompt_flag_input = gr.Checkbox(label="Enhance Prompt", value=False, visible=False)
2464
 
2465
  with gr.Accordion("تنظیمات پیشرفته", open=False, visible=False):
@@ -2480,7 +2520,9 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2480
  camera_ui = CameraDropdown(choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", title="افکت دوربین (LoRA)", elem_id="camera_ui")
2481
  camera_lora = gr.Dropdown(label="Camera Control LoRA", choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", visible=False)
2482
 
2483
- generate_btn = gr.Button("🤩 ساخت ویدیو", variant="primary", elem_classes="button-gradient")
 
 
2484
 
2485
  # اتصال رویدادها
2486
  camera_ui.change(fn=lambda x: x, inputs=camera_ui, outputs=camera_lora, api_visibility="private")
@@ -2491,9 +2533,16 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2491
  audio_ui.change(fn=lambda v: None if v == "__CLEAR__" or not v else gr.update(), inputs=audio_ui, outputs=audio_input, api_visibility="private")
2492
  download_btn.click(fn=None, inputs=[output_video], js=js_download_video)
2493
 
2494
- # --- زنجیره اصلی ساخت ویدیو (Main Chain) ---
 
 
 
 
 
 
2495
 
2496
- gen_event = generate_btn.click(
 
2497
  fn=ui_lock_and_enhance,
2498
  inputs=[first_frame, prompt, radioanimated_mode],
2499
  outputs=[generate_btn, prompt_ui, prompt, output_video]
@@ -2507,15 +2556,6 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2507
  outputs=[generate_btn, output_video, download_btn]
2508
  )
2509
 
2510
- # --- هندل کردن خطای محدودیت GPU ---
2511
- # در صورتی که ساخت ویدیو (مثلا به خاطر اتمام سهمیه GPU) با خطا مواجه شود،
2512
- # این بخش وارد عمل شده و فوراً دکمه را به حالت اولیه برمی‌گرداند.
2513
- gen_event.catch(
2514
- fn=lambda: gr.Button(value="🤩 ساخت ویدیو", interactive=True),
2515
- inputs=[],
2516
- outputs=[generate_btn]
2517
- )
2518
-
2519
  # منطق نمونه ها
2520
  examples_list = [
2521
  ["examples/supergirl-2.png", "A fuzzy puppet superhero...", "Static", "16:9", "تبدیل تصویر به ویدیو", None, "examples/supergirl.m4a", None],
 
2347
  """
2348
  این تابع روی CPU اجرا می‌شود و هیچ سهمیه‌ای از GPU کم نمی‌کند.
2349
  """
 
2350
  if mode not in ['تبدیل تصویر به ویدیو', 'تکمیل فریم‌های میانی'] or not image_path:
2351
  return prompt
2352
 
 
2356
  with open(image_path, 'rb') as f:
2357
  files = {'image': f}
2358
  data = {'prompt': prompt, 'is_extension': 'false'}
 
2359
  response = requests.post(url, files=files, data=data, timeout=60)
2360
 
2361
  if response.status_code == 200:
 
2386
  """
2387
  مرحله ۱: قفل کردن UI و اجرای بهینه سازی روی CPU
2388
  """
 
2389
  yield (
2390
  gr.Button(value="⏳ در حال بهینه سازی پرامپت (CPU)...", interactive=False),
2391
+ gr.update(),
2392
+ gr.update(),
2393
+ None
2394
  )
2395
 
 
 
2396
  enhanced = enhance_prompt_on_cpu(first_frame, prompt, mode)
2397
 
 
2398
  yield (
2399
  gr.Button(value="🚀 در حال ساخت ویدیو (GPU)...", interactive=False),
2400
+ gr.update(value=enhanced),
2401
+ enhanced,
2402
  None
2403
  )
2404
 
 
2410
  ):
2411
  """
2412
  مرحله ۲: ساخت ویدیو با استفاده از GPU
 
2413
  """
2414
  video_path = generate_video(
2415
  first_frame, end_frame, enhanced_prompt, duration, input_video,
 
2423
  )
2424
 
2425
 
2426
+ # کدهای جاوااسکریپت برای انتقال المان‌ها و نظارت بر ارور محدودیت GPU
2427
+ relocate_js = r"""
2428
+ (() => {
2429
+ function moveIntoFooter() {
2430
+ const p = document.querySelector("#prompt_ui"), f = p ? p.querySelector(".ds-footer") : null;
2431
+ if (!f) return false;
2432
+ const d = document.querySelector("#duration_ui .cd-wrap"), r = document.querySelector("#resolution_ui .cd-wrap"), c = document.querySelector("#camera_ui .cd-wrap");
2433
+ if (!d || !r || !c) return false;
2434
+ f.appendChild(d); f.appendChild(r); f.appendChild(c);
2435
+ return true;
2436
+ }
2437
+
2438
+ function setupErrorObserver() {
2439
+ const getRoot = () => {
2440
+ const app = document.querySelector('gradio-app');
2441
+ return app && app.shadowRoot ? app.shadowRoot : document;
2442
+ };
2443
+ const observer = new MutationObserver((mutations) => {
2444
+ mutations.forEach(m => {
2445
+ m.addedNodes.forEach(node => {
2446
+ if (node.nodeType === 1) {
2447
+ // بررسی ظهور پاپ‌آپ‌های خطا یا محدودیت
2448
+ const isToast = node.classList && (node.classList.contains('toast-wrap') || node.classList.contains('error') || node.tagName === 'TOAST');
2449
+ const nodeText = (node.innerText || "").toLowerCase();
2450
+ if (isToast || nodeText.includes('quota')) {
2451
+ if (nodeText.includes("quota") || nodeText.includes("exceeded") || nodeText.includes("error") || nodeText.includes("خطا")) {
2452
+ // در صورت مشاهده خطا دکمه ریست نامرئی کلیک می‌شود
2453
+ const rb = getRoot().querySelector("#reset_btn");
2454
+ if (rb) rb.click();
2455
+ }
2456
+ }
2457
+ }
2458
+ });
2459
+ });
2460
+ });
2461
+ observer.observe(document.body, {childList: true, subtree: true});
2462
+ }
2463
+
2464
+ const tick = () => {
2465
+ if (!moveIntoFooter()) requestAnimationFrame(tick);
2466
+ else setupErrorObserver();
2467
+ };
2468
+ requestAnimationFrame(tick);
2469
+ })();
2470
+ """
2471
+
2472
  with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2473
  gr.HTML(
2474
  """
 
2492
  first_frame = gr.Image(label="تصویر اول (برای بهینه‌سازی پرامپت الزامی است)", type="filepath", height=256)
2493
  end_frame = gr.Image(label="تصویر آخر (اختیاری)", type="filepath", height=256, visible=False)
2494
  input_video = gr.Video(label="Motion Reference Video", height=256, visible=False)
2495
+
2496
+ relocate = gr.HTML(value="", html_template="<div></div>", js_on_load=relocate_js)
2497
+
2498
  prompt_ui = PromptBox(value="این تصویر را با حرکت سینمایی و انیمیشن روان زنده کن", elem_id="prompt_ui")
2499
  audio_input = gr.File(label="Audio (Optional)", file_types=["audio"], type="filepath", elem_id="audio_input_hidden")
2500
  audio_ui = AudioDropUpload(target_audio_elem_id="audio_input_hidden", elem_id="audio_ui")
2501
  prompt = gr.Textbox(label="Prompt", value="این تصویر را با حرکت سینمایی و انیمیشن روان زنده کن", lines=3, max_lines=3, visible=False)
2502
 
 
2503
  enhance_prompt_flag_input = gr.Checkbox(label="Enhance Prompt", value=False, visible=False)
2504
 
2505
  with gr.Accordion("تنظیمات پیشرفته", open=False, visible=False):
 
2520
  camera_ui = CameraDropdown(choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", title="افکت دوربین (LoRA)", elem_id="camera_ui")
2521
  camera_lora = gr.Dropdown(label="Camera Control LoRA", choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", visible=False)
2522
 
2523
+ generate_btn = gr.Button("🤩 ساخت ویدیو", variant="primary", elem_classes="button-gradient", elem_id="generate_btn")
2524
+ # دکمه پنهان که در صورت وقوع ارور توسط جاوااسکریپت کلیک می‌شود تا رابط کاربری بازیابی شود
2525
+ reset_btn = gr.Button("Reset", visible=False, elem_id="reset_btn")
2526
 
2527
  # اتصال رویدادها
2528
  camera_ui.change(fn=lambda x: x, inputs=camera_ui, outputs=camera_lora, api_visibility="private")
 
2533
  audio_ui.change(fn=lambda v: None if v == "__CLEAR__" or not v else gr.update(), inputs=audio_ui, outputs=audio_input, api_visibility="private")
2534
  download_btn.click(fn=None, inputs=[output_video], js=js_download_video)
2535
 
2536
+ # رویداد بازیابی دکمه در زمان وقوع محدودیت (وصل شده به دکمه مخفی)
2537
+ reset_btn.click(
2538
+ fn=lambda: gr.Button(value="🤩 ساخت ویدیو", interactive=True),
2539
+ inputs=[],
2540
+ outputs=[generate_btn],
2541
+ api_visibility="private"
2542
+ )
2543
 
2544
+ # زنجیره اصلی ساخت ویدیو
2545
+ generate_btn.click(
2546
  fn=ui_lock_and_enhance,
2547
  inputs=[first_frame, prompt, radioanimated_mode],
2548
  outputs=[generate_btn, prompt_ui, prompt, output_video]
 
2556
  outputs=[generate_btn, output_video, download_btn]
2557
  )
2558
 
 
 
 
 
 
 
 
 
 
2559
  # منطق نمونه ها
2560
  examples_list = [
2561
  ["examples/supergirl-2.png", "A fuzzy puppet superhero...", "Static", "16:9", "تبدیل تصویر به ویدیو", None, "examples/supergirl.m4a", None],