TTSPro / app.py
CVNSS's picture
Update app.py
993c50b verified
import os
import subprocess
import sys
import importlib.util
# ==========================================
# 1. HÀM HỆ THỐNG & SETUP (ROBUST MODE)
# ==========================================
def run_command(command, message):
print(f"⏳ {message}...")
try:
result = subprocess.run(command, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print(f"❌ Lỗi (nhưng sẽ thử tiếp tục): {message}")
print(f"📝 Chi tiết: {result.stderr}")
return False
print(f"✅ Xong: {message}")
return True
except Exception as e:
print(f"❌ Exception: {e}")
return False
def setup_environment():
# 1. Cài System Tools
run_command("apt-get update -qq && apt-get install -y espeak-ng git build-essential -qq", "System Tools")
# 2. Clone Repo (Xử lý đường dẫn thông minh)
if not os.path.exists("VieNeu-TTS"):
run_command("git clone https://github.com/pnnbao97/VieNeu-TTS.git", "Clone VieNeu-TTS")
# 3. Cài đặt Python Dependencies (FIXED)
# Bỏ qua chỉ định CUDA cứng, để pip tự chọn bản phù hợp nhất với HF Space
print("🛠️ Đang cài đặt thư viện (Auto-detect Hardware)...")
# Cài torch trước
run_command("pip install torch torchvision torchaudio", "Install PyTorch (Auto)")
# Cài package chính
run_command("pip install neucodec", "Install Neucodec")
# Vào thư mục repo để cài requirements nội bộ nếu cần
if os.path.exists("VieNeu-TTS"):
os.chdir("VieNeu-TTS")
run_command("pip install -e .", "Install VieNeu Local")
# Quan trọng: Thêm đường dẫn repo vào hệ thống để Python tìm thấy file
sys.path.append(os.getcwd())
os.chdir("..") # Quay lại root
run_command("pip install --upgrade gradio", "Update Gradio")
# Chạy setup nếu chưa có thư viện cốt lõi
if not importlib.util.find_spec("neucodec") or not importlib.util.find_spec("torch"):
setup_environment()
else:
# Đảm bảo path vẫn đúng ngay cả khi restart space
if os.path.exists("VieNeu-TTS"):
sys.path.append(os.path.abspath("VieNeu-TTS"))
# ==========================================
# 2. LOGIC XỬ LÝ (BACKEND WRAPPER)
# ==========================================
import gradio as gr
import torch
# Hàm bọc để gọi logic từ repo gốc an toàn
def tts_wrapper(text, speed):
try:
# Import dynamic để tránh crash lúc khởi động
import gradio_app
# Tìm hàm đúng trong code gốc
if hasattr(gradio_app, 'inference'):
return gradio_app.inference(text, speed)
elif hasattr(gradio_app, 'tts_inference'):
return gradio_app.tts_inference(text, speed)
else:
# Fallback: Nếu không tìm thấy hàm, thử tìm model global
if hasattr(gradio_app, 'model'):
return gradio_app.model.infer(text, speed)
return None, "⚠️ Không tìm thấy hàm inference trong gradio_app.py"
except ImportError:
return None, "❌ Lỗi: Không thể import module 'gradio_app'. Kiểm tra lại cấu trúc thư mục."
except Exception as e:
return None, f"❌ Lỗi Runtime: {str(e)}"
# ==========================================
# 3. UI/UX HIỆN ĐẠI (GRADIO 4/5 COMPATIBLE)
# ==========================================
# CSS đã sửa lỗi tương thích
css = """
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap');
body { font-family: 'Inter', sans-serif; background: #0f172a; }
.header-container {
background: linear-gradient(135deg, #1e40af 0%, #3b82f6 100%);
padding: 2rem;
border-radius: 1rem;
margin-bottom: 1.5rem;
text-align: center;
color: white;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.header-title { font-size: 2.2rem; font-weight: 800; margin: 0; }
.header-sub { opacity: 0.9; margin-top: 0.5rem; }
/* Thay thế Box cũ bằng custom classes */
.panel-container {
background: #1e293b;
border: 1px solid #334155;
border-radius: 12px;
padding: 20px;
}
#gen-btn {
background: linear-gradient(90deg, #059669 0%, #10b981 100%);
border: none;
color: white;
font-size: 1.1rem;
font-weight: bold;
}
"""
# Sử dụng cú pháp mới chuẩn Gradio 4+
with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
# Header Section (Dùng HTML thay vì gr.Box đã bị xóa)
gr.HTML("""
<div class="header-container">
<h1 class="header-title">🇻🇳 VieNeu-TTS Studio</h1>
<div class="header-sub">Deep Learning Neural Text-to-Speech | High Fidelity</div>
</div>
""")
with gr.Row():
# Cột trái: Input
with gr.Column(elem_classes="panel-container"):
gr.Markdown("### 📝 Nhập liệu")
inp_text = gr.Textbox(
label="Văn bản",
placeholder="Nhập tiếng Việt...",
lines=6,
value="Xin chào, hệ thống VieNeu TTS đã hoạt động trở lại."
)
inp_speed = gr.Slider(0.5, 2.0, value=1.0, step=0.1, label="⚡ Tốc độ")
btn_run = gr.Button("▶️ TẠO GIỌNG ĐỌC", elem_id="gen-btn", scale=1)
# Cột phải: Output
with gr.Column(elem_classes="panel-container"):
gr.Markdown("### 🎧 Kết quả")
out_audio = gr.Audio(label="Audio Output", type="filepath")
out_msg = gr.Markdown("Sẵn sàng xử lý...")
# Footer
gr.Markdown("<center style='color: #64748b; margin-top: 20px;'>VieNeu-TTS Community Build</center>")
# Xử lý sự kiện
btn_run.click(fn=tts_wrapper, inputs=[inp_text, inp_speed], outputs=[out_audio, out_msg])
# ==========================================
# 4. RUN
# ==========================================
if __name__ == "__main__":
demo.queue().launch(share=True)