hexgrad commited on
Commit
7b74eba
·
verified ·
1 Parent(s): 9733762

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -69
app.py CHANGED
@@ -142,7 +142,7 @@ VOCAB = get_vocab()
142
  def tokenize(ps):
143
  return [i for i in map(VOCAB.get, ps) if i is not None]
144
 
145
- # ⭐ Starred voices are more stable. 🧪 Experimental voices are less stable.
146
  CHOICES = {
147
  '🇺🇸 🚺 American Female ⭐': 'af',
148
  '🇺🇸 🚺 Bella': 'af_bella',
@@ -212,10 +212,10 @@ def _generate(text, voice, ps, speed, opening_cut, closing_cut, ease_in, ease_ou
212
  tokens = tokens[:510]
213
  ps = ''.join(next(k for k, v in VOCAB.items() if i == v) for i in tokens)
214
  try:
215
- if use_gpu or (use_gpu is None and len(ps) > 99):
216
- out = forward_gpu(tokens, voice, speed)
217
- else:
218
  out = forward(tokens, voice, speed)
 
 
219
  except gr.exceptions.Error as e:
220
  raise gr.Error(e)
221
  return (None, '')
@@ -236,11 +236,29 @@ def _generate(text, voice, ps, speed, opening_cut, closing_cut, ease_in, ease_ou
236
  def toggle_autoplay(autoplay):
237
  return gr.Audio(interactive=False, label='Output Audio', autoplay=autoplay)
238
 
 
 
 
 
 
 
 
 
 
239
  with gr.Blocks() as basic_tts:
240
  with gr.Row():
241
  with gr.Column():
242
- text = gr.Textbox(label='Input Text', info='Generate speech for one segment of text using Kokoro, a TTS model with 80 million parameters.')
243
- voice = gr.Dropdown(list(CHOICES.items()), label='Voice', info='⭐ Starred voices are more stable. 🧪 Experimental voices are less stable.')
 
 
 
 
 
 
 
 
 
244
  with gr.Row():
245
  random_btn = gr.Button('Random Text', variant='secondary')
246
  generate_btn = gr.Button('Generate', variant='primary')
@@ -257,13 +275,6 @@ with gr.Blocks() as basic_tts:
257
  autoplay.change(toggle_autoplay, inputs=[autoplay], outputs=[audio])
258
  with gr.Accordion('Output Tokens', open=True):
259
  out_ps = gr.Textbox(interactive=False, show_label=False, info='Tokens used to generate the audio, up to 510 allowed. Same as input tokens if supplied, excluding unknowns.')
260
- with gr.Row():
261
- use_gpu = gr.Radio(
262
- [('CPU', False), ('Force GPU', True), ('Dynamic', None)],
263
- value=None if CUDA_AVAILABLE else False, label='⚙️ Hardware',
264
- info='CPU: unlimited, ~faster <100 tokens. GPU: limited usage quota, ~faster 100+ tokens. Dynamic: switches based on # of tokens.',
265
- interactive=CUDA_AVAILABLE
266
- )
267
  with gr.Accordion('Audio Settings', open=False):
268
  with gr.Row():
269
  speed = gr.Slider(minimum=0.5, maximum=2, value=1, step=0.1, label='⚡️ Speed', info='Adjust the speed of the audio; the settings below are auto-scaled by speed')
@@ -421,9 +432,17 @@ with gr.Blocks() as lf_tts:
421
  with gr.Row():
422
  with gr.Column():
423
  file_input = gr.File(file_types=['.pdf', '.txt'], label='Input File: pdf or txt')
424
- text = gr.Textbox(label='Input Text', info='Generate speech in batches of 100 text segments and automatically join them together.')
425
  file_input.upload(fn=extract_text, inputs=[file_input], outputs=[text])
426
- voice = gr.Dropdown(list(CHOICES.items()), label='Voice', info='⭐ Starred voices are more stable. 🧪 Experimental voices are less stable.')
 
 
 
 
 
 
 
 
427
  with gr.Accordion('Text Settings', open=False):
428
  skip_square_brackets = gr.Checkbox(True, label='Skip [Square Brackets]', info='Recommended for academic papers, Wikipedia articles, or texts with citations')
429
  newline_split = gr.Number(2, label='Newline Split', info='Split the input text on this many newlines. Affects how the text is segmented.', precision=0, minimum=0)
@@ -432,24 +451,19 @@ with gr.Blocks() as lf_tts:
432
  generate_btn = gr.Button('Generate x0', variant='secondary', interactive=False)
433
  with gr.Column():
434
  audio = gr.Audio(interactive=False, label='Output Audio')
435
- use_gpu = gr.Checkbox(value=CUDA_AVAILABLE, label='Use ZeroGPU', info='🚀 ZeroGPU is fast but has a limited usage quota', interactive=CUDA_AVAILABLE)
436
- use_gpu.change(
437
- fn=lambda v: gr.Checkbox(value=v, label='Use ZeroGPU', info='🚀 ZeroGPU is fast but has a limited usage quota' if v else '🐌 CPU is slow but unlimited'),
438
- inputs=[use_gpu], outputs=[use_gpu]
439
- )
440
  with gr.Accordion('Audio Settings', open=False):
441
  with gr.Row():
442
  speed = gr.Slider(minimum=0.5, maximum=2, value=1, step=0.1, label='⚡️ Speed', info='Adjust the speed of the audio; the settings below are auto-scaled by speed')
443
  with gr.Row():
444
  with gr.Column():
445
- opening_cut = gr.Slider(minimum=0, maximum=24000, value=4000, step=1000, label='✂️ Opening Cut', info='Cut this many samples from the start')
446
  with gr.Column():
447
- closing_cut = gr.Slider(minimum=0, maximum=24000, value=2000, step=1000, label='🎬 Closing Cut', info='Cut this many samples from the end')
448
  with gr.Row():
449
  with gr.Column():
450
- ease_in = gr.Slider(minimum=0, maximum=24000, value=3000, step=1000, label='🎢 Ease In', info='Ease in for this many samples, after opening cut')
451
  with gr.Column():
452
- ease_out = gr.Slider(minimum=0, maximum=24000, value=1000, step=1000, label='🛝 Ease Out', info='Ease out for this many samples, before closing cut')
453
  with gr.Row():
454
  pad_between = gr.Slider(minimum=0, maximum=24000, value=10000, step=1000, label='🔇 Pad Between', info='How many samples of silence to insert between segments')
455
  with gr.Row():
@@ -460,51 +474,26 @@ with gr.Blocks() as lf_tts:
460
 
461
  with gr.Blocks() as about:
462
  gr.Markdown("""
463
- Kokoro is a frontier TTS model for its size. It has 80 million parameters,<sup>[1]</sup> uses a lean StyleTTS 2 architecture,<sup>[2]</sup> and was trained on high-quality data.
464
 
465
- The weights are currently private, but a free public demo is hosted here, at `https://hf.co/spaces/hexgrad/Kokoro-TTS`
 
 
 
 
 
 
 
 
 
 
466
 
467
  ### Compute
468
  The model was trained on 1x A100-class 80GB instances rented from [Vast.ai](https://cloud.vast.ai/?ref_id=79907).<sup>[3]</sup><br/>
469
  Vast was chosen over other compute providers due to its competitive on-demand hourly rates.<br/>
470
  The average hourly cost for the 1x A100-class 80GB VRAM instances used for training was below $1/hr — around half the quoted rates from other providers.
471
 
472
- ### Licenses
473
- Inference code: MIT<br/>
474
- espeak-ng dependency: GPL-3.0<sup>[4]</sup><br/>
475
- Random English texts: Unknown<sup>[5]</sup><br/>
476
- Random Japanese texts: CC0 public domain<sup>[6]</sup>
477
-
478
- ### References
479
- 1. Kokoro parameter count | https://hf.co/spaces/hexgrad/Kokoro-TTS/blob/main/app.py#L31
480
- 2. StyleTTS 2 | https://github.com/yl4579/StyleTTS2
481
- 3. Vast.ai referral link | https://cloud.vast.ai/?ref_id=79907
482
- 4. eSpeak NG | https://github.com/espeak-ng/espeak-ng
483
- 5. Quotable Data | https://github.com/quotable-io/data/blob/master/data/quotes.json
484
- 6. Common Voice Japanese sentences | https://github.com/common-voice/common-voice/tree/main/server/data/ja
485
-
486
- ### Contact
487
- @rzvzn on Discord
488
- """)
489
-
490
- with gr.Blocks() as faq:
491
- gr.Markdown("""
492
- ### Will this be open sourced?
493
- There currently isn't a release date scheduled for the weights. The inference code in this space is MIT licensed. The StyleTTS 2 architecture was already published by Li et al, with MIT licensed code and pretrained weights.
494
-
495
- ### What does it mean for a voice to be unstable?
496
- An unstable voice is more likely to stumble or produce unnatural artifacts, especially on short or strange texts.
497
-
498
- ### CPU faster than ZeroGPU? How?
499
- The CPU seems to be a dedicated resource for this Space, whereas the ZeroGPU pool is shared dynamically allocated across all of HF. Obviously the latter demands some kind of queue & allocator system, which inevitably must add latency.
500
-
501
- For Basic TTS under 100 tokens (~characters), only a few seconds of audio needs to be generated, so the actual compute is not that heavy. For these short bursts, the dedicated CPU can often compute the result faster than the total time it takes for you to: enter the ZeroGPU queue, wait to get allocated, and have a GPU compute and deliver the result.
502
-
503
- As you move beyond 100 tokens and especially closer to the ~500 token context window, the GPU catches up. And for Long-Form, since batches of 100 segments are processed at a time, the GPU should outspeed the CPU by 1-2 orders of magnitude.
504
- """)
505
-
506
- with gr.Blocks() as api_info:
507
- gr.Markdown("""
508
  This Space can be used via API. The following code block can be copied and run in one Google Colab cell.
509
  ```
510
  # 1. Install the Gradio Python client
@@ -527,21 +516,33 @@ display(Audio(audio_path, autoplay=True))
527
  print(out_ps)
528
  ```
529
  Note that this Space and the underlying Kokoro model are both under development and subject to change. Reliability is not guaranteed. Hugging Face and/or Gradio might enforce their own rate limits.
530
- """)
531
 
532
- with gr.Blocks() as version_info:
533
- gr.Markdown("""
534
- | Model Version | Date | Validation losses (mel/dur/f0) |
535
- | ------- | ---- | ------------------------------ |
536
  | v0.19 | 2024 Nov 22 | 0.261 / 0.627 / 1.897 |
537
  | v0.16 | 2024 Nov 15 | 0.263 / 0.646 / 1.934 |
538
  | v0.14 | 2024 Nov 12 | 0.262 / 0.642 / 1.889 |
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  """)
540
 
541
  with gr.Blocks() as app:
542
  gr.TabbedInterface(
543
- [basic_tts, lf_tts, about, faq, api_info, version_info],
544
- ['🗣️ Basic TTS', '📖 Long-Form', 'ℹ️ About', '❓ FAQ', '🚀 Gradio API', '📝 Version History'],
545
  )
546
 
547
  if __name__ == '__main__':
 
142
  def tokenize(ps):
143
  return [i for i in map(VOCAB.get, ps) if i is not None]
144
 
145
+ # ⭐ voices are stable, 🧪 voices are unstable
146
  CHOICES = {
147
  '🇺🇸 🚺 American Female ⭐': 'af',
148
  '🇺🇸 🚺 Bella': 'af_bella',
 
212
  tokens = tokens[:510]
213
  ps = ''.join(next(k for k, v in VOCAB.items() if i == v) for i in tokens)
214
  try:
215
+ if not use_gpu or (use_gpu == 'auto' and len(ps) < 100):
 
 
216
  out = forward(tokens, voice, speed)
217
+ else:
218
+ out = forward_gpu(tokens, voice, speed)
219
  except gr.exceptions.Error as e:
220
  raise gr.Error(e)
221
  return (None, '')
 
236
  def toggle_autoplay(autoplay):
237
  return gr.Audio(interactive=False, label='Output Audio', autoplay=autoplay)
238
 
239
+ USE_GPU_CHOICES = [('Auto', 'auto'), ('CPU', False), ('ZeroGPU', True)]
240
+ USE_GPU_INFOS = {
241
+ 'auto': 'Use CPU or GPU, whichever is faster',
242
+ False: 'CPU is ~faster <100 tokens',
243
+ True: 'ZeroGPU is ~faster >100 tokens',
244
+ }
245
+ def change_use_gpu(value):
246
+ return gr.Dropdown(USE_GPU_CHOICES, value=value, label='Hardware', info=USE_GPU_INFOS[value], interactive=CUDA_AVAILABLE)
247
+
248
  with gr.Blocks() as basic_tts:
249
  with gr.Row():
250
  with gr.Column():
251
+ text = gr.Textbox(label='Input Text', info='Generate speech for one segment of text using Kokoro, a TTS model with 80 million parameters')
252
+ with gr.Row():
253
+ voice = gr.Dropdown(list(CHOICES.items()), value='af', label='Voice', info='⭐ voices are stable, 🧪 voices are unstable')
254
+ use_gpu = gr.Dropdown(
255
+ USE_GPU_CHOICES,
256
+ value='auto' if CUDA_AVAILABLE else False,
257
+ label='Hardware',
258
+ info=USE_GPU_INFOS['auto' if CUDA_AVAILABLE else False],
259
+ interactive=CUDA_AVAILABLE
260
+ )
261
+ use_gpu.change(fn=change_use_gpu, inputs=[use_gpu], outputs=[use_gpu])
262
  with gr.Row():
263
  random_btn = gr.Button('Random Text', variant='secondary')
264
  generate_btn = gr.Button('Generate', variant='primary')
 
275
  autoplay.change(toggle_autoplay, inputs=[autoplay], outputs=[audio])
276
  with gr.Accordion('Output Tokens', open=True):
277
  out_ps = gr.Textbox(interactive=False, show_label=False, info='Tokens used to generate the audio, up to 510 allowed. Same as input tokens if supplied, excluding unknowns.')
 
 
 
 
 
 
 
278
  with gr.Accordion('Audio Settings', open=False):
279
  with gr.Row():
280
  speed = gr.Slider(minimum=0.5, maximum=2, value=1, step=0.1, label='⚡️ Speed', info='Adjust the speed of the audio; the settings below are auto-scaled by speed')
 
432
  with gr.Row():
433
  with gr.Column():
434
  file_input = gr.File(file_types=['.pdf', '.txt'], label='Input File: pdf or txt')
435
+ text = gr.Textbox(label='Input Text', info='Generate speech in batches of 100 text segments and automatically join them together')
436
  file_input.upload(fn=extract_text, inputs=[file_input], outputs=[text])
437
+ with gr.Row():
438
+ voice = gr.Dropdown(list(CHOICES.items()), value='af', label='Voice', info='⭐ voices are stable, 🧪 voices are unstable')
439
+ use_gpu = gr.Dropdown(
440
+ [('ZeroGPU', True), ('CPU', False)],
441
+ value=CUDA_AVAILABLE,
442
+ label='Hardware',
443
+ info='GPU is >10x faster but has a usage quota',
444
+ interactive=CUDA_AVAILABLE
445
+ )
446
  with gr.Accordion('Text Settings', open=False):
447
  skip_square_brackets = gr.Checkbox(True, label='Skip [Square Brackets]', info='Recommended for academic papers, Wikipedia articles, or texts with citations')
448
  newline_split = gr.Number(2, label='Newline Split', info='Split the input text on this many newlines. Affects how the text is segmented.', precision=0, minimum=0)
 
451
  generate_btn = gr.Button('Generate x0', variant='secondary', interactive=False)
452
  with gr.Column():
453
  audio = gr.Audio(interactive=False, label='Output Audio')
 
 
 
 
 
454
  with gr.Accordion('Audio Settings', open=False):
455
  with gr.Row():
456
  speed = gr.Slider(minimum=0.5, maximum=2, value=1, step=0.1, label='⚡️ Speed', info='Adjust the speed of the audio; the settings below are auto-scaled by speed')
457
  with gr.Row():
458
  with gr.Column():
459
+ opening_cut = gr.Slider(minimum=0, maximum=24000, value=4000, step=1000, label='✂️ Opening Cut', info='Cut samples from the start')
460
  with gr.Column():
461
+ closing_cut = gr.Slider(minimum=0, maximum=24000, value=2000, step=1000, label='🎬 Closing Cut', info='Cut samples from the end')
462
  with gr.Row():
463
  with gr.Column():
464
+ ease_in = gr.Slider(minimum=0, maximum=24000, value=3000, step=1000, label='🎢 Ease In', info='Ease in samples, after opening cut')
465
  with gr.Column():
466
+ ease_out = gr.Slider(minimum=0, maximum=24000, value=1000, step=1000, label='🛝 Ease Out', info='Ease out samples, before closing cut')
467
  with gr.Row():
468
  pad_between = gr.Slider(minimum=0, maximum=24000, value=10000, step=1000, label='🔇 Pad Between', info='How many samples of silence to insert between segments')
469
  with gr.Row():
 
474
 
475
  with gr.Blocks() as about:
476
  gr.Markdown("""
477
+ Kokoro is a frontier TTS model for its size. It has 80 million parameters,<sup>[1]</sup> uses a lean StyleTTS 2 architecture,<sup>[2]</sup> and was trained on high-quality data. The weights are currently private, but a free public demo is hosted here, at `https://hf.co/spaces/hexgrad/Kokoro-TTS`. The Community tab is open for feature requests, bug reports, etc. For other inquiries, contact @rzvzn on Discord.
478
 
479
+ ### FAQ
480
+ #### Will this be open sourced?
481
+ There currently isn't a release date scheduled for the weights. The inference code in this space is MIT licensed. The architecture was already published by Li et al, with MIT licensed code and pretrained weights.<sup>[2]</sup>
482
+
483
+ #### What is an unstable voice?
484
+ An unstable voice is more likely to stumble or produce unnatural artifacts, especially on short or strange texts.
485
+
486
+ #### How can CPU be faster than ZeroGPU?
487
+ The CPU is a dedicated resource for this Space, while the ZeroGPU pool is shared and dynamically allocated across all of HF. The ZeroGPU queue/allocator system inevitably adds latency to each request.<br/>
488
+ For Basic TTS under ~100 tokens or characters, only a few seconds of audio need to be generated, so the actual compute is not that heavy. In these short bursts, the dedicated CPU can often compute the result faster than the total time it takes to: enter the ZeroGPU queue, wait to get allocated, and have a GPU compute and deliver the result.<br/>
489
+ ZeroGPU catches up beyond 100 tokens and especially closer to the ~500 token context window. Long-Form mode processes batches of 100 segments at a time, so the GPU should outspeed the CPU by 1-2 orders of magnitude.
490
 
491
  ### Compute
492
  The model was trained on 1x A100-class 80GB instances rented from [Vast.ai](https://cloud.vast.ai/?ref_id=79907).<sup>[3]</sup><br/>
493
  Vast was chosen over other compute providers due to its competitive on-demand hourly rates.<br/>
494
  The average hourly cost for the 1x A100-class 80GB VRAM instances used for training was below $1/hr — around half the quoted rates from other providers.
495
 
496
+ ### Gradio API
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
497
  This Space can be used via API. The following code block can be copied and run in one Google Colab cell.
498
  ```
499
  # 1. Install the Gradio Python client
 
516
  print(out_ps)
517
  ```
518
  Note that this Space and the underlying Kokoro model are both under development and subject to change. Reliability is not guaranteed. Hugging Face and/or Gradio might enforce their own rate limits.
 
519
 
520
+ ### Model Version History
521
+ | Version | Date | Val mel / dur / f0 Losses |
522
+ | ------- | ---- | ------------------------- |
 
523
  | v0.19 | 2024 Nov 22 | 0.261 / 0.627 / 1.897 |
524
  | v0.16 | 2024 Nov 15 | 0.263 / 0.646 / 1.934 |
525
  | v0.14 | 2024 Nov 12 | 0.262 / 0.642 / 1.889 |
526
+
527
+ ### Licenses
528
+ Inference code: MIT<br/>
529
+ espeak-ng dependency: GPL-3.0<sup>[4]</sup><br/>
530
+ Random English texts: Unknown<sup>[5]</sup><br/>
531
+ Random Japanese texts: CC0 public domain<sup>[6]</sup>
532
+
533
+ ### References
534
+ 1. Kokoro parameter count | https://hf.co/spaces/hexgrad/Kokoro-TTS/blob/main/app.py#L31
535
+ 2. StyleTTS 2 | https://github.com/yl4579/StyleTTS2
536
+ 3. Vast.ai referral link | https://cloud.vast.ai/?ref_id=79907
537
+ 4. eSpeak NG | https://github.com/espeak-ng/espeak-ng
538
+ 5. Quotable Data | https://github.com/quotable-io/data/blob/master/data/quotes.json
539
+ 6. Common Voice Japanese sentences | https://github.com/common-voice/common-voice/tree/main/server/data/ja
540
  """)
541
 
542
  with gr.Blocks() as app:
543
  gr.TabbedInterface(
544
+ [basic_tts, lf_tts, about],
545
+ ['🔥 Basic TTS', '📖 Long-Form', 'ℹ️ About'],
546
  )
547
 
548
  if __name__ == '__main__':