Spaces:
Running
on
Zero
Running
on
Zero
Merge branch 'main_sync'
Browse files- README.md +14 -0
- app/config.py +12 -2
- app/leaderboard.py +19 -16
- app/models.py +31 -0
- app/ui.py +3 -0
- app/ui_leaderboard.py +2 -2
- app/ui_vote.py +3 -1
README.md
CHANGED
@@ -34,3 +34,17 @@ sdk_version: 5.13.0
|
|
34 |
|
35 |
[Saved votes dataset](https://huggingface.co/datasets/Pendrokar/TTS_Arena)
|
36 |
[TTS tracker dataset](https://huggingface.co/datasets/Pendrokar/open_tts_tracker)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
[Saved votes dataset](https://huggingface.co/datasets/Pendrokar/TTS_Arena)
|
36 |
[TTS tracker dataset](https://huggingface.co/datasets/Pendrokar/open_tts_tracker)
|
37 |
+
|
38 |
+
# TTS Arena
|
39 |
+
|
40 |
+
The codebase for TTS Arena v2.
|
41 |
+
|
42 |
+
The TTS Arena is a Gradio app with several components. Please refer to the `app` directory for more information.
|
43 |
+
|
44 |
+
## Running the app
|
45 |
+
|
46 |
+
```bash
|
47 |
+
RUNNING_LOCALLY=1 python app.py
|
48 |
+
```
|
49 |
+
|
50 |
+
You must set the `RUNNING_LOCALLY` environment variable to `1` when running the app locally. This prevents it from syncing with the database
|
app/config.py
CHANGED
@@ -1,5 +1,11 @@
|
|
1 |
import os
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
# NOTE: Configure models in `models.py`
|
4 |
|
5 |
#########################
|
@@ -18,7 +24,7 @@ DB_PATH = f"/data/{DB_NAME}" if os.path.isdir("/data") else DB_NAME # If /data a
|
|
18 |
ROUTER_ID = "Pendrokar/xVASynth-TTS" # You should use a router space to route TTS models to avoid exposing your API keys!
|
19 |
# ROUTER_ID = "TTS-AGI/tts-router" # You should use a router space to route TTS models to avoid exposing your API keys!
|
20 |
|
21 |
-
SYNC_DB =
|
22 |
DB_DATASET_ID = os.getenv('DATASET_ID') # HF dataset ID, can be None if not syncing
|
23 |
|
24 |
SPACE_ID = os.getenv('SPACE_ID') # Don't change this! It detects if we're running in a HF Space
|
@@ -48,4 +54,8 @@ CITATION_TEXT = """@misc{tts-arena,
|
|
48 |
year = 2024,
|
49 |
publisher = {Hugging Face},
|
50 |
howpublished = "\\url{https://huggingface.co/spaces/TTS-AGI/TTS-Arena}"
|
51 |
-
}"""
|
|
|
|
|
|
|
|
|
|
1 |
import os
|
2 |
|
3 |
+
RUNNING_LOCALLY = os.getenv('RUNNING_LOCALLY', '0').lower() in ('true', '1', 't')
|
4 |
+
if RUNNING_LOCALLY:
|
5 |
+
print("Running locally, not syncing DB to HF dataset")
|
6 |
+
else:
|
7 |
+
print("Running in HF Space, syncing DB to HF dataset")
|
8 |
+
|
9 |
# NOTE: Configure models in `models.py`
|
10 |
|
11 |
#########################
|
|
|
24 |
ROUTER_ID = "Pendrokar/xVASynth-TTS" # You should use a router space to route TTS models to avoid exposing your API keys!
|
25 |
# ROUTER_ID = "TTS-AGI/tts-router" # You should use a router space to route TTS models to avoid exposing your API keys!
|
26 |
|
27 |
+
SYNC_DB = not RUNNING_LOCALLY # Sync DB to HF dataset?
|
28 |
DB_DATASET_ID = os.getenv('DATASET_ID') # HF dataset ID, can be None if not syncing
|
29 |
|
30 |
SPACE_ID = os.getenv('SPACE_ID') # Don't change this! It detects if we're running in a HF Space
|
|
|
54 |
year = 2024,
|
55 |
publisher = {Hugging Face},
|
56 |
howpublished = "\\url{https://huggingface.co/spaces/TTS-AGI/TTS-Arena}"
|
57 |
+
}"""
|
58 |
+
|
59 |
+
#- 2025/01/21: New leaderboard UI released with enhanced UI and improved performance.
|
60 |
+
NEWS = """
|
61 |
+
"""
|
app/leaderboard.py
CHANGED
@@ -21,27 +21,30 @@ def get_leaderboard(reveal_prelim = False):
|
|
21 |
df['name'] = df['name'].replace(model_names)
|
22 |
for i in range(len(df)):
|
23 |
df.loc[i, "name"] = make_link_to_space(df['name'][i], True)
|
|
|
|
|
24 |
df['votes'] = df['upvote'] + df['downvote']
|
|
|
25 |
# df['score'] = round((df['upvote'] / df['votes']) * 100, 2) # Percentage score
|
26 |
|
27 |
## ELO SCORE
|
28 |
-
df['
|
29 |
-
df['
|
30 |
for i in range(len(df)):
|
31 |
for j in range(len(df)):
|
32 |
if i != j:
|
33 |
try:
|
34 |
-
expected_a = 1 / (1 + 10 ** ((df['
|
35 |
-
expected_b = 1 / (1 + 10 ** ((df['
|
36 |
actual_a = df['upvote'].iloc[i] / df['votes'].iloc[i] if df['votes'].iloc[i] > 0 else 0.5
|
37 |
actual_b = df['upvote'].iloc[j] / df['votes'].iloc[j] if df['votes'].iloc[j] > 0 else 0.5
|
38 |
-
df.at[i, '
|
39 |
-
df.at[j, '
|
40 |
except Exception as e:
|
41 |
print(f"Error in ELO calculation for rows {i} and {j}: {str(e)}")
|
42 |
continue
|
43 |
-
df['
|
44 |
-
df['
|
45 |
|
46 |
if (
|
47 |
reveal_prelim == False
|
@@ -51,18 +54,18 @@ def get_leaderboard(reveal_prelim = False):
|
|
51 |
|
52 |
if (reveal_prelim == False):
|
53 |
for i in range(len(df)):
|
54 |
-
|
55 |
-
if (
|
56 |
continue
|
57 |
-
if (
|
58 |
plus = '<em style="color: green; font-family: monospace">+'
|
59 |
else:
|
60 |
plus = '<em style="color: red; font-family: monospace">'
|
61 |
|
62 |
-
df.at[i, '
|
63 |
|
64 |
-
## ELO
|
65 |
-
df = df.sort_values(by='
|
66 |
# medals
|
67 |
def assign_medal(rank, assign):
|
68 |
rank = str(rank + 1)
|
@@ -86,6 +89,6 @@ def get_leaderboard(reveal_prelim = False):
|
|
86 |
):
|
87 |
top_five.append(orig_name)
|
88 |
|
89 |
-
df['
|
90 |
-
df = df[['order', 'name', '
|
91 |
return df
|
|
|
21 |
df['name'] = df['name'].replace(model_names)
|
22 |
for i in range(len(df)):
|
23 |
df.loc[i, "name"] = make_link_to_space(df['name'][i], True)
|
24 |
+
|
25 |
+
# Calculate total votes and win rate
|
26 |
df['votes'] = df['upvote'] + df['downvote']
|
27 |
+
df['win_rate'] = (df['upvote'] / df['votes'] * 100).round(1)
|
28 |
# df['score'] = round((df['upvote'] / df['votes']) * 100, 2) # Percentage score
|
29 |
|
30 |
## ELO SCORE
|
31 |
+
df['elo'] = 1200
|
32 |
+
df['elo_diff'] = ""
|
33 |
for i in range(len(df)):
|
34 |
for j in range(len(df)):
|
35 |
if i != j:
|
36 |
try:
|
37 |
+
expected_a = 1 / (1 + 10 ** ((df['elo'].iloc[j] - df['elo'].iloc[i]) / 400))
|
38 |
+
expected_b = 1 / (1 + 10 ** ((df['elo'].iloc[i] - df['elo'].iloc[j]) / 400))
|
39 |
actual_a = df['upvote'].iloc[i] / df['votes'].iloc[i] if df['votes'].iloc[i] > 0 else 0.5
|
40 |
actual_b = df['upvote'].iloc[j] / df['votes'].iloc[j] if df['votes'].iloc[j] > 0 else 0.5
|
41 |
+
df.at[i, 'elo'] += round(32 * (actual_a - expected_a))
|
42 |
+
df.at[j, 'elo'] += round(32 * (actual_b - expected_b))
|
43 |
except Exception as e:
|
44 |
print(f"Error in ELO calculation for rows {i} and {j}: {str(e)}")
|
45 |
continue
|
46 |
+
df['elo'] = round(df['elo'])
|
47 |
+
df['elo_diff'] = df['elo']
|
48 |
|
49 |
if (
|
50 |
reveal_prelim == False
|
|
|
54 |
|
55 |
if (reveal_prelim == False):
|
56 |
for i in range(len(df)):
|
57 |
+
elo_diff = (df['elo'].iloc[i] - leaderboard_df['elo'].iloc[i])
|
58 |
+
if (elo_diff == 0):
|
59 |
continue
|
60 |
+
if (elo_diff > 0):
|
61 |
plus = '<em style="color: green; font-family: monospace">+'
|
62 |
else:
|
63 |
plus = '<em style="color: red; font-family: monospace">'
|
64 |
|
65 |
+
df.at[i, 'elo_diff'] = str(df['elo'].iloc[i]) + plus + str(elo_diff) +'</em>'
|
66 |
|
67 |
+
## ELO score
|
68 |
+
df = df.sort_values(by='elo', ascending=False)
|
69 |
# medals
|
70 |
def assign_medal(rank, assign):
|
71 |
rank = str(rank + 1)
|
|
|
89 |
):
|
90 |
top_five.append(orig_name)
|
91 |
|
92 |
+
df['elo'] = df['elo_diff']
|
93 |
+
df = df[['order', 'name', 'elo', 'votes', 'win_rate']]
|
94 |
return df
|
app/models.py
CHANGED
@@ -513,6 +513,37 @@ model_names = {
|
|
513 |
'metavoice': 'MetaVoice-1B',
|
514 |
}
|
515 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
516 |
def make_link_to_space(model_name, for_leaderboard=False):
|
517 |
# create a anchor link if a HF space
|
518 |
style = 'text-decoration: underline;text-decoration-style: dotted;'
|
|
|
513 |
'metavoice': 'MetaVoice-1B',
|
514 |
}
|
515 |
|
516 |
+
model_links = {
|
517 |
+
'ElevenLabs': 'https://elevenlabs.io/',
|
518 |
+
'Play.HT 2.0': 'https://play.ht/',
|
519 |
+
'Play.HT 3.0 Mini': 'https://play.ht/',
|
520 |
+
'XTTSv2': 'https://huggingface.co/coqui/XTTS-v2',
|
521 |
+
'MeloTTS': 'https://github.com/myshell-ai/MeloTTS',
|
522 |
+
'StyleTTS 2': 'https://github.com/yl4579/StyleTTS2',
|
523 |
+
'Parler TTS Large': 'https://github.com/huggingface/parler-tts',
|
524 |
+
'Parler TTS': 'https://github.com/huggingface/parler-tts',
|
525 |
+
'Fish Speech v1.5': 'https://github.com/fishaudio/fish-speech',
|
526 |
+
'Fish Speech v1.4': 'https://github.com/fishaudio/fish-speech',
|
527 |
+
'GPT-SoVITS': 'https://github.com/RVC-Boss/GPT-SoVITS',
|
528 |
+
'WhisperSpeech': 'https://github.com/WhisperSpeech/WhisperSpeech',
|
529 |
+
'VoiceCraft 2.0': 'https://github.com/jasonppy/VoiceCraft',
|
530 |
+
'PlayDialog': 'https://play.ht/',
|
531 |
+
'Kokoro v0.19': 'https://huggingface.co/hexgrad/Kokoro-82M',
|
532 |
+
'CosyVoice 2.0': 'https://github.com/FunAudioLLM/CosyVoice',
|
533 |
+
'MetaVoice': 'https://github.com/metavoiceio/metavoice-src',
|
534 |
+
'OpenVoice': 'https://github.com/myshell-ai/OpenVoice',
|
535 |
+
'OpenVoice V2': 'https://github.com/myshell-ai/OpenVoice',
|
536 |
+
'Pheme': 'https://github.com/PolyAI-LDN/pheme',
|
537 |
+
'Vokan TTS': 'https://huggingface.co/ShoukanLabs/Vokan',
|
538 |
+
}
|
539 |
+
|
540 |
+
closed_source = [
|
541 |
+
'ElevenLabs',
|
542 |
+
'Play.HT 2.0',
|
543 |
+
'Play.HT 3.0 Mini',
|
544 |
+
'PlayDialog',
|
545 |
+
]
|
546 |
+
|
547 |
def make_link_to_space(model_name, for_leaderboard=False):
|
548 |
# create a anchor link if a HF space
|
549 |
style = 'text-decoration: underline;text-decoration-style: dotted;'
|
app/ui.py
CHANGED
@@ -37,6 +37,9 @@ head_js += open("app/cookie.js").read()
|
|
37 |
head_js += '</script>'
|
38 |
|
39 |
with gr.Blocks() as about:
|
|
|
|
|
|
|
40 |
gr.Markdown(ABOUT)
|
41 |
|
42 |
with gr.Blocks(
|
|
|
37 |
head_js += '</script>'
|
38 |
|
39 |
with gr.Blocks() as about:
|
40 |
+
with gr.Row():
|
41 |
+
with gr.Accordion("News", open=False):
|
42 |
+
gr.Markdown(NEWS)
|
43 |
gr.Markdown(ABOUT)
|
44 |
|
45 |
with gr.Blocks(
|
app/ui_leaderboard.py
CHANGED
@@ -9,8 +9,8 @@ with gr.Blocks() as leaderboard:
|
|
9 |
interactive=False,
|
10 |
min_width=0,
|
11 |
wrap=False,
|
12 |
-
column_widths=[30, 200, 50, 50],
|
13 |
-
datatype=["str", "html", "html", "number"]
|
14 |
)
|
15 |
reloadbtn = gr.Button("Refresh")
|
16 |
with gr.Row():
|
|
|
9 |
interactive=False,
|
10 |
min_width=0,
|
11 |
wrap=False,
|
12 |
+
column_widths=[30, 200, 50, 50, 50],
|
13 |
+
datatype=["str", "html", "html", "html", "number"]
|
14 |
)
|
15 |
reloadbtn = gr.Button("Refresh")
|
16 |
with gr.Row():
|
app/ui_vote.py
CHANGED
@@ -54,6 +54,7 @@ with gr.Blocks() as vote:
|
|
54 |
show_label=False,
|
55 |
show_download_button=False,
|
56 |
show_share_button=False,
|
|
|
57 |
# waveform_options={'waveform_progress_color': '#EF4444'},
|
58 |
# var(--color-red-500)'}); gradio only accepts HEX and CSS color
|
59 |
)
|
@@ -76,6 +77,7 @@ with gr.Blocks() as vote:
|
|
76 |
show_download_button=False,
|
77 |
show_share_button=False,
|
78 |
waveform_options={'waveform_progress_color': '#3C82F6'},
|
|
|
79 |
# var(--secondary-500)'}); gradio only accepts HEX and CSS color
|
80 |
)
|
81 |
bbetter = gr.Button(
|
@@ -161,7 +163,7 @@ with gr.Blocks() as vote:
|
|
161 |
.then(
|
162 |
None,
|
163 |
inputs=[bplayed if autoplay else True],
|
164 |
-
js="(b) => b ? 0 : document.querySelector('
|
165 |
)
|
166 |
# autoplay if unplayed
|
167 |
aud2\
|
|
|
54 |
show_label=False,
|
55 |
show_download_button=False,
|
56 |
show_share_button=False,
|
57 |
+
elem_id="vote-a-audio",
|
58 |
# waveform_options={'waveform_progress_color': '#EF4444'},
|
59 |
# var(--color-red-500)'}); gradio only accepts HEX and CSS color
|
60 |
)
|
|
|
77 |
show_download_button=False,
|
78 |
show_share_button=False,
|
79 |
waveform_options={'waveform_progress_color': '#3C82F6'},
|
80 |
+
elem_id="vote-b-audio",
|
81 |
# var(--secondary-500)'}); gradio only accepts HEX and CSS color
|
82 |
)
|
83 |
bbetter = gr.Button(
|
|
|
163 |
.then(
|
164 |
None,
|
165 |
inputs=[bplayed if autoplay else True],
|
166 |
+
js="(b) => b ? 0 : document.getElementById('vote-b-audio')?.querySelector('button.play-pause-button')?.click()",
|
167 |
)
|
168 |
# autoplay if unplayed
|
169 |
aud2\
|