import os import sys import gradio as gr import logging # Thêm thư mục src vào path để import vieneu sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "src"))) from vieneu import Vieneu # Cấu hình logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger("VieNeu-App") # Khởi tạo mô hình (Mặc định chạy CPU) logger.info("Đang khởi tạo mô hình VieNeu-TTS...") tts = Vieneu() # Lấy danh sách giọng nói voices = tts.list_preset_voices() voice_map = {desc: vid for desc, vid in voices} voice_names = list(voice_map.keys()) def generate_audio(text, voice_name, progress=gr.Progress(track_tqdm=True)): if not text.strip(): return None progress(0, desc="Đang khởi tạo...") logger.info(f"Đang tạo giọng nói cho văn bản: {text[:50]}...") progress(0.1, desc="Đang lấy thông tin giọng nói...") voice_id = voice_map.get(voice_name) voice_data = tts.get_preset_voice(voice_id) # Chia nhỏ văn bản để có tiến trình "thật" from vieneu_utils.core_utils import split_text_into_chunks import numpy as np chunks = split_text_into_chunks(text, max_chars=200) audio_list = [] for i, chunk in enumerate(chunks): # Tính toán % tiến trình thật dựa trên số lượng đoạn current_progress = 0.2 + (i / len(chunks)) * 0.7 progress(current_progress, desc=f"Đang tạo âm thanh (đoạn {i+1}/{len(chunks)})...") # Tạo âm thanh cho từng đoạn wav_chunk = tts.infer(text=chunk, voice=voice_data, skip_normalize=False) audio_list.append(wav_chunk) progress(0.9, desc="Đang đóng gói file âm thanh...") # Ghép các đoạn âm thanh lại audio = np.concatenate(audio_list) # Lưu file tạm output_path = "output.wav" tts.save(audio, output_path) progress(1.0, desc="Hoàn tất!") return output_path # CSS để làm chữ to và giao diện sạch sẽ custom_css = """ .big-text { font-size: 24px !important; } .instruction { font-size: 18px !important; margin-bottom: 10px; } button { font-size: 20px !important; min-height: 60px !important; } textarea { font-size: 20px !important; } .gradio-container { max-width: 800px !important; margin: auto !important; } """ with gr.Blocks(title="VieNeu-TTS Siêu Đơn Giản") as demo: gr.Markdown("# 🦜 VieNeu-TTS - Chuyển văn bản thành giọng nói", elem_classes=["big-text"]) with gr.Row(): with gr.Column(): gr.Markdown("### 1. Nhập chữ vào đây:", elem_classes=["instruction"]) input_text = gr.Textbox( label="", placeholder="Ví dụ: Chào bạn, hôm nay bạn thấy thế nào?", lines=5 ) gr.Markdown("### 2. Chọn giọng nói:", elem_classes=["instruction"]) voice_select = gr.Dropdown( choices=voice_names, value=voice_names[0] if voice_names else None, label="" ) generate_btn = gr.Button("🚀 NHẤN VÀO ĐÂY ĐỂ TẠO GIỌNG NÓI", variant="primary") with gr.Column(): gr.Markdown("### 3. Nghe và tải xuống:", elem_classes=["instruction"]) output_audio = gr.Audio( label="", type="filepath", interactive=False ) generate_btn.click( fn=generate_audio, inputs=[input_text, voice_select], outputs=output_audio ) if __name__ == "__main__": demo.launch( server_name="0.0.0.0", server_port=7860, css=custom_css, ssr_mode=False )