archivartaunik commited on
Commit
958dddc
·
verified ·
1 Parent(s): 774a30d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -51
app.py CHANGED
@@ -1,3 +1,6 @@
 
 
 
1
  import os
2
  import sys
3
  import tempfile
@@ -18,7 +21,6 @@ REPO_URL = "https://github.com/tuteishygpt/coqui-ai-TTS.git"
18
  REPO_DIR = "coqui-ai-TTS"
19
 
20
  if not os.path.exists(REPO_DIR):
21
- # Клануем fork з беларускай падтрымкай
22
  subprocess.run(
23
  ["git", "clone", REPO_URL, REPO_DIR],
24
  check=True,
@@ -80,11 +82,19 @@ tokenizer = VoiceBpeTokenizer(vocab_file=vocab_file)
80
  XTTS_MODEL.tokenizer = tokenizer
81
 
82
  # ---------------------------------------------------------
83
- # 4. Функцыя TTS (з токенайзерам)
84
  # ---------------------------------------------------------
85
  @spaces.GPU(duration=60)
86
  def text_to_speech(belarusian_story, speaker_audio_file=None):
87
- if not belarusian_story or belarusian_story.strip() == "":
 
 
 
 
 
 
 
 
88
  raise gr.Error("Увядзі хоць нейкі тэкст 🙂")
89
 
90
  # калі аўдыё не перададзена — бярэм голас па змаўчанні
@@ -104,12 +114,12 @@ def text_to_speech(belarusian_story, speaker_audio_file=None):
104
  except Exception as e:
105
  raise gr.Error(f"Памылка пры атрыманні латэнтаў голасу: {e}")
106
 
107
- # ✅ Замяняем sent_tokenize на split_sentence з токенайзера
108
  try:
109
  lang = "be"
110
  chunk_limit = tokenizer.char_limits.get(lang, 250)
111
  tts_texts = split_sentence(
112
- belarusian_story.strip(),
113
  lang=lang,
114
  text_split_length=chunk_limit,
115
  )
@@ -119,7 +129,10 @@ def text_to_speech(belarusian_story, speaker_audio_file=None):
119
  except Exception as e:
120
  raise gr.Error(f"Памылка пры падзеле тэксту на сказы: {e}")
121
 
122
- all_wavs = []
 
 
 
123
  for text in tqdm(tts_texts):
124
  try:
125
  with torch.no_grad():
@@ -134,58 +147,63 @@ def text_to_speech(belarusian_story, speaker_audio_file=None):
134
  top_k=10,
135
  top_p=0.3,
136
  )
137
- all_wavs.append(wav_chunk["wav"])
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  except Exception as e:
139
  raise gr.Error(f"Памылка пры генерырацыі аўдыя: {e}")
140
 
 
 
 
 
141
  try:
142
- out_wav = np.concatenate(all_wavs).astype(np.float32)
143
- except ValueError:
144
- raise gr.Error(
145
- "Немагчыма згенераваць аўдыё. Праверце ўваходны тэкст і аўдыёфайл."
146
- )
147
  except Exception as e:
148
- raise gr.Error(f"Памылка пры аб'яднанні аўдыя: {e}")
149
-
150
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
151
- write(temp_file.name, sampling_rate, out_wav)
152
-
153
- return temp_file.name
154
 
155
 
156
  # ---------------------------------------------------------
157
- # 5. Прыклады
158
  # ---------------------------------------------------------
159
  examples = [
160
  [
161
  "Такім чынам, клуб стаў уладальнікам усіх існых на сёння міжнародных трафеяў паўднёваамерыканскага футболу.",
162
  "Nestarka.wav",
163
- "krai.wav",
164
  ],
165
  [
166
  "Яму не ўдалося палепшыць фінансавае становішча каралеўства, а, наадварот, прыйшлося распрадаваць каштоўнасці чэшскай кароны.",
167
  "muzh.wav",
168
- "examples/цуды.wav",
169
  ],
170
  [
171
  "Кампілятарамі называюць праграмы, якія пераўтвараюць код вышэйшага ўзроўню ў код ніжэйшага ўзроўню.",
172
  "chunk_100.wav",
173
- "examples/надВозерам.wav",
174
  ],
175
  [
176
  "Акрамя таго, ліхачы аддаюць перавагу рэгі, хіп-хопу і класічнай музыцы.",
177
  "d1015.mp3",
178
- "examples/Беларусь.wav",
179
  ],
180
  [
181
  "Позірк можа быць уважлівым, зацікаўленым, захопленым, але бывае і нахабным, задзірлівым, пагардлівым, напышлівым.",
182
  "donarka_ench.wav",
183
- "examples/цуды.wav",
184
  ],
185
  [
186
  "Такі нават шчыры, ці што: родная мова народу – трасянка, а беларуская яму чужая!",
187
  "muzhcynski.wav",
188
- "examples/цуды.wav",
189
  ],
190
  ]
191
 
@@ -195,16 +213,17 @@ analytics_script = """
195
  window.dataLayer = window.dataLayer || [];
196
  function gtag(){dataLayer.push(arguments);}
197
  gtag('js', new Date());
198
-
199
  gtag('config', 'G-TKDCRCQ7FK');
200
  </script>
201
  """
202
 
203
- demo = gr.Blocks()
204
- with demo:
 
 
205
  gr.HTML(analytics_script)
206
  gr.Interface(
207
- fn=text_to_speech,
208
  inputs=[
209
  gr.Textbox(lines=5, label="Тэкст на беларускай мове"),
210
  gr.Audio(
@@ -214,33 +233,18 @@ with demo:
214
  ),
215
  ],
216
  outputs=gr.Audio(
217
- type="filepath",
218
- label="Згенераванае аўдыя",
219
  ),
220
- title="Belarusian TTS Demo",
221
  description="""
222
- <p>Увядзіце тэкст, і мадэль пераўтворыць яго ў аўдыя. Вы можаце выкарыстоўваць
223
- голас па змаўчанні, абраць голас з прыкладаў унізе ці загрузіць уласны файл
224
- або запісаць аўдыё.</p>
225
-
226
- <p><strong>Карысныя парады:</strong></p>
227
- <ul>
228
- <li>Выкарыстоўвайце прыклады з добрай якасцю, без іншых гукаў і разнастайнай інтанацыяй,
229
- ад яе моцна залежыць вынік.</li>
230
- <li>Інтанацыя таксама ўплывае на націскі.</li>
231
- <li>Прыклады галасоў могуць быць на любой мове.</li>
232
- </ul>
233
-
234
- <p>Каб палепшыць якасць мадэлі (націскі і дакладнасць кланавання галасоў), патрэбны дадатковыя датасэты.
235
- Ахвяруйце свой голас праз <a href="https://Donar.by" target="_blank">Donar.by</a></p>
236
-
237
- <p>Далучайцеся да нашай беларускай суполкі ў ТГ, каб дапамагчы ці даведацца пра навіны ШІ:
238
- <a href="https://t.me/SHibelChat" target="_blank">https://t.me/SHibelChat</a>.</p>
239
-
240
- <p><strong>Падтрымаць праект:</strong> <a href="https://buymeacoffee.com/tuteishygpt" target="_blank">Buy Me a Coffee</a></p>
241
  """,
242
  examples=examples,
243
  cache_examples=False,
 
244
  )
245
 
246
  if __name__ == "__main__":
 
1
+ # Калі запускаеце ў чыстым асяроддзі:
2
+ # !pip install -q gradio spaces huggingface_hub torch scipy tqdm gitpython
3
+
4
  import os
5
  import sys
6
  import tempfile
 
21
  REPO_DIR = "coqui-ai-TTS"
22
 
23
  if not os.path.exists(REPO_DIR):
 
24
  subprocess.run(
25
  ["git", "clone", REPO_URL, REPO_DIR],
26
  check=True,
 
82
  XTTS_MODEL.tokenizer = tokenizer
83
 
84
  # ---------------------------------------------------------
85
+ # 4. Патокавая TTS-функцыя (генератар)
86
  # ---------------------------------------------------------
87
  @spaces.GPU(duration=60)
88
  def text_to_speech(belarusian_story, speaker_audio_file=None):
89
+ """
90
+ Streaming-выхад для gr.Audio:
91
+ - на кожным кроку вяртае (sample_rate, np.ndarray[float32]),
92
+ дзе масіў — гэта КАНКАТЭНАВАНЫ дагэтуль гукавы сігнал.
93
+ - у самым канцы дадаткова вяртаецца шлях да temp-файла з фінальным WAV,
94
+ каб карыстальнік мог яго спампаваць.
95
+ Gradio сам зразумее генератар і будзе абнаўляць аудыё па меры паступлення.
96
+ """
97
+ if not belarusian_story or str(belarusian_story).strip() == "":
98
  raise gr.Error("Увядзі хоць нейкі тэкст 🙂")
99
 
100
  # калі аўдыё не перададзена — бярэм голас па змаўчанні
 
114
  except Exception as e:
115
  raise gr.Error(f"Памылка пры атрыманні латэнтаў голасу: {e}")
116
 
117
+ # ✅ Нарэзка тэксту на сказы/чанкі праз split_sentence
118
  try:
119
  lang = "be"
120
  chunk_limit = tokenizer.char_limits.get(lang, 250)
121
  tts_texts = split_sentence(
122
+ str(belarusian_story).strip(),
123
  lang=lang,
124
  text_split_length=chunk_limit,
125
  )
 
129
  except Exception as e:
130
  raise gr.Error(f"Памылка пры падзеле тэксту на сказы: {e}")
131
 
132
+ # Будзем назапашваць гукавыя кавалкі
133
+ chunks = []
134
+ running_total = None # для хутчэйшага concat (лацінка: cumulative)
135
+
136
  for text in tqdm(tts_texts):
137
  try:
138
  with torch.no_grad():
 
147
  top_k=10,
148
  top_p=0.3,
149
  )
150
+ cur = wav_chunk["wav"].astype(np.float32)
151
+ chunks.append(cur)
152
+
153
+ # 🔴 Паступова абнаўляем агульны буфер.
154
+ # Каб не рабіць O(n^2) канкатэнацыю кожны раз, можна час ад часу rebalance,
155
+ # але для тыповых даўжынь будзе дастаткова:
156
+ if running_total is None:
157
+ running_total = cur
158
+ else:
159
+ running_total = np.concatenate([running_total, cur], axis=0)
160
+
161
+ # STREAM: вяртаем «тое, што маем ужо цяпер»
162
+ yield (sampling_rate, running_total)
163
+
164
  except Exception as e:
165
  raise gr.Error(f"Памылка пры генерырацыі аўдыя: {e}")
166
 
167
+ # Фінал: запішам у temp-файл і таксама вернем яго шлях (Gradio падхопіць апошняе значэнне)
168
+ if running_total is None:
169
+ raise gr.Error("Нічога не згенеравана. Праверце ўваходныя даныя.")
170
+
171
  try:
172
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
173
+ write(temp_file.name, sampling_rate, running_total)
174
+ # Канчатковае вяртанне: можна вярнуць шлях — Gradio пакажа кнопку загрузкі.
175
+ yield temp_file.name
 
176
  except Exception as e:
177
+ raise gr.Error(f"Памылка пры запісе фінальнага WAV: {e}")
 
 
 
 
 
178
 
179
 
180
  # ---------------------------------------------------------
181
+ # 5. Прыклады (2 калоны: тэкст + файл голасу)
182
  # ---------------------------------------------------------
183
  examples = [
184
  [
185
  "Такім чынам, клуб стаў уладальнікам усіх існых на сёння міжнародных трафеяў паўднёваамерыканскага футболу.",
186
  "Nestarka.wav",
 
187
  ],
188
  [
189
  "Яму не ўдалося палепшыць фінансавае становішча каралеўства, а, наадварот, прыйшлося распрадаваць каштоўнасці чэшскай кароны.",
190
  "muzh.wav",
 
191
  ],
192
  [
193
  "Кампілятарамі называюць праграмы, якія пераўтвараюць код вышэйшага ўзроўню ў код ніжэйшага ўзроўню.",
194
  "chunk_100.wav",
 
195
  ],
196
  [
197
  "Акрамя таго, ліхачы аддаюць перавагу рэгі, хіп-хопу і класічнай музыцы.",
198
  "d1015.mp3",
 
199
  ],
200
  [
201
  "Позірк можа быць уважлівым, зацікаўленым, захопленым, але бывае і нахабным, задзірлівым, пагардлівым, напышлівым.",
202
  "donarka_ench.wav",
 
203
  ],
204
  [
205
  "Такі нават шчыры, ці што: родная мова народу – трасянка, а беларуская яму чужая!",
206
  "muzhcynski.wav",
 
207
  ],
208
  ]
209
 
 
213
  window.dataLayer = window.dataLayer || [];
214
  function gtag(){dataLayer.push(arguments);}
215
  gtag('js', new Date());
 
216
  gtag('config', 'G-TKDCRCQ7FK');
217
  </script>
218
  """
219
 
220
+ # ---------------------------------------------------------
221
+ # 6. Gradio UI
222
+ # ---------------------------------------------------------
223
+ with gr.Blocks() as demo:
224
  gr.HTML(analytics_script)
225
  gr.Interface(
226
+ fn=text_to_speech, # генератар
227
  inputs=[
228
  gr.Textbox(lines=5, label="Тэкст на беларускай мове"),
229
  gr.Audio(
 
233
  ),
234
  ],
235
  outputs=gr.Audio(
236
+ type="filepath", # дазваляем і (sr, np.array), і канчатковы шлях
237
+ label="Згенераванае аўдыя (патокава)",
238
  ),
239
+ title="Belarusian TTS Demo — Streaming",
240
  description="""
241
+ <p>Увядзіце тэкст і аўдыя будзе адлюстроўвацца <b>па меры сінтэзу</b> (патокава).</p>
242
+ <p>Вы можаце выкарыстаць голас па змаўчанн��, абраць адзін з прыкладаў ці загрузіць уласны файл.</p>
243
+ <p><strong>Парады:</strong> выкарыстоўвайце чыстыя, разнастайныя па інтанацыі прыклады; інтанацыя ўплывае на націскі.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  """,
245
  examples=examples,
246
  cache_examples=False,
247
+ allow_flagging="never",
248
  )
249
 
250
  if __name__ == "__main__":