Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -2423,7 +2423,7 @@ def ui_generate_video(
|
|
| 2423 |
)
|
| 2424 |
|
| 2425 |
|
| 2426 |
-
# کدهای جا
|
| 2427 |
relocate_js = r"""
|
| 2428 |
(() => {
|
| 2429 |
function getGradioRoot() {
|
|
@@ -2442,20 +2442,91 @@ relocate_js = r"""
|
|
| 2442 |
const c = root.querySelector("#camera_ui .cd-wrap");
|
| 2443 |
if (!d || !r || !c) return false;
|
| 2444 |
|
| 2445 |
-
f.appendChild(d);
|
| 2446 |
-
f.appendChild(r);
|
| 2447 |
-
f.appendChild(c);
|
| 2448 |
return true;
|
| 2449 |
}
|
| 2450 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2451 |
const tick = () => {
|
| 2452 |
if (!moveIntoFooter()) requestAnimationFrame(tick);
|
|
|
|
| 2453 |
};
|
| 2454 |
requestAnimationFrame(tick);
|
| 2455 |
})();
|
| 2456 |
"""
|
| 2457 |
|
| 2458 |
with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2459 |
gr.HTML(
|
| 2460 |
"""
|
| 2461 |
<div style="text-align: center; padding: 20px;">
|
|
@@ -2507,6 +2578,9 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
|
|
| 2507 |
camera_lora = gr.Dropdown(label="Camera Control LoRA", choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", visible=False)
|
| 2508 |
|
| 2509 |
generate_btn = gr.Button("🤩 ساخت ویدیو", variant="primary", elem_classes="button-gradient", elem_id="generate_btn")
|
|
|
|
|
|
|
|
|
|
| 2510 |
|
| 2511 |
# اتصال رویدادها
|
| 2512 |
camera_ui.change(fn=lambda x: x, inputs=camera_ui, outputs=camera_lora, api_visibility="private")
|
|
@@ -2517,18 +2591,22 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
|
|
| 2517 |
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")
|
| 2518 |
download_btn.click(fn=None, inputs=[output_video], js=js_download_video)
|
| 2519 |
|
| 2520 |
-
#
|
| 2521 |
-
|
| 2522 |
-
|
| 2523 |
-
|
| 2524 |
-
|
| 2525 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2526 |
fn=ui_lock_and_enhance,
|
| 2527 |
inputs=[first_frame, prompt, radioanimated_mode],
|
| 2528 |
outputs=[generate_btn, prompt_ui, prompt, output_video]
|
| 2529 |
-
)
|
| 2530 |
-
|
| 2531 |
-
step2 = step1.then(
|
| 2532 |
fn=ui_generate_video,
|
| 2533 |
inputs=[
|
| 2534 |
first_frame, end_frame, prompt,
|
|
@@ -2538,11 +2616,6 @@ with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
|
|
| 2538 |
outputs=[generate_btn, output_video, download_btn]
|
| 2539 |
)
|
| 2540 |
|
| 2541 |
-
# 🔴 کلید حل مشکل: مدیریت استثناها (Exceptions)
|
| 2542 |
-
# با افزودن .error هر وقت سرور به خاطر محدودیت GPU درخواست را رد کند، دکمه سریعاً ریست میشود.
|
| 2543 |
-
step1.error(fn=reset_button_state, inputs=[], outputs=[generate_btn], api_visibility="private")
|
| 2544 |
-
step2.error(fn=reset_button_state, inputs=[], outputs=[generate_btn], api_visibility="private")
|
| 2545 |
-
|
| 2546 |
# منطق نمونه ها
|
| 2547 |
examples_list = [
|
| 2548 |
["examples/supergirl-2.png", "A fuzzy puppet superhero...", "Static", "16:9", "تبدیل تصویر به ویدیو", None, "examples/supergirl.m4a", None],
|
|
|
|
| 2423 |
)
|
| 2424 |
|
| 2425 |
|
| 2426 |
+
# کدهای جاوااسکریپت قدرتمند برای بازکردن قفل دکمه هنگام خطا
|
| 2427 |
relocate_js = r"""
|
| 2428 |
(() => {
|
| 2429 |
function getGradioRoot() {
|
|
|
|
| 2442 |
const c = root.querySelector("#camera_ui .cd-wrap");
|
| 2443 |
if (!d || !r || !c) return false;
|
| 2444 |
|
| 2445 |
+
f.appendChild(d); f.appendChild(r); f.appendChild(c);
|
|
|
|
|
|
|
| 2446 |
return true;
|
| 2447 |
}
|
| 2448 |
|
| 2449 |
+
function checkAndReset(mutations) {
|
| 2450 |
+
let errorFound = false;
|
| 2451 |
+
|
| 2452 |
+
// بررسی افزوده شدن Toast ها
|
| 2453 |
+
if (mutations) {
|
| 2454 |
+
mutations.forEach(m => {
|
| 2455 |
+
m.addedNodes.forEach(node => {
|
| 2456 |
+
if (node.nodeType === 1) {
|
| 2457 |
+
const txt = (node.textContent || "").toLowerCase();
|
| 2458 |
+
if (txt.includes("quota") || txt.includes("exceeded") || txt.includes("error") || txt.includes("خطا")) {
|
| 2459 |
+
errorFound = true;
|
| 2460 |
+
}
|
| 2461 |
+
if (node.classList && node.classList.contains("toast-wrap")) {
|
| 2462 |
+
errorFound = true;
|
| 2463 |
+
}
|
| 2464 |
+
}
|
| 2465 |
+
});
|
| 2466 |
+
});
|
| 2467 |
+
}
|
| 2468 |
+
|
| 2469 |
+
// بررسی متون در کل صفحه (حتی مواردی که توسط کد شما مخفی شدهاند)
|
| 2470 |
+
const root = getGradioRoot();
|
| 2471 |
+
const fullText = ((document.body.textContent || "") + " " + (root.textContent || "")).toLowerCase();
|
| 2472 |
+
if (fullText.includes("exceeded your gpu quota") || fullText.includes("gpu quota")) {
|
| 2473 |
+
errorFound = true;
|
| 2474 |
+
}
|
| 2475 |
+
|
| 2476 |
+
if (errorFound && !window._resetFiredBtn) {
|
| 2477 |
+
window._resetFiredBtn = true;
|
| 2478 |
+
console.log("Error or Quota detected! Forcing reset...");
|
| 2479 |
+
|
| 2480 |
+
// کلیک کردن دکمه مخفی پایتون که صف رو دور میزند
|
| 2481 |
+
const rb = root.querySelector('#reset_btn');
|
| 2482 |
+
if (rb) {
|
| 2483 |
+
const btn = rb.tagName === 'BUTTON' ? rb : rb.querySelector('button');
|
| 2484 |
+
if (btn) btn.click();
|
| 2485 |
+
}
|
| 2486 |
+
|
| 2487 |
+
// باز کردن فیزیکی قفل دکمه تولید (احتیاط ثانویه)
|
| 2488 |
+
const gbWrap = root.querySelector('#generate_btn');
|
| 2489 |
+
if (gbWrap) {
|
| 2490 |
+
const gb = gbWrap.tagName === 'BUTTON' ? gbWrap : gbWrap.querySelector('button');
|
| 2491 |
+
if (gb) {
|
| 2492 |
+
gb.innerText = "🤩 ساخت ویدیو";
|
| 2493 |
+
gb.disabled = false;
|
| 2494 |
+
gb.classList.remove("disabled");
|
| 2495 |
+
gb.style.pointerEvents = "auto";
|
| 2496 |
+
}
|
| 2497 |
+
}
|
| 2498 |
+
|
| 2499 |
+
// جلوگیری از کلیک مکرر به مدت ۵ ثانیه
|
| 2500 |
+
setTimeout(() => { window._resetFiredBtn = false; }, 5000);
|
| 2501 |
+
}
|
| 2502 |
+
}
|
| 2503 |
+
|
| 2504 |
+
function setupErrorObserver() {
|
| 2505 |
+
const observer = new MutationObserver(checkAndReset);
|
| 2506 |
+
observer.observe(document.body, { childList: true, subtree: true });
|
| 2507 |
+
|
| 2508 |
+
const root = getGradioRoot();
|
| 2509 |
+
if (root !== document) {
|
| 2510 |
+
observer.observe(root, { childList: true, subtree: true });
|
| 2511 |
+
}
|
| 2512 |
+
|
| 2513 |
+
// اسکن دائمی صفحه هر 1 ثانیه به عنوان روش تضمینی
|
| 2514 |
+
setInterval(() => checkAndReset(), 1000);
|
| 2515 |
+
}
|
| 2516 |
+
|
| 2517 |
const tick = () => {
|
| 2518 |
if (!moveIntoFooter()) requestAnimationFrame(tick);
|
| 2519 |
+
else setupErrorObserver();
|
| 2520 |
};
|
| 2521 |
requestAnimationFrame(tick);
|
| 2522 |
})();
|
| 2523 |
"""
|
| 2524 |
|
| 2525 |
with gr.Blocks(title="LTX-2 Video Distilled 🎥🔈") as demo:
|
| 2526 |
+
|
| 2527 |
+
# مخفی کردن فیزیکی دکمه ریست بدون استفاده از visible=False
|
| 2528 |
+
gr.HTML("<style>#reset_btn { display: none !important; }</style>")
|
| 2529 |
+
|
| 2530 |
gr.HTML(
|
| 2531 |
"""
|
| 2532 |
<div style="text-align: center; padding: 20px;">
|
|
|
|
| 2578 |
camera_lora = gr.Dropdown(label="Camera Control LoRA", choices=[name for name, _ in VISIBLE_RUNTIME_LORA_CHOICES], value="No LoRA", visible=False)
|
| 2579 |
|
| 2580 |
generate_btn = gr.Button("🤩 ساخت ویدیو", variant="primary", elem_classes="button-gradient", elem_id="generate_btn")
|
| 2581 |
+
|
| 2582 |
+
# توجه مهم: این دکمه دیگر visible=False نیست تا از DOM حذف نشود. توسط CSS بالا مخفی شده است.
|
| 2583 |
+
reset_btn = gr.Button("Reset", elem_id="reset_btn")
|
| 2584 |
|
| 2585 |
# اتصال رویدادها
|
| 2586 |
camera_ui.change(fn=lambda x: x, inputs=camera_ui, outputs=camera_lora, api_visibility="private")
|
|
|
|
| 2591 |
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")
|
| 2592 |
download_btn.click(fn=None, inputs=[output_video], js=js_download_video)
|
| 2593 |
|
| 2594 |
+
# *** رویداد جادویی برای شکستن قفل گاردریو ***
|
| 2595 |
+
# پارامتر queue=False باعث میشود اگر گاردریو در صف گیر کرده باشد، این دستور معطل نشود و فوراً اجرا شود
|
| 2596 |
+
reset_btn.click(
|
| 2597 |
+
fn=lambda: gr.Button(value="🤩 ساخت ویدیو", interactive=True),
|
| 2598 |
+
inputs=[],
|
| 2599 |
+
outputs=[generate_btn],
|
| 2600 |
+
api_visibility="private",
|
| 2601 |
+
queue=False
|
| 2602 |
+
)
|
| 2603 |
+
|
| 2604 |
+
# زنجیره اصلی ساخت ویدیو
|
| 2605 |
+
generate_btn.click(
|
| 2606 |
fn=ui_lock_and_enhance,
|
| 2607 |
inputs=[first_frame, prompt, radioanimated_mode],
|
| 2608 |
outputs=[generate_btn, prompt_ui, prompt, output_video]
|
| 2609 |
+
).then(
|
|
|
|
|
|
|
| 2610 |
fn=ui_generate_video,
|
| 2611 |
inputs=[
|
| 2612 |
first_frame, end_frame, prompt,
|
|
|
|
| 2616 |
outputs=[generate_btn, output_video, download_btn]
|
| 2617 |
)
|
| 2618 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2619 |
# منطق نمونه ها
|
| 2620 |
examples_list = [
|
| 2621 |
["examples/supergirl-2.png", "A fuzzy puppet superhero...", "Static", "16:9", "تبدیل تصویر به ویدیو", None, "examples/supergirl.m4a", None],
|