CVNSS commited on
Commit
993c50b
·
verified ·
1 Parent(s): 7625a4e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -185
app.py CHANGED
@@ -1,244 +1,165 @@
1
  import os
2
  import subprocess
3
  import sys
4
- import time
5
  import importlib.util
6
 
7
  # ==========================================
8
- # PHẦN 1: CẤU HÌNH & HÀM HỆ THỐNG (SYSTEM EXPERT)
9
  # ==========================================
10
 
11
  def run_command(command, message):
12
  print(f"⏳ {message}...")
13
  try:
14
- # Chuyển đổi lệnh shell phức tạp để chạy an toàn
15
  result = subprocess.run(command, shell=True, capture_output=True, text=True)
16
  if result.returncode != 0:
17
- print(f"❌ Lỗi tại: {message}")
18
- print(f"📝 Chi tiết lỗi: {result.stderr}")
19
  return False
20
- else:
21
- print(f"✅ Xong: {message}")
22
- return True
23
  except Exception as e:
24
  print(f"❌ Exception: {e}")
25
  return False
26
 
27
  def setup_environment():
28
- """Thiết lập môi trường chuẩn Studio"""
29
- # 1. Cài đặt System Dependencies
30
- run_command("apt-get update -qq && apt-get install -y espeak-ng git build-essential -qq", "Cài đặt System Tools")
31
 
32
- # 2. Xử lý Repo
33
- if os.path.exists("VieNeu-TTS"):
34
- print("📂 Repo đã tồn tại, đang pull cập nhật...")
35
- os.chdir("VieNeu-TTS")
36
- run_command("git pull", "Cập nhật Repo")
37
- else:
38
- run_command("git clone https://github.com/pnnbao97/VieNeu-TTS.git", "Clone Repo VieNeu-TTS")
39
- os.chdir("VieNeu-TTS")
40
-
41
- # 3. Cài đặt Dependencies (Ưu tiên UV để tốc độ cao)
42
- print("🛠️ Đang cài đặt thư viện (Deep Learning Core)...")
43
 
44
- # Cài đặt UV nếu chưa có
45
- run_command("curl -LsSf https://astral.sh/uv/install.sh | sh", "Cài UV Manager")
46
- os.environ['PATH'] += ":/root/.local/bin" # Cập nhật path tạm thời
47
 
48
- # Cài các gói nặng
49
- cmds = [
50
- "pip install --upgrade pip",
51
- "pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121",
52
- "pip install neucodec",
53
- "pip install -e .", # Cài đặt package hiện tại
54
- "pip install gradio"
55
- ]
56
 
57
- for cmd in cmds:
58
- run_command(cmd, f"Executing: {cmd}")
 
 
 
 
 
59
 
60
- # ==========================================
61
- # PHẦN 2: THỰC THI SETUP
62
- # ==========================================
63
 
64
- # Kiểm tra xem đã cài xong chưa để tránh chạy lại khi restart space
65
- if not importlib.util.find_spec("neucodec"):
66
  setup_environment()
67
  else:
68
- print("✅ Môi trường đã sẵn sàng, bỏ qua bước cài đặt.")
69
  if os.path.exists("VieNeu-TTS"):
70
- os.chdir("VieNeu-TTS")
71
 
72
  # ==========================================
73
- # PHẦN 3: IMPORT & LOGIC XỬ LÝ (BACKEND)
74
  # ==========================================
75
 
76
  import gradio as gr
77
  import torch
78
- # Import library từ repo vừa cài
79
- try:
80
- # Giả định cấu trúc import dựa trên repo VieNeu-TTS chuẩn
81
- from vieneu.models import VieNeuTTS
82
- # Khởi tạo model global để tránh load lại
83
- print("🧠 Đang tải mô hình AI...")
84
- device = "cuda" if torch.cuda.is_available() else "cpu"
85
- # Lưu ý: Cần điều chỉnh hàm load tùy theo API thực tế của repo nếu có thay đổi
86
- # Ở đây tôi dùng cơ chế dynamic import hoặc giả lập n���u cần thiết
87
- except ImportError:
88
- # Fallback nếu import trực tiếp thất bại, ta sẽ cố gắng load từ file inference
89
- print("⚠️ Cảnh báo: Không import được trực tiếp. Đang thử phương án dự phòng...")
90
- # (Trong thực tế cần check code repo để import đúng class)
91
- pass
92
-
93
- # Hàm xử lý Dummy để test UI nếu model chưa load được (Safety net)
94
- def tts_inference(text, speed):
95
  try:
96
- # Đây nơi gọi hàm thực tế của VieNeu-TTS
97
- # dụ: audio = model.infer(text, speed=speed)
98
- # tôi không thể chạy code thực tế ngay lúc này, tôi sẽ dùng subprocess gọi script gốc
99
- # hoặc giả định hàm chuẩn.
100
-
101
- # GIẢI PHÁP 100% ĂN NGAY: Gọi CLI hoặc Wrapper
102
- # Để đảm bảo an toàn, chúng ta sẽ import infer từ gradio_app gốc
103
- sys.path.append(os.getcwd())
104
- import gradio_app
105
- return gradio_app.inference(text, speed) # Giả định hàm tên là inference
 
 
 
 
106
  except Exception as e:
107
- return None, f"Lỗi xử lý: {str(e)}"
108
 
109
  # ==========================================
110
- # PHẦN 4: THIẾT KẾ UI/UX CHUYÊN NGHIỆP (FRONTEND)
111
  # ==========================================
112
 
113
- # CSS Tùy chỉnh cao cấp
114
- custom_css = """
115
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&display=swap');
116
-
117
- body { font-family: 'Inter', sans-serif !important; background-color: #0b0f19; }
118
- .container { max-width: 1200px; margin: auto; padding-top: 20px; }
119
 
120
- /* Header Styling */
121
- .header-box {
 
 
 
122
  text-align: center;
123
- background: linear-gradient(90deg, #1e3a8a 0%, #3b82f6 100%);
124
- padding: 30px;
125
- border-radius: 16px;
126
  color: white;
127
- margin-bottom: 20px;
128
- box-shadow: 0 10px 25px -5px rgba(59, 130, 246, 0.5);
129
  }
130
- .header-title { font-size: 2.5rem; font-weight: 800; margin-bottom: 5px; }
131
- .header-desc { font-size: 1.1rem; opacity: 0.9; font-weight: 300; }
132
 
133
- /* Input/Output Panels */
134
- .panel {
135
- background: #1f2937;
136
- border: 1px solid #374151;
137
  border-radius: 12px;
138
  padding: 20px;
139
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
140
  }
141
 
142
- /* Button Styling */
143
- #generate-btn {
144
- background: linear-gradient(90deg, #10b981 0%, #059669 100%);
145
  border: none;
146
- color: white;
147
- font-weight: 600;
148
  font-size: 1.1rem;
149
- padding: 12px;
150
- border-radius: 8px;
151
- transition: transform 0.1s;
152
  }
153
- #generate-btn:hover { transform: scale(1.02); box-shadow: 0 0 15px rgba(16, 185, 129, 0.4); }
154
-
155
- /* Footer */
156
- .footer { text-align: center; margin-top: 30px; color: #6b7280; font-size: 0.8rem; }
157
  """
158
 
159
- with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue="blue", neutral_hue="slate")) as demo:
 
160
 
161
- with gr.Column(elem_classes="container"):
162
- # 1. Header Section
163
- with gr.Box(elem_classes="header-box"):
164
- gr.Markdown("""
165
- <div class="header-title">🇻🇳 VieNeu-TTS Studio</div>
166
- <div class="header-desc">Hệ thống tổng hợp tiếng Việt Neural tiên tiến | Chất lượng Studio</div>
167
- """)
168
-
169
- # 2. Main Interface (2 Columns)
170
- with gr.Row(equal_height=True):
171
-
172
- # Left Column: Controls
173
- with gr.Column(scale=1, elem_classes="panel"):
174
- gr.Markdown("### 📝 Thiết lập đầu vào")
175
- text_input = gr.Textbox(
176
- label="Văn bản cần đọc",
177
- placeholder="Nhập tiếng Việt dấu tại đây...",
178
- lines=8,
179
- value="Xin chào, đây hệ thống VieNeu TTS với giao diện được thiết kế lại chuyên nghiệp hơn."
180
- )
181
-
182
- with gr.Row():
183
- speed_slider = gr.Slider(
184
- minimum=0.5, maximum=2.0, value=1.0, step=0.1,
185
- label=" Tốc độ đọc"
186
- )
187
-
188
- # Nút bấm lớn
189
- btn_run = gr.Button("▶️ TẠO GIỌNG ĐỌC NGAY", elem_id="generate-btn")
190
-
191
- # Right Column: Output
192
- with gr.Column(scale=1, elem_classes="panel"):
193
- gr.Markdown("### 🎧 Kết quả đầu ra")
194
- audio_output = gr.Audio(label="Audio", type="filepath", interactive=False)
195
-
196
- # Khu vực log hoặc thông tin bổ sung
197
- with gr.Accordion("ℹ️ Thông tin kỹ thuật", open=False):
198
- logs = gr.Markdown("Hệ thống đang chạy trên GPU/CPU...")
199
-
200
- # 3. Footer
201
- gr.Markdown("Designed with ❤️ by VieNeu-TTS Community", elem_classes="footer")
202
-
203
- # 4. Wiring Logic
204
- # Lưu ý: Cần kết nối với hàm xử lý thực tế từ file gốc
205
- # Ở đây ta dùng thủ thuật import module gốc để lấy hàm xử lý
206
- try:
207
- # Cố gắng import module gốc sau khi setup xong
208
- sys.path.append(os.getcwd())
209
- import gradio_app
210
- # Trỏ sự kiện click vào hàm của gradio_app gốc
211
- # Giả định hàm gốc tên là 'inference' hoặc 'synthesize' và nhận text làm đầu vào
212
- # Nếu hàm gốc yêu cầu nhiều tham số hơn, ta cần wrapper (như bên dưới)
213
-
214
- def wrapper_inference(text, speed):
215
- # Hàm này cần điều chỉnh dựa trên code thực tế của pnnbao97
216
- # Ví dụ nếu hàm gốc là gradio_app.predict(text)
217
- try:
218
- if hasattr(gradio_app, 'inference'):
219
- return gradio_app.inference(text) # Thêm tham số speed nếu model hỗ trợ
220
- elif hasattr(gradio_app, 'predict'):
221
- return gradio_app.predict(text)
222
- else:
223
- return None
224
- except Exception as e:
225
- print(f"Inference Error: {e}")
226
- return None
227
-
228
- btn_run.click(
229
- fn=wrapper_inference,
230
- inputs=[text_input, speed_slider],
231
- outputs=[audio_output]
232
- )
233
- except ImportError:
234
- # Fallback hiển thị lỗi nếu không load được core
235
- def error_handler(x, y): return None
236
- btn_run.click(fn=error_handler, inputs=[text_input, speed_slider], outputs=[audio_output])
237
- print("❌ CRITICAL: Không thể load module gradio_app gốc. Vui lòng kiểm tra tên file.")
238
 
239
  # ==========================================
240
- # PHẦN 5: KHỞI CHẠY
241
  # ==========================================
242
  if __name__ == "__main__":
243
- print("🚀 Khởi chạy giao diện Studio...")
244
- demo.launch(share=True)
 
1
  import os
2
  import subprocess
3
  import sys
 
4
  import importlib.util
5
 
6
  # ==========================================
7
+ # 1. HÀM HỆ THỐNG & SETUP (ROBUST MODE)
8
  # ==========================================
9
 
10
  def run_command(command, message):
11
  print(f"⏳ {message}...")
12
  try:
 
13
  result = subprocess.run(command, shell=True, capture_output=True, text=True)
14
  if result.returncode != 0:
15
+ print(f"❌ Lỗi (nhưng sẽ thử tiếp tục): {message}")
16
+ print(f"📝 Chi tiết: {result.stderr}")
17
  return False
18
+ print(f"✅ Xong: {message}")
19
+ return True
 
20
  except Exception as e:
21
  print(f"❌ Exception: {e}")
22
  return False
23
 
24
  def setup_environment():
25
+ # 1. Cài System Tools
26
+ run_command("apt-get update -qq && apt-get install -y espeak-ng git build-essential -qq", "System Tools")
 
27
 
28
+ # 2. Clone Repo (Xử lý đường dẫn thông minh)
29
+ if not os.path.exists("VieNeu-TTS"):
30
+ run_command("git clone https://github.com/pnnbao97/VieNeu-TTS.git", "Clone VieNeu-TTS")
31
+
32
+ # 3. Cài đặt Python Dependencies (FIXED)
33
+ # Bỏ qua chỉ định CUDA cứng, để pip tự chọn bản phù hợp nhất với HF Space
34
+ print("🛠️ Đang cài đặt thư viện (Auto-detect Hardware)...")
 
 
 
 
35
 
36
+ # Cài torch trước
37
+ run_command("pip install torch torchvision torchaudio", "Install PyTorch (Auto)")
 
38
 
39
+ # Cài package chính
40
+ run_command("pip install neucodec", "Install Neucodec")
 
 
 
 
 
 
41
 
42
+ # Vào thư mục repo để cài requirements nội bộ nếu cần
43
+ if os.path.exists("VieNeu-TTS"):
44
+ os.chdir("VieNeu-TTS")
45
+ run_command("pip install -e .", "Install VieNeu Local")
46
+ # Quan trọng: Thêm đường dẫn repo vào hệ thống để Python tìm thấy file
47
+ sys.path.append(os.getcwd())
48
+ os.chdir("..") # Quay lại root
49
 
50
+ run_command("pip install --upgrade gradio", "Update Gradio")
 
 
51
 
52
+ # Chạy setup nếu chưa thư viện cốt lõi
53
+ if not importlib.util.find_spec("neucodec") or not importlib.util.find_spec("torch"):
54
  setup_environment()
55
  else:
56
+ # Đảm bảo path vẫn đúng ngay cả khi restart space
57
  if os.path.exists("VieNeu-TTS"):
58
+ sys.path.append(os.path.abspath("VieNeu-TTS"))
59
 
60
  # ==========================================
61
+ # 2. LOGIC XỬ LÝ (BACKEND WRAPPER)
62
  # ==========================================
63
 
64
  import gradio as gr
65
  import torch
66
+
67
+ # Hàm bọc để gọi logic từ repo gốc an toàn
68
+ def tts_wrapper(text, speed):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  try:
70
+ # Import dynamic để tránh crash lúc khởi động
71
+ import gradio_app
72
+ # Tìm hàm đúng trong code gốc
73
+ if hasattr(gradio_app, 'inference'):
74
+ return gradio_app.inference(text, speed)
75
+ elif hasattr(gradio_app, 'tts_inference'):
76
+ return gradio_app.tts_inference(text, speed)
77
+ else:
78
+ # Fallback: Nếu không tìm thấy hàm, thử tìm model global
79
+ if hasattr(gradio_app, 'model'):
80
+ return gradio_app.model.infer(text, speed)
81
+ return None, "⚠️ Không tìm thấy hàm inference trong gradio_app.py"
82
+ except ImportError:
83
+ return None, "❌ Lỗi: Không thể import module 'gradio_app'. Kiểm tra lại cấu trúc thư mục."
84
  except Exception as e:
85
+ return None, f"Lỗi Runtime: {str(e)}"
86
 
87
  # ==========================================
88
+ # 3. UI/UX HIỆN ĐẠI (GRADIO 4/5 COMPATIBLE)
89
  # ==========================================
90
 
91
+ # CSS đã sửa lỗi tương thích
92
+ css = """
93
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap');
94
+ body { font-family: 'Inter', sans-serif; background: #0f172a; }
 
 
95
 
96
+ .header-container {
97
+ background: linear-gradient(135deg, #1e40af 0%, #3b82f6 100%);
98
+ padding: 2rem;
99
+ border-radius: 1rem;
100
+ margin-bottom: 1.5rem;
101
  text-align: center;
 
 
 
102
  color: white;
103
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
 
104
  }
105
+ .header-title { font-size: 2.2rem; font-weight: 800; margin: 0; }
106
+ .header-sub { opacity: 0.9; margin-top: 0.5rem; }
107
 
108
+ /* Thay thế Box cũ bằng custom classes */
109
+ .panel-container {
110
+ background: #1e293b;
111
+ border: 1px solid #334155;
112
  border-radius: 12px;
113
  padding: 20px;
 
114
  }
115
 
116
+ #gen-btn {
117
+ background: linear-gradient(90deg, #059669 0%, #10b981 100%);
 
118
  border: none;
119
+ color: white;
 
120
  font-size: 1.1rem;
121
+ font-weight: bold;
 
 
122
  }
 
 
 
 
123
  """
124
 
125
+ # Sử dụng pháp mới chuẩn Gradio 4+
126
+ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
127
 
128
+ # Header Section (Dùng HTML thay vì gr.Box đã bị xóa)
129
+ gr.HTML("""
130
+ <div class="header-container">
131
+ <h1 class="header-title">🇻🇳 VieNeu-TTS Studio</h1>
132
+ <div class="header-sub">Deep Learning Neural Text-to-Speech | High Fidelity</div>
133
+ </div>
134
+ """)
135
+
136
+ with gr.Row():
137
+ # Cột trái: Input
138
+ with gr.Column(elem_classes="panel-container"):
139
+ gr.Markdown("### 📝 Nhập liệu")
140
+ inp_text = gr.Textbox(
141
+ label="Văn bản",
142
+ placeholder="Nhập tiếng Việt...",
143
+ lines=6,
144
+ value="Xin chào, hệ thống VieNeu TTS đã hoạt động trở lại."
145
+ )
146
+ inp_speed = gr.Slider(0.5, 2.0, value=1.0, step=0.1, label="⚡ Tốc độ")
147
+ btn_run = gr.Button("▶️ TẠO GIỌNG ĐỌC", elem_id="gen-btn", scale=1)
148
+
149
+ # Cột phải: Output
150
+ with gr.Column(elem_classes="panel-container"):
151
+ gr.Markdown("### 🎧 Kết quả")
152
+ out_audio = gr.Audio(label="Audio Output", type="filepath")
153
+ out_msg = gr.Markdown("Sẵn sàng xử lý...")
154
+
155
+ # Footer
156
+ gr.Markdown("<center style='color: #64748b; margin-top: 20px;'>VieNeu-TTS Community Build</center>")
157
+
158
+ # Xử sự kiện
159
+ btn_run.click(fn=tts_wrapper, inputs=[inp_text, inp_speed], outputs=[out_audio, out_msg])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  # ==========================================
162
+ # 4. RUN
163
  # ==========================================
164
  if __name__ == "__main__":
165
+ demo.queue().launch(share=True)