archivartaunik commited on
Commit
5ea7abd
·
verified ·
1 Parent(s): 30be2d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -17
app.py CHANGED
@@ -121,7 +121,7 @@ def _crossfade_concat(a: np.ndarray, b: np.ndarray, sr: int, fade_s: float) -> n
121
  rest = b[fade_n:]
122
  return np.concatenate([head, tail, rest], axis=0)
123
 
124
- def _bpe_prefixes(text: str, lang: str, step_tokens: int) -> Iterable[str]:
125
  """
126
  Прэфіксы па BPE/субсловах; калі encode/decode недаступны — псэўда-токены (словы+прабелы).
127
  """
@@ -308,16 +308,20 @@ def _yield_buffered_chunks_for_gradio(
308
  time.sleep(buf.size / float(sr))
309
 
310
  # ---------------------------------------------------------
311
- # 6) Асноўная функцыя TTS для Gradio (у стылі .generate(do_stream=True))
 
 
 
312
  # ---------------------------------------------------------
313
  @spaces.GPU(duration=60)
314
  def text_to_speech(belarusian_story, speaker_audio_file=None):
315
  """
316
- Streaming для gr.Audio:
317
- - model.generate(..., do_stream=True) -> чанкі (sr, chunk) з мінімальнай затрымкай;
318
- - у фінале шлях да поўнага WAV.
319
  """
320
  if not belarusian_story or str(belarusian_story).strip() == "":
 
321
  raise gr.Error("Увядзі хоць нейкі тэкст 🙂")
322
 
323
  # Голас па змаўчанні
@@ -355,13 +359,17 @@ def text_to_speech(belarusian_story, speaker_audio_file=None):
355
 
356
  full_audio_chunks: List[np.ndarray] = []
357
 
 
358
  for sr, chunk in _yield_buffered_chunks_for_gradio(generator, sampling_rate, MIN_BUFFER_S):
359
  full_audio_chunks.append(chunk)
360
- yield (sr, chunk)
361
 
362
  if not full_audio_chunks:
363
- raise gr.Error("Нічога не згенеравана. Праверце ўваходныя даныя або лагі.")
 
 
364
 
 
365
  full_audio = full_audio_chunks[0]
366
  for i in range(1, len(full_audio_chunks)):
367
  full_audio = _crossfade_concat(full_audio, full_audio_chunks[i], sampling_rate, FADE_S)
@@ -369,7 +377,8 @@ def text_to_speech(belarusian_story, speaker_audio_file=None):
369
  try:
370
  tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
371
  write(tmp.name, sampling_rate, full_audio.astype(np.float32))
372
- yield tmp.name
 
373
  except Exception as e:
374
  raise gr.Error(f"Памылка пры запісе фінальнага WAV: {e}")
375
 
@@ -414,7 +423,9 @@ analytics_script = """
414
  """
415
 
416
  # ---------------------------------------------------------
417
- # 8) Gradio UI (аўтапрайграванне)
 
 
418
  # ---------------------------------------------------------
419
  with gr.Blocks() as demo:
420
  gr.HTML(analytics_script)
@@ -428,15 +439,24 @@ with gr.Blocks() as demo:
428
  interactive=True,
429
  ),
430
  ],
431
- outputs=gr.Audio(
432
- type="filepath",
433
- label="Згенераванае аўдыя (па токенах, мінімальная затрымка)",
434
- autoplay=True,
435
- ),
436
- title="Belarusian TTS — Token Streaming (як у transformers-stream-generator)",
 
 
 
 
 
 
 
437
  description="""
438
- <p>Мадэль <code>Xtts</code> мае метады <code>generate()</code> і <code>sample_stream()</code>, як у прыкладзе.
439
- Калі даступны <code>inference_stream</code>, выкарыстоўваем яго; інакш інкрементальна па «токенах» з ~50&nbsp;мс буферам.</p>
 
 
440
  """,
441
  examples=examples,
442
  cache_examples=False,
 
121
  rest = b[fade_n:]
122
  return np.concatenate([head, tail, rest], axis=0)
123
 
124
+ def _bpe_prefixes(text: str, lang: str, step_tokens: int):
125
  """
126
  Прэфіксы па BPE/субсловах; калі encode/decode недаступны — псэўда-токены (словы+прабелы).
127
  """
 
308
  time.sleep(buf.size / float(sr))
309
 
310
  # ---------------------------------------------------------
311
+ # 6) Асноўная функцыя TTS для Gradio
312
+ # Цяпер ВЫХАД = ДВА элементы:
313
+ # 1) Стрымінг па токенах (грайцеся ўжывую) — gr.Audio(type='numpy')
314
+ # 2) Згенераванае аўдыя (па токенах, мінімальная затрымка) — толькі ФІНАЛЬНЫ файл
315
  # ---------------------------------------------------------
316
  @spaces.GPU(duration=60)
317
  def text_to_speech(belarusian_story, speaker_audio_file=None):
318
  """
319
+ Вяртаем два выхады:
320
+ - (sr, chunk) для стрымінгавага прайгравальніка (на кожным кроку)
321
+ - None / шлях да WAV у ФІНАЛЕ для элемента «Згенераванае аўдыя...»
322
  """
323
  if not belarusian_story or str(belarusian_story).strip() == "":
324
+ # Для абодвух выхадаў вяртаем None
325
  raise gr.Error("Увядзі хоць нейкі тэкст 🙂")
326
 
327
  # Голас па змаўчанні
 
359
 
360
  full_audio_chunks: List[np.ndarray] = []
361
 
362
+ # 1) падчас стриму — аддаем у першы выход (стрымінг), другі — None
363
  for sr, chunk in _yield_buffered_chunks_for_gradio(generator, sampling_rate, MIN_BUFFER_S):
364
  full_audio_chunks.append(chunk)
365
+ yield ( (sr, chunk), None )
366
 
367
  if not full_audio_chunks:
368
+ # Нічога не назбіралі абодва выхады None
369
+ yield ( None, None )
370
+ return
371
 
372
+ # 2) збіраем фінальны WAV і вяртаем яго ў другі выход
373
  full_audio = full_audio_chunks[0]
374
  for i in range(1, len(full_audio_chunks)):
375
  full_audio = _crossfade_concat(full_audio, full_audio_chunks[i], sampling_rate, FADE_S)
 
377
  try:
378
  tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
379
  write(tmp.name, sampling_rate, full_audio.astype(np.float32))
380
+ # у фінале — першы выход (стрымінг) прыбіраем (None), другі — шлях да файла
381
+ yield ( None, tmp.name )
382
  except Exception as e:
383
  raise gr.Error(f"Памылка пры запісе фінальнага WAV: {e}")
384
 
 
423
  """
424
 
425
  # ---------------------------------------------------------
426
+ # 8) Gradio UI:
427
+ # - Новы ЭЛЕМЕНТ для стрыму: "Стрымінг па токенах (анлайн прайграванне)" — прымае (sr, ndarray)
428
+ # - Стары ЭЛЕМЕНТ "Згенераванае аўдыя (па токенах, мінімальная затрымка)" — цяпер ТОЛЬКІ фінальны файл
429
  # ---------------------------------------------------------
430
  with gr.Blocks() as demo:
431
  gr.HTML(analytics_script)
 
439
  interactive=True,
440
  ),
441
  ],
442
+ outputs=[
443
+ gr.Audio(
444
+ type="numpy", # стримінг: (sr, np.ndarray)
445
+ label="Стрымінг па токенах (анлайн прайграванне)",
446
+ autoplay=True,
447
+ ),
448
+ gr.Audio(
449
+ type="filepath", # толькі фінальны шлях да WAV
450
+ label="Згенераванае аўдыя (па токенах, мінімальная затрымка)",
451
+ autoplay=False,
452
+ ),
453
+ ],
454
+ title="Belarusian TTS — Token Streaming (два выхады)",
455
  description="""
456
+ <ul>
457
+ <li><b>Стрымінг па токенах</b> жывы прайгравальнік, атрымлівае маленькія чанкі гуку па меры генерацыі.</li>
458
+ <li><b>Згенераванае аўдыя (па токенах, мінімальная затрымка)</b> — толькі <i>фінальны</i> цэлы WAV-файл для загрузкі/прайгравання.</li>
459
+ </ul>
460
  """,
461
  examples=examples,
462
  cache_examples=False,