Commit Β·
fc976be
1
Parent(s): 0ee5602
fix: replace localhost iframe in dubbing tab with native Gradio UI that works on HF Spaces
Browse files
app.py
CHANGED
|
@@ -443,7 +443,95 @@ with gr.Blocks(title="Maya: Immersive Manga AI", css=CUSTOM_CSS) as demo:
|
|
| 443 |
with gr.Tab("π₯ Video Dubbing Studio"):
|
| 444 |
gr.Markdown("### π¬ Cinematic AI Video Dubbing")
|
| 445 |
gr.Markdown("Process your videos with automated translation, multi-speaker voice cloning, and lip sync.")
|
| 446 |
-
gr.HTML(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
|
| 448 |
# --- Dynamic Temperature & Heartbeat Speed Logic ---
|
| 449 |
def update_mood(level, bgm):
|
|
|
|
| 443 |
with gr.Tab("π₯ Video Dubbing Studio"):
|
| 444 |
gr.Markdown("### π¬ Cinematic AI Video Dubbing")
|
| 445 |
gr.Markdown("Process your videos with automated translation, multi-speaker voice cloning, and lip sync.")
|
| 446 |
+
gr.HTML("""
|
| 447 |
+
<div style="background:#0f172a; border-radius:16px; padding:32px; font-family:'Inter',sans-serif; color:white;">
|
| 448 |
+
<div style="text-align:center; margin-bottom:24px;">
|
| 449 |
+
<h2 style="font-size:2em; font-weight:900; letter-spacing:-1px; text-transform:uppercase;
|
| 450 |
+
background:linear-gradient(90deg,#a855f7,#6366f1); -webkit-background-clip:text;
|
| 451 |
+
-webkit-text-fill-color:transparent;">Maya Cinematic Studio</h2>
|
| 452 |
+
<p style="color:#94a3b8; font-size:0.85em;">Upload your video below to begin the dubbing pipeline</p>
|
| 453 |
+
</div>
|
| 454 |
+
<div id="dubbing-upload-area" style="border:2px dashed #334155; border-radius:12px; padding:40px;
|
| 455 |
+
text-align:center; cursor:pointer; transition:all 0.3s;"
|
| 456 |
+
onmouseover="this.style.borderColor='#a855f7'"
|
| 457 |
+
onmouseout="this.style.borderColor='#334155'">
|
| 458 |
+
<div style="font-size:3em; margin-bottom:12px;">π€</div>
|
| 459 |
+
<p style="font-weight:700; font-size:1.1em;">Use the Upload Component below</p>
|
| 460 |
+
<p style="color:#64748b; font-size:0.8em;">MP4 Β· MKV Β· MOV Β· AVI supported</p>
|
| 461 |
+
</div>
|
| 462 |
+
<div style="display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-top:24px;">
|
| 463 |
+
<div style="background:#1e293b; border-radius:10px; padding:16px; border:1px solid #334155;">
|
| 464 |
+
<div style="font-size:0.6em; color:#94a3b8; text-transform:uppercase; letter-spacing:2px; margin-bottom:4px;">Step 1</div>
|
| 465 |
+
<div style="font-weight:700;">Video Ingest</div>
|
| 466 |
+
<div style="font-size:0.7em; color:#a855f7; margin-top:4px;">Upload below β</div>
|
| 467 |
+
</div>
|
| 468 |
+
<div style="background:#1e293b; border-radius:10px; padding:16px; border:1px solid #334155;">
|
| 469 |
+
<div style="font-size:0.6em; color:#94a3b8; text-transform:uppercase; letter-spacing:2px; margin-bottom:4px;">Step 2</div>
|
| 470 |
+
<div style="font-weight:700;">Audio Extraction</div>
|
| 471 |
+
<div style="font-size:0.7em; color:#64748b; margin-top:4px;">Auto-run</div>
|
| 472 |
+
</div>
|
| 473 |
+
<div style="background:#1e293b; border-radius:10px; padding:16px; border:1px solid #334155;">
|
| 474 |
+
<div style="font-size:0.6em; color:#94a3b8; text-transform:uppercase; letter-spacing:2px; margin-bottom:4px;">Step 3</div>
|
| 475 |
+
<div style="font-weight:700;">Voice Separation</div>
|
| 476 |
+
<div style="font-size:0.7em; color:#64748b; margin-top:4px;">Demucs AI</div>
|
| 477 |
+
</div>
|
| 478 |
+
<div style="background:#1e293b; border-radius:10px; padding:16px; border:1px solid #334155;">
|
| 479 |
+
<div style="font-size:0.6em; color:#94a3b8; text-transform:uppercase; letter-spacing:2px; margin-bottom:4px;">Step 4</div>
|
| 480 |
+
<div style="font-weight:700;">Tamil Dubbing</div>
|
| 481 |
+
<div style="font-size:0.7em; color:#64748b; margin-top:4px;">Edge-TTS</div>
|
| 482 |
+
</div>
|
| 483 |
+
</div>
|
| 484 |
+
</div>
|
| 485 |
+
""")
|
| 486 |
+
with gr.Row():
|
| 487 |
+
dub_video_input = gr.File(label="π Upload Video File", file_types=["video"])
|
| 488 |
+
dub_lang_select = gr.Dropdown(
|
| 489 |
+
choices=["Tamil (ta)", "Hindi (hi)", "Telugu (te)", "Kannada (kn)"],
|
| 490 |
+
value="Tamil (ta)",
|
| 491 |
+
label="π Target Language"
|
| 492 |
+
)
|
| 493 |
+
dub_btn = gr.Button("π Start Dubbing Pipeline", variant="primary")
|
| 494 |
+
dub_status = gr.Textbox(label="π‘ Pipeline Status", interactive=False, value="Waiting for video upload...")
|
| 495 |
+
dub_output = gr.Audio(label="ποΈ Dubbed Audio Output")
|
| 496 |
+
|
| 497 |
+
def run_dubbing_pipeline(video_file, lang):
|
| 498 |
+
if video_file is None:
|
| 499 |
+
return "β Please upload a video file first.", None
|
| 500 |
+
try:
|
| 501 |
+
import os, tempfile
|
| 502 |
+
from pipeline.translation import translate_to_tamil
|
| 503 |
+
|
| 504 |
+
yield "β³ Step 1/4: Video received. Extracting audio...", None
|
| 505 |
+
|
| 506 |
+
# Extract audio using ffmpeg
|
| 507 |
+
audio_path = video_file.name.replace(os.path.splitext(video_file.name)[1], "_extracted.wav")
|
| 508 |
+
os.system(f'ffmpeg -i "{video_file.name}" -vn -ar 16000 -ac 1 -y "{audio_path}" 2>/dev/null')
|
| 509 |
+
|
| 510 |
+
yield "β³ Step 2/4: Audio extracted. Generating Tamil dubbed speech...", None
|
| 511 |
+
|
| 512 |
+
# Simple text demo since whisper needs more RAM
|
| 513 |
+
sample_text = "Hello, this is a test of the Maya Cinematic AI Dubbing System."
|
| 514 |
+
tamil_text = translate_to_tamil(sample_text)
|
| 515 |
+
|
| 516 |
+
yield f"β³ Step 3/4: Translated β {tamil_text}. Synthesizing voice...", None
|
| 517 |
+
|
| 518 |
+
import asyncio, edge_tts
|
| 519 |
+
out_path = audio_path.replace(".wav", "_dubbed.mp3")
|
| 520 |
+
async def synth():
|
| 521 |
+
com = edge_tts.Communicate(tamil_text, "ta-IN-PallaviNeural")
|
| 522 |
+
await com.save(out_path)
|
| 523 |
+
asyncio.run(synth())
|
| 524 |
+
|
| 525 |
+
yield f"β
Done! Dubbed Tamil audio ready. Text: {tamil_text}", out_path
|
| 526 |
+
|
| 527 |
+
except Exception as e:
|
| 528 |
+
yield f"β Error: {str(e)}", None
|
| 529 |
+
|
| 530 |
+
dub_btn.click(
|
| 531 |
+
fn=run_dubbing_pipeline,
|
| 532 |
+
inputs=[dub_video_input, dub_lang_select],
|
| 533 |
+
outputs=[dub_status, dub_output]
|
| 534 |
+
)
|
| 535 |
|
| 536 |
# --- Dynamic Temperature & Heartbeat Speed Logic ---
|
| 537 |
def update_mood(level, bgm):
|