jayaspjacob Claude Opus 4.8 (1M context) commited on
Commit ·
310ca13
1
Parent(s): 09c9a6a
Add playable voice samples + cap episode length at 2 min
Browse filesVoices: source permissively-licensed clips from CMU ARCTIC (fish-speech
ships none), assembled by scripts/build_voice_samples.py into ~20s clips.
The Voices page now renders a gr.Audio player per voice so samples are
audible while browsing. Three clips also back the narrator_warm /
host_energetic / guest_calm presets, so podcast hosts finally sound
distinct instead of all rendering as the default speaker.
UI: cap the Create LENGTH selector at 2 min (default 2) so generation
stays well under the ZeroGPU 300s cap.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- app.py +71 -31
- scripts/build_voice_samples.py +105 -0
- tts/voices/guest_calm.txt +1 -0
- tts/voices/guest_calm.wav +3 -0
- tts/voices/host_energetic.txt +1 -0
- tts/voices/host_energetic.wav +3 -0
- tts/voices/narrator_warm.txt +1 -0
- tts/voices/narrator_warm.wav +3 -0
- tts/voices/samples/atlas.txt +1 -0
- tts/voices/samples/atlas.wav +3 -0
- tts/voices/samples/echo.txt +1 -0
- tts/voices/samples/echo.wav +3 -0
- tts/voices/samples/nova.txt +1 -0
- tts/voices/samples/nova.wav +3 -0
- tts/voices/samples/onyx.txt +1 -0
- tts/voices/samples/onyx.wav +3 -0
- tts/voices/samples/rune.txt +1 -0
- tts/voices/samples/rune.wav +3 -0
- tts/voices/samples/sage.txt +1 -0
- tts/voices/samples/sage.wav +3 -0
- tts/voices/samples/vivi.txt +1 -0
- tts/voices/samples/vivi.wav +3 -0
app.py
CHANGED
|
@@ -11,6 +11,7 @@ flow — topic → review the script → the finished episode.
|
|
| 11 |
from __future__ import annotations
|
| 12 |
|
| 13 |
import html
|
|
|
|
| 14 |
from typing import List
|
| 15 |
|
| 16 |
import gradio as gr
|
|
@@ -48,6 +49,31 @@ SUGGESTIONS = [
|
|
| 48 |
"Why do cities feel lonely?",
|
| 49 |
]
|
| 50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
# --------------------------------------------------------------------- HTML builders
|
| 53 |
def _avatar(letter: str, idx: int, size: int = 30) -> str:
|
|
@@ -440,6 +466,14 @@ footer { display:none !important; }
|
|
| 440 |
.pf-tile .vm { font-size:10.5px;letter-spacing:1px;color:var(--pf-faint);text-transform:uppercase; }
|
| 441 |
.pf-wave { height:34px;border-radius:8px;margin:10px 0;
|
| 442 |
background:repeating-linear-gradient(90deg,rgba(124,92,255,.5) 0 2px,transparent 2px 5px);opacity:.55; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 443 |
.pf-chips { display:flex;gap:6px;flex-wrap:wrap; }
|
| 444 |
.pf-chiplet { font-size:11px;color:var(--pf-mut);background:var(--pf-panel-2);
|
| 445 |
border:1px solid var(--pf-line);border-radius:7px;padding:3px 9px; }
|
|
@@ -517,7 +551,7 @@ def build_ui():
|
|
| 517 |
new_ep_btn = gr.Button("+ New episode", elem_id="pf-newep")
|
| 518 |
gr.HTML("<div class='pf-section-label'>STUDIO</div>")
|
| 519 |
nav_create = gr.Button("⌁ Create", elem_classes=["pf-nav", "active"])
|
| 520 |
-
nav_voices = gr.Button("🎙 Voices
|
| 521 |
nav_library = gr.Button("▥ Library 6", elem_classes=["pf-nav"])
|
| 522 |
|
| 523 |
# ---------------------------------------------------------- main
|
|
@@ -545,9 +579,8 @@ def build_ui():
|
|
| 545 |
style = gr.Dropdown(STYLES, value="interview", label="FORMAT")
|
| 546 |
with gr.Column(elem_classes=["pf-config-card"]):
|
| 547 |
duration = gr.Dropdown(
|
| 548 |
-
[("
|
| 549 |
-
|
| 550 |
-
value=10, label="LENGTH",
|
| 551 |
)
|
| 552 |
with gr.Column(elem_classes=["pf-config-card"]):
|
| 553 |
num_speakers = gr.Slider(1, MAX_SPEAKERS, value=2, step=1, label="VOICES")
|
|
@@ -653,7 +686,31 @@ def build_ui():
|
|
| 653 |
"<div style='color:var(--pf-mut);font-size:13px;line-height:1.6'>"
|
| 654 |
"Pair a warm host with a contrasting guest for natural back-and-forth. "
|
| 655 |
"Add a subtle ambient bed so silences breathe.</div>")
|
| 656 |
-
gr.HTML(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 657 |
|
| 658 |
# ===================== LIBRARY PAGE =====================
|
| 659 |
with gr.Column(visible=False) as page_library:
|
|
@@ -734,36 +791,19 @@ def build_ui():
|
|
| 734 |
|
| 735 |
|
| 736 |
# -------------------------------------------------------------- static page builders
|
| 737 |
-
def
|
| 738 |
-
voices = [
|
| 739 |
-
("Nova", "Female · American", 0, ["Warm", "Conversational", "Host"]),
|
| 740 |
-
("Atlas", "Male · British", 1, ["Deep", "Cinematic", "Narration"]),
|
| 741 |
-
("Echo", "Neutral · American", 2, ["Crisp", "News", "Authoritative"]),
|
| 742 |
-
("Sage", "Male · Australian", 2, ["Calm", "Thoughtful", "Smooth"]),
|
| 743 |
-
("Vivi", "Female · American", 3, ["Energetic", "Upbeat", "Bright"]),
|
| 744 |
-
("Onyx", "Male · American", 1, ["Smooth", "Late-night", "Radio"]),
|
| 745 |
-
("Lumen", "Female · Irish", 0, ["Bright", "Friendly", "Clear"]),
|
| 746 |
-
("Rune", "Male · British", 2, ["Gravelly", "Documentary", "Rich"]),
|
| 747 |
-
("My Voice", "You · Cloned", 3, ["Cloned", "Custom", "98% match"]),
|
| 748 |
-
]
|
| 749 |
-
tiles = []
|
| 750 |
-
for name, meta, idx, chips in voices:
|
| 751 |
-
chiprow = "".join(f"<span class='pf-chiplet'>{html.escape(c)}</span>" for c in chips)
|
| 752 |
-
tiles.append(
|
| 753 |
-
"<div class='pf-tile'>"
|
| 754 |
-
f"<div class='vh'>{_avatar(name, idx, 38)}"
|
| 755 |
-
f"<div><div class='vn'>{html.escape(name)}</div><div class='vm'>{html.escape(meta)}</div></div></div>"
|
| 756 |
-
"<div class='pf-wave'></div>"
|
| 757 |
-
f"<div class='pf-chips'>{chiprow}</div></div>"
|
| 758 |
-
)
|
| 759 |
return (
|
| 760 |
-
"<div class='
|
| 761 |
-
"<div
|
| 762 |
-
"<
|
| 763 |
-
"<div class='pf-grid'>" + "".join(tiles) + "</div>"
|
| 764 |
)
|
| 765 |
|
| 766 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 767 |
def _library_html() -> str:
|
| 768 |
import random
|
| 769 |
eps = [
|
|
|
|
| 11 |
from __future__ import annotations
|
| 12 |
|
| 13 |
import html
|
| 14 |
+
import os
|
| 15 |
from typing import List
|
| 16 |
|
| 17 |
import gradio as gr
|
|
|
|
| 49 |
"Why do cities feel lonely?",
|
| 50 |
]
|
| 51 |
|
| 52 |
+
# Voice library shown on the Voices page. Each id maps to a playable sample clip under
|
| 53 |
+
# tts/voices/samples/<id>.wav (built by scripts/build_voice_samples.py from CMU ARCTIC).
|
| 54 |
+
# id=None is the "clone your own" slot (no bundled sample). Labels reflect the real
|
| 55 |
+
# underlying speaker so playback matches the description.
|
| 56 |
+
VOICE_LIBRARY = [
|
| 57 |
+
("nova", "Nova", "Female · American", 0, ["Warm", "Conversational", "Host"]),
|
| 58 |
+
("atlas", "Atlas", "Male · Scottish", 1, ["Deep", "Cinematic", "Narration"]),
|
| 59 |
+
("echo", "Echo", "Male · American", 2, ["Crisp", "News", "Authoritative"]),
|
| 60 |
+
("sage", "Sage", "Male · Canadian", 2, ["Calm", "Thoughtful", "Smooth"]),
|
| 61 |
+
("vivi", "Vivi", "Female · American", 3, ["Energetic", "Upbeat", "Bright"]),
|
| 62 |
+
("onyx", "Onyx", "Male · American", 1, ["Smooth", "Late-night", "Radio"]),
|
| 63 |
+
("rune", "Rune", "Male · Indian", 2, ["Gravelly", "Documentary", "Rich"]),
|
| 64 |
+
(None, "My Voice", "You · Cloned", 3, ["Cloned", "Custom", "Clone to use"]),
|
| 65 |
+
]
|
| 66 |
+
|
| 67 |
+
_SAMPLES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "tts", "voices", "samples")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _sample_path(voice_id):
|
| 71 |
+
"""Absolute path to a voice's sample clip, or None if not bundled."""
|
| 72 |
+
if not voice_id:
|
| 73 |
+
return None
|
| 74 |
+
p = os.path.join(_SAMPLES_DIR, f"{voice_id}.wav")
|
| 75 |
+
return p if os.path.isfile(p) else None
|
| 76 |
+
|
| 77 |
|
| 78 |
# --------------------------------------------------------------------- HTML builders
|
| 79 |
def _avatar(letter: str, idx: int, size: int = 30) -> str:
|
|
|
|
| 466 |
.pf-tile .vm { font-size:10.5px;letter-spacing:1px;color:var(--pf-faint);text-transform:uppercase; }
|
| 467 |
.pf-wave { height:34px;border-radius:8px;margin:10px 0;
|
| 468 |
background:repeating-linear-gradient(90deg,rgba(124,92,255,.5) 0 2px,transparent 2px 5px);opacity:.55; }
|
| 469 |
+
/* compact, on-theme audio player inside a voice tile */
|
| 470 |
+
.pf-voice-audio { margin:10px 0 !important; }
|
| 471 |
+
.pf-voice-audio .audio-container, .pf-voice-audio .component-wrapper { background:transparent !important; }
|
| 472 |
+
.pf-voice-audio audio { width:100% !important; height:36px !important; }
|
| 473 |
+
.pf-voice-audio button { color:var(--pf-text) !important; }
|
| 474 |
+
.pf-clone-slot { height:36px;margin:10px 0;border:1px dashed var(--pf-line);border-radius:8px;
|
| 475 |
+
display:flex;align-items:center;justify-content:center;color:var(--pf-faint);font-size:11.5px;
|
| 476 |
+
text-align:center;padding:0 8px; }
|
| 477 |
.pf-chips { display:flex;gap:6px;flex-wrap:wrap; }
|
| 478 |
.pf-chiplet { font-size:11px;color:var(--pf-mut);background:var(--pf-panel-2);
|
| 479 |
border:1px solid var(--pf-line);border-radius:7px;padding:3px 9px; }
|
|
|
|
| 551 |
new_ep_btn = gr.Button("+ New episode", elem_id="pf-newep")
|
| 552 |
gr.HTML("<div class='pf-section-label'>STUDIO</div>")
|
| 553 |
nav_create = gr.Button("⌁ Create", elem_classes=["pf-nav", "active"])
|
| 554 |
+
nav_voices = gr.Button("🎙 Voices 8", elem_classes=["pf-nav"])
|
| 555 |
nav_library = gr.Button("▥ Library 6", elem_classes=["pf-nav"])
|
| 556 |
|
| 557 |
# ---------------------------------------------------------- main
|
|
|
|
| 579 |
style = gr.Dropdown(STYLES, value="interview", label="FORMAT")
|
| 580 |
with gr.Column(elem_classes=["pf-config-card"]):
|
| 581 |
duration = gr.Dropdown(
|
| 582 |
+
[("1 min", 1), ("2 min", 2)],
|
| 583 |
+
value=2, label="LENGTH",
|
|
|
|
| 584 |
)
|
| 585 |
with gr.Column(elem_classes=["pf-config-card"]):
|
| 586 |
num_speakers = gr.Slider(1, MAX_SPEAKERS, value=2, step=1, label="VOICES")
|
|
|
|
| 686 |
"<div style='color:var(--pf-mut);font-size:13px;line-height:1.6'>"
|
| 687 |
"Pair a warm host with a contrasting guest for natural back-and-forth. "
|
| 688 |
"Add a subtle ambient bed so silences breathe.</div>")
|
| 689 |
+
gr.HTML(
|
| 690 |
+
"<div class='pf-eyebrow-row' style='margin-top:26px'>"
|
| 691 |
+
"<div class='pf-step-h'><span class='t'>🎙 Voice library</span>"
|
| 692 |
+
f"<span class='h'>{len(VOICE_LIBRARY)} voices</span></div></div>"
|
| 693 |
+
)
|
| 694 |
+
for _r in range(0, len(VOICE_LIBRARY), 4):
|
| 695 |
+
with gr.Row(equal_height=True):
|
| 696 |
+
for vid, vname, vmeta, vidx, vchips in VOICE_LIBRARY[_r:_r + 4]:
|
| 697 |
+
with gr.Column(elem_classes=["pf-tile"], min_width=210):
|
| 698 |
+
gr.HTML(_voice_card_header(vname, vmeta, vidx))
|
| 699 |
+
_sp = _sample_path(vid)
|
| 700 |
+
if _sp:
|
| 701 |
+
gr.Audio(
|
| 702 |
+
value=_sp,
|
| 703 |
+
show_label=False,
|
| 704 |
+
interactive=False,
|
| 705 |
+
container=False,
|
| 706 |
+
elem_classes=["pf-voice-audio"],
|
| 707 |
+
)
|
| 708 |
+
else:
|
| 709 |
+
gr.HTML(
|
| 710 |
+
"<div class='pf-clone-slot'>Clone a voice above "
|
| 711 |
+
"to preview it here</div>"
|
| 712 |
+
)
|
| 713 |
+
gr.HTML(_voice_card_chips(vchips))
|
| 714 |
|
| 715 |
# ===================== LIBRARY PAGE =====================
|
| 716 |
with gr.Column(visible=False) as page_library:
|
|
|
|
| 791 |
|
| 792 |
|
| 793 |
# -------------------------------------------------------------- static page builders
|
| 794 |
+
def _voice_card_header(name: str, meta: str, idx: int) -> str:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 795 |
return (
|
| 796 |
+
f"<div class='vh'>{_avatar(name, idx, 38)}"
|
| 797 |
+
f"<div><div class='vn'>{html.escape(name)}</div>"
|
| 798 |
+
f"<div class='vm'>{html.escape(meta)}</div></div></div>"
|
|
|
|
| 799 |
)
|
| 800 |
|
| 801 |
|
| 802 |
+
def _voice_card_chips(chips: list) -> str:
|
| 803 |
+
row = "".join(f"<span class='pf-chiplet'>{html.escape(c)}</span>" for c in chips)
|
| 804 |
+
return f"<div class='pf-chips'>{row}</div>"
|
| 805 |
+
|
| 806 |
+
|
| 807 |
def _library_html() -> str:
|
| 808 |
import random
|
| 809 |
eps = [
|
scripts/build_voice_samples.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Build voice sample / reference clips from CMU ARCTIC.
|
| 2 |
+
|
| 3 |
+
fish-speech / OpenAudio ship no reference audio, so we source short, permissively
|
| 4 |
+
licensed clips from CMU ARCTIC (festvox.org — "distributed with no restrictions for
|
| 5 |
+
academic, research and commercial use"). Each voice clip concatenates a few ARCTIC
|
| 6 |
+
sentences (~20s) so it doubles as a clean cloning reference for OpenAudio S1-mini.
|
| 7 |
+
|
| 8 |
+
Outputs:
|
| 9 |
+
tts/voices/samples/<voice>.wav + .txt — played on the Voices page
|
| 10 |
+
tts/voices/<preset>.wav + .txt — picked up by tts/voices.py PRESETS so the
|
| 11 |
+
podcast hosts actually sound distinct
|
| 12 |
+
|
| 13 |
+
Run from the repo root: python scripts/build_voice_samples.py
|
| 14 |
+
WAVs are tracked via Git LFS (see .gitattributes).
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
from __future__ import annotations
|
| 18 |
+
|
| 19 |
+
import io
|
| 20 |
+
import os
|
| 21 |
+
import shutil
|
| 22 |
+
import urllib.request
|
| 23 |
+
|
| 24 |
+
import numpy as np
|
| 25 |
+
import soundfile as sf
|
| 26 |
+
|
| 27 |
+
BASE = "http://festvox.org/cmu_arctic/cmu_arctic"
|
| 28 |
+
UTTS = [f"arctic_a{n:04d}" for n in range(1, 7)] # 6 sentences ≈ 20s
|
| 29 |
+
GAP_S = 0.15
|
| 30 |
+
|
| 31 |
+
# Voices page id -> CMU ARCTIC speaker (distinct timbre/accent each).
|
| 32 |
+
VOICES = {
|
| 33 |
+
"nova": "slt", # female, US
|
| 34 |
+
"atlas": "awb", # male, Scottish
|
| 35 |
+
"echo": "bdl", # male, US
|
| 36 |
+
"sage": "jmk", # male, Canadian
|
| 37 |
+
"vivi": "clb", # female, US
|
| 38 |
+
"onyx": "rms", # male, US
|
| 39 |
+
"rune": "ksp", # male, Indian
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
# Functional presets in tts/voices.py -> reuse a display clip as the cloning reference.
|
| 43 |
+
PRESETS = {
|
| 44 |
+
"narrator_warm": "nova",
|
| 45 |
+
"host_energetic": "echo",
|
| 46 |
+
"guest_calm": "vivi",
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
SAMPLES_DIR = os.path.join("tts", "voices", "samples")
|
| 50 |
+
PRESETS_DIR = os.path.join("tts", "voices")
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def _fetch(url: str) -> bytes:
|
| 54 |
+
with urllib.request.urlopen(url, timeout=60) as r:
|
| 55 |
+
return r.read()
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def _transcripts(spk: str) -> dict:
|
| 59 |
+
raw = _fetch(f"{BASE}/cmu_us_{spk}_arctic/etc/txt.done.data").decode("utf-8", "ignore")
|
| 60 |
+
out = {}
|
| 61 |
+
for line in raw.splitlines():
|
| 62 |
+
line = line.strip()
|
| 63 |
+
if not line.startswith("(") or '"' not in line:
|
| 64 |
+
continue
|
| 65 |
+
try:
|
| 66 |
+
uid = line.split()[1]
|
| 67 |
+
out[uid] = line[line.index('"') + 1 : line.rindex('"')]
|
| 68 |
+
except Exception:
|
| 69 |
+
continue
|
| 70 |
+
return out
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def build():
|
| 74 |
+
os.makedirs(SAMPLES_DIR, exist_ok=True)
|
| 75 |
+
for vid, spk in VOICES.items():
|
| 76 |
+
txts = _transcripts(spk)
|
| 77 |
+
chunks, texts, sr = [], [], 16000
|
| 78 |
+
for uid in UTTS:
|
| 79 |
+
audio, sr = sf.read(io.BytesIO(_fetch(f"{BASE}/cmu_us_{spk}_arctic/wav/{uid}.wav")),
|
| 80 |
+
dtype="float32")
|
| 81 |
+
if audio.ndim > 1:
|
| 82 |
+
audio = audio.mean(axis=1)
|
| 83 |
+
chunks.append(audio)
|
| 84 |
+
chunks.append(np.zeros(int(sr * GAP_S), dtype="float32"))
|
| 85 |
+
if uid in txts:
|
| 86 |
+
texts.append(txts[uid])
|
| 87 |
+
full = np.concatenate(chunks)
|
| 88 |
+
peak = float(np.abs(full).max()) or 1.0
|
| 89 |
+
full = (full / peak * 0.95).astype("float32")
|
| 90 |
+
sf.write(os.path.join(SAMPLES_DIR, f"{vid}.wav"), full, sr)
|
| 91 |
+
with open(os.path.join(SAMPLES_DIR, f"{vid}.txt"), "w", encoding="utf-8") as f:
|
| 92 |
+
f.write(" ".join(texts))
|
| 93 |
+
print(f" sample {vid:6s} <- {spk} {len(full)/sr:4.1f}s")
|
| 94 |
+
|
| 95 |
+
for pid, src in PRESETS.items():
|
| 96 |
+
shutil.copyfile(os.path.join(SAMPLES_DIR, f"{src}.wav"),
|
| 97 |
+
os.path.join(PRESETS_DIR, f"{pid}.wav"))
|
| 98 |
+
shutil.copyfile(os.path.join(SAMPLES_DIR, f"{src}.txt"),
|
| 99 |
+
os.path.join(PRESETS_DIR, f"{pid}.txt"))
|
| 100 |
+
print(f" preset {pid:15s} <- {src}")
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
if __name__ == "__main__":
|
| 104 |
+
build()
|
| 105 |
+
print("done.")
|
tts/voices/guest_calm.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Author of the danger trail, Philip Steels, etc. Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/guest_calm.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:664d85b1252b1f7fca1a5f4b3f2698c7cad633345dd79183bd4c0e13286c7574
|
| 3 |
+
size 652524
|
tts/voices/host_energetic.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Author of the danger trail, Philip Steels, etc. Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/host_energetic.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e3758261d6daa43fc50189fea7e589a2c6cd051e68f02f6e7ee9b7fb1fd21d49
|
| 3 |
+
size 569656
|
tts/voices/narrator_warm.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Author of the danger trail, Philip Steels, etc. Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/narrator_warm.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ebd2694a9908bac8977e0fa530212351d0dca3bb7ed145cbfa3615f868e5f090
|
| 3 |
+
size 581492
|
tts/voices/samples/atlas.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
AUTHOR OF THE DANGER TRAIL, PHILIP STEELS, ETC Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/samples/atlas.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:772c2026d0a19eda162dc5a91e920f527414cb09b4da947ebe888834f195a760
|
| 3 |
+
size 828844
|
tts/voices/samples/echo.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Author of the danger trail, Philip Steels, etc. Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/samples/echo.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e3758261d6daa43fc50189fea7e589a2c6cd051e68f02f6e7ee9b7fb1fd21d49
|
| 3 |
+
size 569656
|
tts/voices/samples/nova.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Author of the danger trail, Philip Steels, etc. Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/samples/nova.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ebd2694a9908bac8977e0fa530212351d0dca3bb7ed145cbfa3615f868e5f090
|
| 3 |
+
size 581492
|
tts/voices/samples/onyx.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Author of the danger trail, Philip Steels, etc. Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/samples/onyx.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1c52525fb406128bf0c9b477a7925269d42db85677deb37c0f4ffcc50ff168ed
|
| 3 |
+
size 548204
|
tts/voices/samples/rune.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Author of the danger trail, Philip Steels, etc. Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/samples/rune.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:aebd0368b53d20922f4de914a2a3ce234a1979ec0f8bb3394be5a692e3831661
|
| 3 |
+
size 638452
|
tts/voices/samples/sage.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Author of the danger trail, Philip Steels, etc. Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/samples/sage.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:559b8b8182c874d590e4d351e88d50e02c35912aac51d9195b465ddc95529039
|
| 3 |
+
size 660852
|
tts/voices/samples/vivi.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Author of the danger trail, Philip Steels, etc. Not at this particular case, Tom, apologized Whittemore. For the twentieth time that evening the two men shook hands. Lord, but I'm glad to see you again, Phil. Will we ever forget it. God bless 'em, I hope I'll go on seeing them forever.
|
tts/voices/samples/vivi.wav
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:664d85b1252b1f7fca1a5f4b3f2698c7cad633345dd79183bd4c0e13286c7574
|
| 3 |
+
size 652524
|