hoanglinhn0 commited on
Commit
227305c
·
1 Parent(s): f69f95d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -88
app.py CHANGED
@@ -4,119 +4,81 @@ import numpy as np
4
  import json
5
  import pysrt
6
  import re
7
- import os
8
  from vinorm import TTSnorm
 
9
  from scipy.io import wavfile
10
 
11
- # --- 1. CẤU HÌNH FILE ---
12
- # Tên file model và config phải khớp chính xác với file bạn đã upload
13
- MODEL_PATH = "model.onnx"
14
- CONFIG_PATH = "config.json"
15
-
16
- # --- 2. LOAD MODEL & CONFIG ---
17
  try:
18
- with open(CONFIG_PATH, "r", encoding="utf-8") as f:
19
  config = json.load(f)
20
- symbols = config.get("symbols", [])
21
- symbol_to_id = {s: i for i, s in enumerate(symbols)}
22
  sample_rate = config.get("audio", {}).get("sample_rate", 22050)
23
- print("✅ Đã tải Config và Symbols thành công.")
24
-
25
- sess = ort.InferenceSession(MODEL_PATH, providers=['CPUExecutionProvider'])
26
- print("✅ Đã tải Model ONNX thành công.")
27
  except Exception as e:
28
- print(f"❌ Lỗi khởi tạo: {e}")
29
 
30
- # --- 3. HÀM XỬ VĂN BẢN ---
31
- def clean_text(text):
32
- # Loại bỏ thẻ HTML trong SRT (<i>, <b>...)
33
  text = re.sub(r'<[^>]*>', '', text)
34
- # Loại bỏ xuống dòng khoảng trắng thừa
35
- text = text.replace('\n', ' ').strip()
36
- # Chuẩn hóa tiếng Việt (số, ngày tháng...)
37
- return TTSnorm(text)
38
-
39
- def text_to_ids(text):
40
- text = clean_text(text).lower()
41
- ids = []
42
- for char in text:
43
- if char in symbol_to_id:
44
- ids.append(symbol_to_id[char])
45
- elif f" {char} " in symbol_to_id:
46
- ids.append(symbol_to_id[f" {char} "])
47
- return ids if ids else [1]
48
 
49
- # --- 4. HÀM CHUYỂN SRT SANG AUDIO ---
50
- def process_srt(srt_file, speed, noise, noise_w):
 
51
  try:
52
- if srt_file is None:
53
- return "Vui lòng chọn file SRT!", None
54
-
55
- # Đọc file phụ đề
56
  subs = pysrt.open(srt_file.name, encoding='utf-8')
57
  combined_audio = []
58
 
59
  for sub in subs:
60
- ids = text_to_ids(sub.text)
61
  input_ids = np.array([ids], dtype=np.int64)
62
  input_lens = np.array([len(ids)], dtype=np.int64)
63
-
64
- # Tốc độ mặc định 1.30 truyền vào scales
65
  scales = np.array([noise, noise_w, 1.0/speed], dtype=np.float32)
66
 
67
- # Chạy model ONNX
68
  outputs = sess.run(None, {
69
- "input": input_ids,
70
- "input_lengths": input_lens,
71
- "scales": scales
72
  })
73
 
74
- # Làm phẳng mảng 4D thành 1D (Sửa lỗi im lặng)
75
- audio_segment = outputs[0].flatten().astype(np.float32)
76
- combined_audio.append(audio_segment)
77
-
78
- # Thêm 0.2s im lặng giữa các câu cho tự nhiên
79
- silence = np.zeros(int(sample_rate * 0.2), dtype=np.float32)
80
- combined_audio.append(silence)
81
 
82
- # Ghép tất cả các đoạn audio
83
- final_audio = np.concatenate(combined_audio)
84
-
85
- # Xuất file wav
86
- output_path = "output_srt_voice.wav"
87
- wavfile.write(output_path, sample_rate, final_audio)
88
-
89
- return "Hoàn thành! Bạn có thể nghe hoặc tải audio bên dưới.", output_path
90
  except Exception as e:
91
- return f"Lỗi xử lý: {str(e)}", None
92
-
93
- # --- 5. GIAO DIỆN GRADIO ---
94
- with gr.Blocks(title="SRT to Audio VN") as demo:
95
- gr.Markdown("# 📂 Chuyển đổi SRT sang Audio Tiếng Việt")
96
- gr.Markdown("Hỗ trợ làm sạch văn bản và đặt tốc độ nói tùy chỉnh.")
97
-
98
- with gr.Row():
99
- with gr.Column():
100
- # Thành phần cho phép chọn file từ SD Card trên Android
101
- file_input = gr.File(label="Chọn file .srt từ thiết bị", file_types=[".srt"])
102
-
103
- with gr.Row():
104
- speed_sld = gr.Slider(0.5, 2.0, value=1.30, label="Tốc độ nói (Speed)")
105
- noise_sld = gr.Slider(0.1, 1.0, value=0.667, label="Noise Scale")
106
-
107
- noise_w_sld = gr.Slider(0.1, 1.0, value=0.8, label="Noise W")
108
- btn = gr.Button("🚀 Bắt đầu chuyển đổi", variant="primary")
109
-
110
- with gr.Column():
111
- status = gr.Textbox(label="Trạng thái hệ thống")
112
- audio_out = gr.Audio(label="Audio hoàn chỉnh", type="filepath")
113
 
114
- btn.click(
115
- fn=process_srt,
116
- inputs=[file_input, speed_sld, noise_sld, noise_w_sld],
117
- outputs=[status, audio_out]
118
- )
 
 
 
 
 
 
 
119
 
120
  if __name__ == "__main__":
121
- # server_name="0.0.0.0" là bắt buộc để chạy trên Hugging Face
122
  demo.launch(server_name="0.0.0.0")
 
4
  import json
5
  import pysrt
6
  import re
 
7
  from vinorm import TTSnorm
8
+ from phonemizer import phonemize
9
  from scipy.io import wavfile
10
 
11
+ # --- 1. TẢI MODEL & CONFIG ---
 
 
 
 
 
12
  try:
13
+ with open("config.json", "r", encoding="utf-8") as f:
14
  config = json.load(f)
15
+ # Lấy bản đồ ID âm vị từ config của bạn
16
+ phoneme_id_map = config["phoneme_id_map"]
17
  sample_rate = config.get("audio", {}).get("sample_rate", 22050)
18
+
19
+ sess = ort.InferenceSession("model.onnx", providers=['CPUExecutionProvider'])
20
+ print("✅ Hệ thống đã sẵn sàng")
 
21
  except Exception as e:
22
+ print(f"❌ Lỗi khởi động: {e}")
23
 
24
+ # --- 2. LÀM SẠCH VĂN BẢN & CHUYỂN ÂM VỊ ---
25
+ def process_text(text):
26
+ # Loại bỏ thẻ HTML <i>, <b> thường có trong SRT
27
  text = re.sub(r'<[^>]*>', '', text)
28
+ # Chuẩn hóa tiếng Việt (100k -> một trăm nghìn)
29
+ text = TTSnorm(text.replace('\n', ' ').strip())
30
+ # Chuyển sang âm vị IPA (Piper yêu cầu)
31
+ phonemes = phonemize(text, language='vi', backend='espeak', strip=True)
32
+
33
+ ids = [phoneme_id_map.get("^", [1])[0]] # Bắt đầu
34
+ for p in phonemes:
35
+ if p in phoneme_id_map:
36
+ ids.extend(phoneme_id_map[p])
37
+ ids.append(phoneme_id_map.get("_", [0])[0]) # Ký tự trống
38
+ ids.append(phoneme_id_map.get("$", [2])[0]) # Kết thúc
39
+ return ids
 
 
40
 
41
+ # --- 3. XỬ SRT TO AUDIO ---
42
+ def srt_to_audio(srt_file, speed=1.30, noise=0.667, noise_w=0.8):
43
+ if srt_file is None: return "Chưa có file!", None
44
  try:
 
 
 
 
45
  subs = pysrt.open(srt_file.name, encoding='utf-8')
46
  combined_audio = []
47
 
48
  for sub in subs:
49
+ ids = process_text(sub.text)
50
  input_ids = np.array([ids], dtype=np.int64)
51
  input_lens = np.array([len(ids)], dtype=np.int64)
52
+ # Tốc độ 1.30 được đưa vào tham số scale cuối cùng
 
53
  scales = np.array([noise, noise_w, 1.0/speed], dtype=np.float32)
54
 
 
55
  outputs = sess.run(None, {
56
+ "input": input_ids, "input_lengths": input_lens, "scales": scales
 
 
57
  })
58
 
59
+ # Làm phẳng mảng 4D thành 1D âm thanh
60
+ combined_audio.append(outputs[0].flatten())
61
+ # Nghỉ 0.2s giữa các câu
62
+ combined_audio.append(np.zeros(int(sample_rate * 0.2), dtype=np.float32))
 
 
 
63
 
64
+ final_wave = np.concatenate(combined_audio).astype(np.float32)
65
+ wavfile.write("output.wav", sample_rate, final_wave)
66
+ return "Thành công!", "output.wav"
 
 
 
 
 
67
  except Exception as e:
68
+ return f"Lỗi: {str(e)}", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
+ # --- 4. GIAO DIỆN ---
71
+ demo = gr.Interface(
72
+ fn=srt_to_audio,
73
+ inputs=[
74
+ gr.File(label="Tải file SRT từ điện thoại/SDCard"),
75
+ gr.Slider(0.5, 2.0, value=1.30, label="Tốc độ nói"),
76
+ gr.Slider(0.1, 1.0, value=0.667, label="Độ nhiễu (Noise)"),
77
+ gr.Slider(0.1, 1.0, value=0.8, label="Độ nhiễu W")
78
+ ],
79
+ outputs=[gr.Textbox(label="Trạng thái"), gr.Audio(label="Kết quả lồng tiếng")],
80
+ title="SRT to Audio Tiếng Việt - Tốc độ 1.30"
81
+ )
82
 
83
  if __name__ == "__main__":
 
84
  demo.launch(server_name="0.0.0.0")