Opera8 commited on
Commit
da25c3d
·
verified ·
1 Parent(s): e9ca807

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -116
app.py CHANGED
@@ -2319,7 +2319,7 @@ def apply_example(idx: str):
2319
 
2320
 
2321
  ####################################################################################################
2322
- ### PART 20: Gradio UI Layout & Launch (REVISED & FIXED)
2323
  ####################################################################################################
2324
 
2325
  # JS Function to handle download request via PostMessage
@@ -2341,19 +2341,13 @@ async (video) => {
2341
  }
2342
  """
2343
 
2344
- # این تابع جاوااسکریپت فقط مسئول فراخوانی API بهینه ساز است
2345
- # ورودی ها را از پایتون می گیرد و خروجی (پرامپت بهینه شده) را به پایتون برمی گرداند
2346
  js_enhancer_api_call = """
2347
  async (firstFrame, promptText, mode) => {
2348
  // اگر حالت انتخابی نیازی به بهینه سازی ندارد، پرامپت اصلی را برگردان
2349
- if (mode !== 'تبدیل تصویر به ویدیو' && mode !== 'تکمیل فریم‌های میانی') {
2350
- return promptText;
2351
- }
2352
-
2353
- // API بهینه ساز به تصویر نیاز دارد
2354
- if (!firstFrame) {
2355
- // چون این مرحله در میانه راه است، به کاربر اطلاع داده و با پرامپت اصلی ادامه می دهیم
2356
- console.warn("Enhancement skipped: First frame image is required.");
2357
  return promptText;
2358
  }
2359
 
@@ -2379,12 +2373,11 @@ async (firstFrame, promptText, mode) => {
2379
 
2380
  const data = await apiResponse.json();
2381
  console.log("Enhanced Prompt received:", data.animation_prompt);
2382
- // پرامپت بهینه شده را برای مرحله بعد در گرادیو برگردان
2383
- return data.animation_prompt;
2384
 
2385
  } catch (error) {
2386
  console.error("Enhancement API Error:", error);
2387
- // در صورت خطا، پرامپت اصلی را برگردان تا فرآیند ساخت ویدیو متوقف نشود
2388
  return promptText;
2389
  }
2390
  }
@@ -2395,17 +2388,10 @@ def apply_example(idx: str):
2395
  idx = int(idx)
2396
  img, prompt_txt, cam, res, mode, vid, aud, end_img = examples_list[idx]
2397
  return (
2398
- img or None,
2399
- prompt_txt,
2400
- cam,
2401
- res,
2402
- mode,
2403
  gr.update(value=vid or None, visible=(mode == "Motion Control")),
2404
- aud or None,
2405
- aud or None,
2406
- end_img or None,
2407
- gr.update(value=None),
2408
- gr.update(visible=False)
2409
  )
2410
 
2411
  with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
@@ -2423,90 +2409,65 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2423
  """
2424
  )
2425
 
2426
- # State components to pass data between Python and JS
2427
- # این کامپوننت ها برای کاربر قابل مشاهده نیستند
2428
  enhanced_prompt_state = gr.State("")
2429
 
2430
  with gr.Column(elem_id="col-container"):
 
2431
  with gr.Row(elem_id="mode-row"):
2432
- radioanimated_mode = RadioAnimated(
2433
- choices=["تبدیل تصویر به ویدیو", "تکمیل فریم‌های میانی"],
2434
- value="تبدیل تصویر به ویدیو",
2435
- elem_id="radioanimated_mode"
2436
- )
2437
  with gr.Row():
2438
  with gr.Column(elem_id="step-column"):
2439
  with gr.Row():
2440
- first_frame = gr.Image(
2441
- label="تصویر اول (برای بهینه‌سازی پرامپت الزامی است)",
2442
- type="filepath",
2443
- height=256
2444
- )
2445
- end_frame = gr.Image(
2446
- label="تصویر آخر (اختیاری)",
2447
- type="filepath",
2448
- height=256,
2449
- visible=False,
2450
- )
2451
  input_video = gr.Video(label="Motion Reference Video", height=256, visible=False)
2452
-
2453
- relocate = gr.HTML(value="", html_template="<div></div>", js_on_load=r"""
2454
- (() => {
2455
- function moveIntoFooter() {
2456
- const promptRoot = document.querySelector("#prompt_ui"); if (!promptRoot) return false;
2457
- const footer = promptRoot.querySelector(".ds-footer"); if (!footer) return false;
2458
- const dur = document.querySelector("#duration_ui .cd-wrap");
2459
- const res = document.querySelector("#resolution_ui .cd-wrap");
2460
- const cam = document.querySelector("#camera_ui .cd-wrap");
2461
- if (!dur || !res || !cam) return false;
2462
- footer.appendChild(dur); footer.appendChild(res); footer.appendChild(cam);
2463
- return true;
2464
- }
2465
- const tick = () => { if (!moveIntoFooter()) requestAnimationFrame(tick); };
2466
- requestAnimationFrame(tick);
2467
- })();
2468
- """)
2469
-
2470
  prompt_ui = PromptBox(value="این تصویر را با حرکت سینمایی و انیمیشن روان زنده کن", elem_id="prompt_ui")
2471
  audio_input = gr.File(label="Audio (Optional)", file_types=["audio"], type="filepath", elem_id="audio_input_hidden")
2472
  audio_ui = AudioDropUpload(target_audio_elem_id="audio_input_hidden", elem_id="audio_ui")
2473
- prompt = gr.Textbox(label="Prompt", value="این تصویر را با حرکت سینمایی و انیمیشن روان زنده کن", lines=3, max_lines=3, placeholder="حرکت و انیمیشن مورد نظر خود را توصیف کنید...", visible=False)
2474
  enhance_prompt = gr.Checkbox(label="Enhance Prompt", value=True, visible=False)
2475
-
2476
  with gr.Accordion("تنظیمات پیشرفته", open=False, visible=False):
2477
  seed = gr.Slider(label="سید (Seed)", minimum=0, maximum=MAX_SEED, value=DEFAULT_SEED, step=1)
2478
  randomize_seed = gr.Checkbox(label="استفاده از سید تصادفی", value=True)
2479
-
2480
  with gr.Column(elem_id="step-column"):
2481
  output_video = gr.Video(label="ویدیوی ساخته شده", autoplay=True, height=512)
2482
  with gr.Row():
2483
  download_btn = gr.Button("📥 دانلود ویدیو", variant="secondary", size="sm", scale=0, visible=False)
2484
 
2485
  with gr.Row(elem_id="controls-row"):
2486
- duration_ui = CameraDropdown(choices=["3s", "5s", "10s"], value="5s", title="مدت زمان ویدیو", elem_id="duration_ui")
2487
- duration = gr.Slider(label="Duration (seconds)", minimum=1.0, maximum=10.0, value=5.0, step=0.1, visible=False)
2488
-
2489
- ICON_16_9 = """<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3" y="7" width="18" height="10" rx="2" stroke="currentColor" stroke-width="2"/></svg>"""
2490
- ICON_1_1 = """<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="2" stroke="currentColor" stroke-width="2"/></svg>"""
2491
- ICON_9_16 = """<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="7" y="3" width="10" height="18" rx="2" stroke="currentColor" stroke-width="2"/></svg>"""
2492
-
2493
- resolution_ui = CameraDropdown(
2494
- choices=[{"label": "16:9", "value": "16:9", "icon": ICON_16_9}, {"label": "1:1", "value": "1:1", "icon": ICON_1_1}, {"label": "9:16", "value": "9:16", "icon": ICON_9_16}],
2495
- value="16:9", title="ابعاد تصویر", elem_id="resolution_ui"
2496
- )
2497
- width = gr.Number(label="Width", value=DEFAULT_1_STAGE_WIDTH, precision=0, visible=False)
2498
- height = gr.Number(label="Height", value=DEFAULT_1_STAGE_HEIGHT, precision=0, visible=False)
2499
- camera_ui = CameraDropdown(choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", title="افکت دوربین (LoRA)", elem_id="camera_ui")
2500
- camera_lora = gr.Dropdown(label="Camera Control LoRA", choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", visible=False)
2501
 
2502
  generate_btn = gr.Button("🤩 ساخت ویدیو", variant="primary", elem_classes="button-gradient")
2503
 
2504
- # توابع کمکی برای به‌روزرسانی UI
2505
- def lock_ui():
 
2506
  return gr.Button(value="⏳ در حال بهینه سازی پرامپت...", interactive=False)
2507
 
2508
- def re_enable_ui():
2509
- return gr.Button(value="🤩 ساخت ویدیو", interactive=True)
 
 
 
 
 
 
 
 
 
 
 
 
2510
 
2511
  # اتصال رویدادها
2512
  camera_ui.change(fn=lambda x: x, inputs=camera_ui, outputs=camera_lora, api_visibility="private")
@@ -2519,22 +2480,24 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2519
 
2520
  # --- زنجیره اصلی رویداد ساخت ویدیو ---
2521
 
2522
- # 1. وقتی کاربر روی دکمه کلیک می کند، ابتدا UI را قفل کرده و متن دکمه را تغییر می دهیم.
2523
- # این تابع پایتون هیچ کاری جز آماده سازی UI انجام نمی دهد.
2524
  generate_btn.click(
2525
- fn=lock_ui,
2526
  outputs=[generate_btn]
2527
- ) \
2528
- .then(
2529
- # 2. سپس، تابع جاوااسکریپت را برای بهینه سازی پرامپت فراخوانی می کنیم.
2530
- # ورودی های آن از کامپوننت های گرادیو گرفته شده و خروجی آن در یک State ذخیره می شود.
2531
- fn=None,
2532
  inputs=[first_frame, prompt, radioanimated_mode],
2533
  outputs=[enhanced_prompt_state],
2534
  js=js_enhancer_api_call
2535
- ) \
2536
- .then(
2537
- # 3. حالا، تابع اصلی ساخت ویدیو را با پرامپت بهینه شده (که از State خوانده می شود) اجرا می کنیم.
 
 
 
 
2538
  fn=generate_video,
2539
  inputs=[
2540
  first_frame, end_frame, enhanced_prompt_state, duration, input_video,
@@ -2542,16 +2505,10 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2542
  height, width, camera_lora, audio_input
2543
  ],
2544
  outputs=[output_video]
2545
- ) \
2546
- .then(
2547
- # 4. پس از اتمام ساخت ویدیو، دکمه دانلود را نمایش می دهیم.
2548
- fn=lambda: gr.update(visible=True),
2549
- outputs=[download_btn]
2550
- ) \
2551
- .then(
2552
- # 5. در نهایت، UI را دوباره فعال می کنیم.
2553
- fn=re_enable_ui,
2554
- outputs=[generate_btn]
2555
  )
2556
 
2557
  # منطق نمونه ها
@@ -2565,25 +2522,14 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
2565
  ]
2566
 
2567
  preset_gallery = PresetGallery(
2568
- items=[
2569
- {"thumb": "examples/supergirl-2.png", "label": "تصویر و صدا به ویدیو"},
2570
- {"thumb": "examples/frame3.png", "label": "تصویر اول و آخر"},
2571
- {"thumb": "examples/supergirl.png", "label": "تصویر به ویدیو (عروسک)"},
2572
- {"thumb": "examples/highland.png", "label": "تصویر به ویدیو (گاو)"},
2573
- {"thumb": "examples/wednesday.png", "label": "تصویر به ویدیو (ونزدی)"},
2574
- {"thumb": "examples/astronaut.png", "label": "تصویر به ویدیو (فضانورد)"},
2575
- ],
2576
  title="برای شروع روی یکی از نمونه‌ها کلیک کنید",
2577
  )
2578
 
2579
  preset_gallery.change(
2580
  fn=apply_example,
2581
  inputs=preset_gallery,
2582
- outputs=[
2583
- first_frame, prompt_ui, camera_ui, resolution_ui, radioanimated_mode,
2584
- input_video, audio_input, audio_ui, end_frame,
2585
- output_video, download_btn
2586
- ],
2587
  api_visibility="private",
2588
  )
2589
 
 
2319
 
2320
 
2321
  ####################################################################################################
2322
+ ### PART 20: Gradio UI Layout & Launch (REVISED & FIXED for Step-by-Step Feedback)
2323
  ####################################################################################################
2324
 
2325
  # JS Function to handle download request via PostMessage
 
2341
  }
2342
  """
2343
 
2344
+ # این تابع JS فقط مسئول فراخوانی API بهینه ساز است
2345
+ # خروجی آن (پرامپت بهینه شده) به مرحله بعدی در زنجیره گرادیو ارسال می شود
2346
  js_enhancer_api_call = """
2347
  async (firstFrame, promptText, mode) => {
2348
  // اگر حالت انتخابی نیازی به بهینه سازی ندارد، پرامپت اصلی را برگردان
2349
+ if (mode !== 'تبدیل تصویر به ویدیو' && mode !== 'تکمیل فریم‌های میانی' || !firstFrame) {
2350
+ if (!firstFrame) console.warn("Enhancement skipped: First frame image is required.");
 
 
 
 
 
 
2351
  return promptText;
2352
  }
2353
 
 
2373
 
2374
  const data = await apiResponse.json();
2375
  console.log("Enhanced Prompt received:", data.animation_prompt);
2376
+ return data.animation_prompt; // پرامپت بهینه شده را برگردان
 
2377
 
2378
  } catch (error) {
2379
  console.error("Enhancement API Error:", error);
2380
+ // در صورت خطا، پرامپت اصلی را برگردان تا فرآیند متوقف نشود
2381
  return promptText;
2382
  }
2383
  }
 
2388
  idx = int(idx)
2389
  img, prompt_txt, cam, res, mode, vid, aud, end_img = examples_list[idx]
2390
  return (
2391
+ img or None, prompt_txt, cam, res, mode,
 
 
 
 
2392
  gr.update(value=vid or None, visible=(mode == "Motion Control")),
2393
+ aud or None, aud or None, end_img or None,
2394
+ gr.update(value=None), gr.update(visible=False)
 
 
 
2395
  )
2396
 
2397
  with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
 
2409
  """
2410
  )
2411
 
2412
+ # کامپوننت State برای نگهداری پرامپت بهینه شده
 
2413
  enhanced_prompt_state = gr.State("")
2414
 
2415
  with gr.Column(elem_id="col-container"):
2416
+ # ... تعریف بقیه UI ...
2417
  with gr.Row(elem_id="mode-row"):
2418
+ radioanimated_mode = RadioAnimated(choices=["تبدیل تصویر به ویدیو", "تکمیل فریم‌های میانی"], value="تبدیل تصویر به ویدیو", elem_id="radioanimated_mode")
 
 
 
 
2419
  with gr.Row():
2420
  with gr.Column(elem_id="step-column"):
2421
  with gr.Row():
2422
+ first_frame = gr.Image(label="تصویر اول (برای بهینه‌سازی پرامپت الزامی است)", type="filepath", height=256)
2423
+ end_frame = gr.Image(label="تصویر آخرختیاری)", type="filepath", height=256, visible=False)
 
 
 
 
 
 
 
 
 
2424
  input_video = gr.Video(label="Motion Reference Video", height=256, visible=False)
2425
+ 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); })();""")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2426
  prompt_ui = PromptBox(value="این تصویر را با حرکت سینمایی و انیمیشن روان زنده کن", elem_id="prompt_ui")
2427
  audio_input = gr.File(label="Audio (Optional)", file_types=["audio"], type="filepath", elem_id="audio_input_hidden")
2428
  audio_ui = AudioDropUpload(target_audio_elem_id="audio_input_hidden", elem_id="audio_ui")
2429
+ prompt = gr.Textbox(label="Prompt", value="این تصویر را با حرکت سینمایی و انیمیشن روان زنده کن", lines=3, max_lines=3, visible=False)
2430
  enhance_prompt = gr.Checkbox(label="Enhance Prompt", value=True, visible=False)
 
2431
  with gr.Accordion("تنظیمات پیشرفته", open=False, visible=False):
2432
  seed = gr.Slider(label="سید (Seed)", minimum=0, maximum=MAX_SEED, value=DEFAULT_SEED, step=1)
2433
  randomize_seed = gr.Checkbox(label="استفاده از سید تصادفی", value=True)
2434
+
2435
  with gr.Column(elem_id="step-column"):
2436
  output_video = gr.Video(label="ویدیوی ساخته شده", autoplay=True, height=512)
2437
  with gr.Row():
2438
  download_btn = gr.Button("📥 دانلود ویدیو", variant="secondary", size="sm", scale=0, visible=False)
2439
 
2440
  with gr.Row(elem_id="controls-row"):
2441
+ duration_ui = CameraDropdown(choices=["3s", "5s", "10s"], value="5s", title="مدت زمان ویدیو", elem_id="duration_ui")
2442
+ duration = gr.Slider(label="Duration (seconds)", minimum=1.0, maximum=10.0, value=5.0, step=0.1, visible=False)
2443
+ ICON_16_9, ICON_1_1, ICON_9_16 = ("<svg viewBox='0 0 24 24' fill='none' aria-hidden='true'><rect x='3' y='7' width='18' height='10' rx='2' stroke='currentColor' stroke-width='2'/></svg>", "<svg viewBox='0 0 24 24' fill='none' aria-hidden='true'><rect x='6' y='6' width='12' height='12' rx='2' stroke='currentColor' stroke-width='2'/></svg>", "<svg viewBox='0 0 24 24' fill='none' aria-hidden='true'><rect x='7' y='3' width='10' height='18' rx='2' stroke='currentColor' stroke-width='2'/></svg>")
2444
+ resolution_ui = CameraDropdown(choices=[{"label": "16:9", "value": "16:9", "icon": ICON_16_9}, {"label": "1:1", "value": "1:1", "icon": ICON_1_1}, {"label": "9:16", "value": "9:16", "icon": ICON_9_16}], value="16:9", title="ابعاد تصویر", elem_id="resolution_ui")
2445
+ width = gr.Number(label="Width", value=DEFAULT_1_STAGE_WIDTH, precision=0, visible=False)
2446
+ height = gr.Number(label="Height", value=DEFAULT_1_STAGE_HEIGHT, precision=0, visible=False)
2447
+ camera_ui = CameraDropdown(choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", title="افکت دوربین (LoRA)", elem_id="camera_ui")
2448
+ camera_lora = gr.Dropdown(label="Camera Control LoRA", choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", visible=False)
 
 
 
 
 
 
 
2449
 
2450
  generate_btn = gr.Button("🤩 ساخت ویدیو", variant="primary", elem_classes="button-gradient")
2451
 
2452
+ # توابع کمکی برای کنترل جریان و به‌روزرسانی UI
2453
+ def start_process():
2454
+ """مرحله ۱: UI را برای شروع فرآیند آماده می کند."""
2455
  return gr.Button(value="⏳ در حال بهینه سازی پرامپت...", interactive=False)
2456
 
2457
+ def prepare_for_generation(enhanced_prompt):
2458
+ """مرحله ۳: UI را برای شروع ساخت ویدیو آماده می کند."""
2459
+ # پرامپت بهینه شده را در UI نمایش می دهیم
2460
+ return {
2461
+ generate_btn: gr.Button(value="🚀 در حال ساخت ویدیو...", interactive=False),
2462
+ prompt_ui: gr.update(value=enhanced_prompt)
2463
+ }
2464
+
2465
+ def finalize_process():
2466
+ """مرحله ۵: UI را پس از اتمام کار به حالت اولیه برمی گرداند."""
2467
+ return {
2468
+ generate_btn: gr.Button(value="🤩 ساخت ویدیو", interactive=True),
2469
+ download_btn: gr.Button(visible=True)
2470
+ }
2471
 
2472
  # اتصال رویدادها
2473
  camera_ui.change(fn=lambda x: x, inputs=camera_ui, outputs=camera_lora, api_visibility="private")
 
2480
 
2481
  # --- زنجیره اصلی رویداد ساخت ویدیو ---
2482
 
2483
+ # 1. کلیک کاربر: تابع پایتون start_process را برای قفل کردن UI اجرا می کند.
 
2484
  generate_btn.click(
2485
+ fn=start_process,
2486
  outputs=[generate_btn]
2487
+ ).then(
2488
+ # 2. سپس: تابع جاوااسکریپت js_enhancer_api_call برای گرفتن پرامپت بهینه شده اجرا می شود.
2489
+ # خروجی آن به طور خودکار به ورودی تابع بعدی در زنجیره داده می شود.
2490
+ fn=None,
 
2491
  inputs=[first_frame, prompt, radioanimated_mode],
2492
  outputs=[enhanced_prompt_state],
2493
  js=js_enhancer_api_call
2494
+ ).then(
2495
+ # 3. سپس: تابع پایتون prepare_for_generation برای به‌روزرسانی UI با وضعیت جدید اجرا می شود.
2496
+ fn=prepare_for_generation,
2497
+ inputs=[enhanced_prompt_state],
2498
+ outputs=[generate_btn, prompt_ui]
2499
+ ).then(
2500
+ # 4. سپس: تابع اصلی ساخت ویدیو با پرامپت بهینه شده اجرا می شود.
2501
  fn=generate_video,
2502
  inputs=[
2503
  first_frame, end_frame, enhanced_prompt_state, duration, input_video,
 
2505
  height, width, camera_lora, audio_input
2506
  ],
2507
  outputs=[output_video]
2508
+ ).then(
2509
+ # 5. در نهایت: تابع پایتون finalize_process برای باز کردن قفل UI و نمایش دکمه دانلود اجرا می شود.
2510
+ fn=finalize_process,
2511
+ outputs=[generate_btn, download_btn]
 
 
 
 
 
 
2512
  )
2513
 
2514
  # منطق نمونه ها
 
2522
  ]
2523
 
2524
  preset_gallery = PresetGallery(
2525
+ items=[{"thumb": "examples/supergirl-2.png", "label": "تصویر و صدا به ویدیو"}, {"thumb": "examples/frame3.png", "label": "تصویر اول و آخر"}, {"thumb": "examples/supergirl.png", "label": "تصویر به ویدیو (عروسک)"}, {"thumb": "examples/highland.png", "label": "تصویر به ویدیو (گاو)"}, {"thumb": "examples/wednesday.png", "label": "تصویر به ویدیو (ونزدی)"}, {"thumb": "examples/astronaut.png", "label": "تصویر به ویدیو (فضانورد)"}],
 
 
 
 
 
 
 
2526
  title="برای شروع روی یکی از نمونه‌ها کلیک کنید",
2527
  )
2528
 
2529
  preset_gallery.change(
2530
  fn=apply_example,
2531
  inputs=preset_gallery,
2532
+ outputs=[first_frame, prompt_ui, camera_ui, resolution_ui, radioanimated_mode, input_video, audio_input, audio_ui, end_frame, output_video, download_btn],
 
 
 
 
2533
  api_visibility="private",
2534
  )
2535