Update app.py
Browse files
app.py
CHANGED
|
@@ -14,6 +14,7 @@ import re
|
|
| 14 |
import time
|
| 15 |
|
| 16 |
import numpy as np
|
|
|
|
| 17 |
import gradio as gr
|
| 18 |
import spaces
|
| 19 |
|
|
@@ -73,6 +74,26 @@ def _gpu_duration(text, *args, **kwargs):
|
|
| 73 |
return int(min(180, 30 + n // 8))
|
| 74 |
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
# ── Single-speaker synthesis ──────────────────────────────────────────────────
|
| 77 |
@spaces.GPU(duration=_gpu_duration)
|
| 78 |
def synthesize(text, voice, ref_audio, temperature, top_k, top_p,
|
|
@@ -195,14 +216,22 @@ with gr.Blocks(theme=theme, title="VieNeu-TTS v3 Turbo") as demo:
|
|
| 195 |
label="Chọn giọng", choices=VOICE_CHOICES, value=DEFAULT_VOICE,
|
| 196 |
)
|
| 197 |
with gr.Tab("Nhân bản giọng"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
ref_audio_in = gr.Audio(
|
| 199 |
label="Audio mẫu (3–5 giây)", type="filepath",
|
| 200 |
sources=["upload", "microphone"],
|
| 201 |
)
|
|
|
|
| 202 |
gr.Markdown(
|
| 203 |
"_Có audio mẫu ở đây sẽ **ghi đè** giọng dựng sẵn. "
|
| 204 |
"Xoá audio để quay lại giọng dựng sẵn._"
|
| 205 |
)
|
|
|
|
| 206 |
with gr.Accordion("Tuỳ chọn nâng cao", open=False):
|
| 207 |
with gr.Row():
|
| 208 |
temperature_in = gr.Slider(0.1, 1.5, value=0.8, step=0.05, label="temperature")
|
|
|
|
| 14 |
import time
|
| 15 |
|
| 16 |
import numpy as np
|
| 17 |
+
import soundfile as sf
|
| 18 |
import gradio as gr
|
| 19 |
import spaces
|
| 20 |
|
|
|
|
| 74 |
return int(min(180, 30 + n // 8))
|
| 75 |
|
| 76 |
|
| 77 |
+
def _check_ref_len(path):
|
| 78 |
+
"""Warn when the reference clip is longer than the ideal 3–5 s window."""
|
| 79 |
+
if not path:
|
| 80 |
+
return gr.update(visible=False)
|
| 81 |
+
try:
|
| 82 |
+
dur = sf.info(path).duration
|
| 83 |
+
except Exception:
|
| 84 |
+
return gr.update(visible=False)
|
| 85 |
+
if dur > 5.5:
|
| 86 |
+
return gr.update(
|
| 87 |
+
visible=True,
|
| 88 |
+
value=(
|
| 89 |
+
f"⚠️ Audio mẫu đang dài **{dur:.1f} giây**. Hãy cắt còn "
|
| 90 |
+
f"**3–5 giây** (một câu nói rõ, ít ồn) để clone giọng tốt nhất — "
|
| 91 |
+
f"audio quá dài thường cho kết quả kém hơn."
|
| 92 |
+
),
|
| 93 |
+
)
|
| 94 |
+
return gr.update(visible=False)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
# ── Single-speaker synthesis ──────────────────────────────────────────────────
|
| 98 |
@spaces.GPU(duration=_gpu_duration)
|
| 99 |
def synthesize(text, voice, ref_audio, temperature, top_k, top_p,
|
|
|
|
| 216 |
label="Chọn giọng", choices=VOICE_CHOICES, value=DEFAULT_VOICE,
|
| 217 |
)
|
| 218 |
with gr.Tab("Nhân bản giọng"):
|
| 219 |
+
gr.Markdown(
|
| 220 |
+
"### ⏱️ Audio mẫu nên dài **3–5 giây**\n"
|
| 221 |
+
"Dùng **một câu nói rõ ràng, ít tiếng ồn**. "
|
| 222 |
+
"**Đừng** tải lên file dài (cả đoạn/cả bài) — audio càng dài "
|
| 223 |
+
"clone càng dễ sai giọng và méo tiếng."
|
| 224 |
+
)
|
| 225 |
ref_audio_in = gr.Audio(
|
| 226 |
label="Audio mẫu (3–5 giây)", type="filepath",
|
| 227 |
sources=["upload", "microphone"],
|
| 228 |
)
|
| 229 |
+
ref_warn = gr.Markdown(visible=False)
|
| 230 |
gr.Markdown(
|
| 231 |
"_Có audio mẫu ở đây sẽ **ghi đè** giọng dựng sẵn. "
|
| 232 |
"Xoá audio để quay lại giọng dựng sẵn._"
|
| 233 |
)
|
| 234 |
+
ref_audio_in.change(_check_ref_len, ref_audio_in, ref_warn)
|
| 235 |
with gr.Accordion("Tuỳ chọn nâng cao", open=False):
|
| 236 |
with gr.Row():
|
| 237 |
temperature_in = gr.Slider(0.1, 1.5, value=0.8, step=0.05, label="temperature")
|