Spaces:
Running on Zero
Running on Zero
Mobile fix v2: strict single-column layout, forced overflow clamp
Browse filesDrops the two-column layout entirely so nothing renders side-by-side, stacks the advanced settings row on phones, and hard-clamps horizontal overflow with min-width 0 on all blocks.
app.py
CHANGED
|
@@ -435,6 +435,9 @@ def _refresh_quota(request: gr.Request):
|
|
| 435 |
|
| 436 |
CUSTOM_CSS = """
|
| 437 |
.gradio-container {max-width: 1180px !important; margin: 0 auto !important;}
|
|
|
|
|
|
|
|
|
|
| 438 |
#hero {
|
| 439 |
background: linear-gradient(120deg, #4f46e5 0%, #7c3aed 45%, #db2777 100%);
|
| 440 |
border-radius: 18px; padding: 26px 30px; margin-bottom: 8px;
|
|
@@ -475,12 +478,10 @@ body {overflow-x: hidden;}
|
|
| 475 |
#hero {padding: 16px 14px; border-radius: 14px;}
|
| 476 |
#hero h1 {font-size: 1.3rem;}
|
| 477 |
#hero p {font-size: 0.82rem;}
|
| 478 |
-
#main-row {flex-direction: column !important;}
|
| 479 |
#adv-row {flex-direction: column !important;}
|
| 480 |
#voice-btns {flex-wrap: wrap !important; gap: 8px !important;}
|
| 481 |
#voice-btns button {flex: 1 1 45% !important; min-width: 0 !important;}
|
| 482 |
.gradio-container {padding: 8px !important;}
|
| 483 |
-
.block, .form, .wrap, .gap {min-width: 0 !important; max-width: 100% !important;}
|
| 484 |
.quota-row {flex-direction: column; gap: 1px;}
|
| 485 |
#generate-btn {height: 46px !important; font-size: 0.95rem !important;}
|
| 486 |
}
|
|
@@ -509,40 +510,37 @@ TIPS_MD = """
|
|
| 509 |
with gr.Blocks(title="Offex Voice Studio β AI Voice Cloning", theme=gr.themes.Soft(primary_hue="indigo", neutral_hue="slate"), css=CUSTOM_CSS) as demo:
|
| 510 |
gr.HTML(HEADER_HTML)
|
| 511 |
|
| 512 |
-
|
| 513 |
-
|
| 514 |
-
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
|
| 521 |
-
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
gr.Button(label, size="sm").click(
|
| 525 |
-
fn=lambda p=path: p, outputs=reference_audio
|
| 526 |
-
)
|
| 527 |
-
with gr.Accordion("π Emotion reference (optional β big boost)", open=False):
|
| 528 |
-
emotion_audio = gr.Audio(
|
| 529 |
-
label="Emotion reference",
|
| 530 |
-
sources=["upload", "microphone"],
|
| 531 |
-
type="filepath",
|
| 532 |
)
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
| 545 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 546 |
|
| 547 |
with gr.Accordion("βοΈ Advanced settings", open=False):
|
| 548 |
with gr.Row(elem_id="adv-row"):
|
|
|
|
| 435 |
|
| 436 |
CUSTOM_CSS = """
|
| 437 |
.gradio-container {max-width: 1180px !important; margin: 0 auto !important;}
|
| 438 |
+
html, body {overflow-x: hidden !important; max-width: 100vw !important;}
|
| 439 |
+
.gradio-container .block, .gradio-container .form, .gradio-container .wrap,
|
| 440 |
+
.gradio-container .gap, .gradio-container .form-row, .gradio-container .component-wrapper {min-width: 0 !important; max-width: 100% !important;}
|
| 441 |
#hero {
|
| 442 |
background: linear-gradient(120deg, #4f46e5 0%, #7c3aed 45%, #db2777 100%);
|
| 443 |
border-radius: 18px; padding: 26px 30px; margin-bottom: 8px;
|
|
|
|
| 478 |
#hero {padding: 16px 14px; border-radius: 14px;}
|
| 479 |
#hero h1 {font-size: 1.3rem;}
|
| 480 |
#hero p {font-size: 0.82rem;}
|
|
|
|
| 481 |
#adv-row {flex-direction: column !important;}
|
| 482 |
#voice-btns {flex-wrap: wrap !important; gap: 8px !important;}
|
| 483 |
#voice-btns button {flex: 1 1 45% !important; min-width: 0 !important;}
|
| 484 |
.gradio-container {padding: 8px !important;}
|
|
|
|
| 485 |
.quota-row {flex-direction: column; gap: 1px;}
|
| 486 |
#generate-btn {height: 46px !important; font-size: 0.95rem !important;}
|
| 487 |
}
|
|
|
|
| 510 |
with gr.Blocks(title="Offex Voice Studio β AI Voice Cloning", theme=gr.themes.Soft(primary_hue="indigo", neutral_hue="slate"), css=CUSTOM_CSS) as demo:
|
| 511 |
gr.HTML(HEADER_HTML)
|
| 512 |
|
| 513 |
+
reference_audio = gr.Audio(
|
| 514 |
+
label="Reference voice",
|
| 515 |
+
sources=["upload", "microphone"],
|
| 516 |
+
type="filepath",
|
| 517 |
+
value=DEFAULT_VOICE,
|
| 518 |
+
)
|
| 519 |
+
if MY_VOICES:
|
| 520 |
+
gr.Markdown("**β‘ Quick-pick β no upload needed:**")
|
| 521 |
+
with gr.Row(elem_id="voice-btns"):
|
| 522 |
+
for label, path in MY_VOICES:
|
| 523 |
+
gr.Button(label, size="sm").click(
|
| 524 |
+
fn=lambda p=path: p, outputs=reference_audio
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 525 |
)
|
| 526 |
+
with gr.Accordion("π Emotion reference (optional β big boost)", open=False):
|
| 527 |
+
emotion_audio = gr.Audio(
|
| 528 |
+
label="Emotion reference",
|
| 529 |
+
sources=["upload", "microphone"],
|
| 530 |
+
type="filepath",
|
| 531 |
+
)
|
| 532 |
+
text = gr.Textbox(
|
| 533 |
+
label="Text to speak",
|
| 534 |
+
placeholder="Type the text you want in the cloned voice...",
|
| 535 |
+
lines=5,
|
| 536 |
+
max_lines=12,
|
| 537 |
+
)
|
| 538 |
+
permission = gr.Checkbox(
|
| 539 |
+
label="β
I have permission to use this voice",
|
| 540 |
+
value=False,
|
| 541 |
+
)
|
| 542 |
+
generate = gr.Button("β¨ Generate Voice", variant="primary", size="lg", elem_id="generate-btn")
|
| 543 |
+
output = gr.Audio(label="π Generated voice", type="filepath", autoplay=True, show_download_button=True)
|
| 544 |
|
| 545 |
with gr.Accordion("βοΈ Advanced settings", open=False):
|
| 546 |
with gr.Row(elem_id="adv-row"):
|