rjzevallos commited on
Commit
c310cb4
β€’
1 Parent(s): c6207a9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +765 -193
app.py CHANGED
@@ -1,204 +1,776 @@
1
  import gradio as gr
2
- from gradio_leaderboard import Leaderboard, ColumnFilter, SelectColumns
3
  import pandas as pd
4
- from apscheduler.schedulers.background import BackgroundScheduler
5
- from huggingface_hub import snapshot_download
6
-
7
- from src.about import (
8
- CITATION_BUTTON_LABEL,
9
- CITATION_BUTTON_TEXT,
10
- EVALUATION_QUEUE_TEXT,
11
- INTRODUCTION_TEXT,
12
- LLM_BENCHMARKS_TEXT,
13
- TITLE,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  )
15
- from src.display.css_html_js import custom_css
16
- from src.display.utils import (
17
- BENCHMARK_COLS,
18
- COLS,
19
- EVAL_COLS,
20
- EVAL_TYPES,
21
- AutoEvalColumn,
22
- ModelType,
23
- fields,
24
- WeightType,
25
- Precision
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  )
27
- from src.envs import API, EVAL_REQUESTS_PATH, EVAL_RESULTS_PATH, QUEUE_REPO, REPO_ID, RESULTS_REPO, TOKEN
28
- from src.populate import get_evaluation_queue_df, get_leaderboard_df
29
- from src.submission.submit import add_new_eval
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
- def restart_space():
33
- API.restart_space(repo_id=REPO_ID)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
- ### Space initialisation
36
- try:
37
- print(EVAL_REQUESTS_PATH)
38
- snapshot_download(
39
- repo_id=QUEUE_REPO, local_dir=EVAL_REQUESTS_PATH, repo_type="dataset", tqdm_class=None, etag_timeout=30, token=TOKEN
40
- )
41
- except Exception:
42
- restart_space()
43
- try:
44
- print(EVAL_RESULTS_PATH)
45
- snapshot_download(
46
- repo_id=RESULTS_REPO, local_dir=EVAL_RESULTS_PATH, repo_type="dataset", tqdm_class=None, etag_timeout=30, token=TOKEN
47
- )
48
- except Exception:
49
- restart_space()
50
-
51
-
52
- LEADERBOARD_DF = get_leaderboard_df(EVAL_RESULTS_PATH, EVAL_REQUESTS_PATH, COLS, BENCHMARK_COLS)
53
-
54
- (
55
- finished_eval_queue_df,
56
- running_eval_queue_df,
57
- pending_eval_queue_df,
58
- ) = get_evaluation_queue_df(EVAL_REQUESTS_PATH, EVAL_COLS)
59
-
60
- def init_leaderboard(dataframe):
61
- if dataframe is None or dataframe.empty:
62
- raise ValueError("Leaderboard DataFrame is empty or None.")
63
- return Leaderboard(
64
- value=dataframe,
65
- datatype=[c.type for c in fields(AutoEvalColumn)],
66
- select_columns=SelectColumns(
67
- default_selection=[c.name for c in fields(AutoEvalColumn) if c.displayed_by_default],
68
- cant_deselect=[c.name for c in fields(AutoEvalColumn) if c.never_hidden],
69
- label="Select Columns to Display:",
70
- ),
71
- search_columns=[AutoEvalColumn.model.name, AutoEvalColumn.license.name],
72
- hide_columns=[c.name for c in fields(AutoEvalColumn) if c.hidden],
73
- filter_columns=[
74
- ColumnFilter(AutoEvalColumn.model_type.name, type="checkboxgroup", label="Model types"),
75
- ColumnFilter(AutoEvalColumn.precision.name, type="checkboxgroup", label="Precision"),
76
- ColumnFilter(
77
- AutoEvalColumn.params.name,
78
- type="slider",
79
- min=0.01,
80
- max=150,
81
- label="Select the number of parameters (B)",
82
- ),
83
- ColumnFilter(
84
- AutoEvalColumn.still_on_hub.name, type="boolean", label="Deleted/incomplete", default=True
85
- ),
86
- ],
87
- bool_checkboxgroup_label="Hide models",
88
- interactive=False,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
 
 
 
 
 
 
91
 
92
- demo = gr.Blocks(css=custom_css)
93
- with demo:
94
- gr.HTML(TITLE)
95
- gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text")
96
-
97
- with gr.Tabs(elem_classes="tab-buttons") as tabs:
98
- with gr.TabItem("πŸ… LLM Benchmark", elem_id="llm-benchmark-tab-table", id=0):
99
- leaderboard = init_leaderboard(LEADERBOARD_DF)
100
-
101
- with gr.TabItem("πŸ“ About", elem_id="llm-benchmark-tab-table", id=2):
102
- gr.Markdown(LLM_BENCHMARKS_TEXT, elem_classes="markdown-text")
103
-
104
- with gr.TabItem("πŸš€ Submit here! ", elem_id="llm-benchmark-tab-table", id=3):
105
- with gr.Column():
106
- with gr.Row():
107
- gr.Markdown(EVALUATION_QUEUE_TEXT, elem_classes="markdown-text")
108
-
109
- with gr.Column():
110
- with gr.Accordion(
111
- f"βœ… Finished Evaluations ({len(finished_eval_queue_df)})",
112
- open=False,
113
- ):
114
- with gr.Row():
115
- finished_eval_table = gr.components.Dataframe(
116
- value=finished_eval_queue_df,
117
- headers=EVAL_COLS,
118
- datatype=EVAL_TYPES,
119
- row_count=5,
120
- )
121
- with gr.Accordion(
122
- f"πŸ”„ Running Evaluation Queue ({len(running_eval_queue_df)})",
123
- open=False,
124
- ):
125
- with gr.Row():
126
- running_eval_table = gr.components.Dataframe(
127
- value=running_eval_queue_df,
128
- headers=EVAL_COLS,
129
- datatype=EVAL_TYPES,
130
- row_count=5,
131
- )
132
-
133
- with gr.Accordion(
134
- f"⏳ Pending Evaluation Queue ({len(pending_eval_queue_df)})",
135
- open=False,
136
- ):
137
- with gr.Row():
138
- pending_eval_table = gr.components.Dataframe(
139
- value=pending_eval_queue_df,
140
- headers=EVAL_COLS,
141
- datatype=EVAL_TYPES,
142
- row_count=5,
143
- )
144
- with gr.Row():
145
- gr.Markdown("# βœ‰οΈβœ¨ Submit your model here!", elem_classes="markdown-text")
146
-
147
- with gr.Row():
148
- with gr.Column():
149
- model_name_textbox = gr.Textbox(label="Model name")
150
- revision_name_textbox = gr.Textbox(label="Revision commit", placeholder="main")
151
- model_type = gr.Dropdown(
152
- choices=[t.to_str(" : ") for t in ModelType if t != ModelType.Unknown],
153
- label="Model type",
154
- multiselect=False,
155
- value=None,
156
- interactive=True,
157
- )
158
-
159
- with gr.Column():
160
- precision = gr.Dropdown(
161
- choices=[i.value.name for i in Precision if i != Precision.Unknown],
162
- label="Precision",
163
- multiselect=False,
164
- value="float16",
165
- interactive=True,
166
- )
167
- weight_type = gr.Dropdown(
168
- choices=[i.value.name for i in WeightType],
169
- label="Weights type",
170
- multiselect=False,
171
- value="Original",
172
- interactive=True,
173
- )
174
- base_model_name_textbox = gr.Textbox(label="Base model (for delta or adapter weights)")
175
-
176
- submit_button = gr.Button("Submit Eval")
177
- submission_result = gr.Markdown()
178
- submit_button.click(
179
- add_new_eval,
180
- [
181
- model_name_textbox,
182
- base_model_name_textbox,
183
- revision_name_textbox,
184
- precision,
185
- weight_type,
186
- model_type,
187
- ],
188
- submission_result,
189
- )
190
 
191
- with gr.Row():
192
- with gr.Accordion("πŸ“™ Citation", open=False):
193
- citation_button = gr.Textbox(
194
- value=CITATION_BUTTON_TEXT,
195
- label=CITATION_BUTTON_LABEL,
196
- lines=20,
197
- elem_id="citation-button",
198
- show_copy_button=True,
199
- )
200
-
201
- scheduler = BackgroundScheduler()
202
- scheduler.add_job(restart_space, "interval", seconds=1800)
203
- scheduler.start()
204
- demo.queue(default_concurrency_limit=40).launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
 
2
  import pandas as pd
3
+ from langdetect import detect
4
+ from datasets import load_dataset
5
+ import threading, time, uuid, sqlite3, shutil, os, random, asyncio, threading
6
+ from pathlib import Path
7
+ from huggingface_hub import CommitScheduler, delete_file, hf_hub_download
8
+ from gradio_client import Client
9
+ import pyloudnorm as pyln
10
+ import soundfile as sf
11
+ import librosa
12
+ from detoxify import Detoxify
13
+ import os
14
+ import tempfile
15
+ from pydub import AudioSegment
16
+
17
+ def match_target_amplitude(sound, target_dBFS):
18
+ change_in_dBFS = target_dBFS - sound.dBFS
19
+ return sound.apply_gain(change_in_dBFS)
20
+
21
+ # from gradio_space_ci import enable_space_ci
22
+
23
+ # enable_space_ci()
24
+
25
+
26
+
27
+ toxicity = Detoxify('original')
28
+ with open('harvard_sentences.txt') as f:
29
+ sents = f.read().strip().splitlines()
30
+ ####################################
31
+ # Constants
32
+ ####################################
33
+ AVAILABLE_MODELS = {
34
+ 'XTTSv2': 'xtts',
35
+ # 'WhisperSpeech': 'whisperspeech',
36
+ 'ElevenLabs': 'eleven',
37
+ # 'OpenVoice': 'openvoice',
38
+ 'OpenVoice V2': 'openvoicev2',
39
+ 'Play.HT 2.0': 'playht',
40
+ # 'MetaVoice': 'metavoice',
41
+ 'MeloTTS': 'melo',
42
+ 'StyleTTS 2': 'styletts2',
43
+ 'GPT-SoVITS': 'sovits',
44
+ # 'Vokan TTS': 'vokan',
45
+ 'VoiceCraft 2.0': 'voicecraft',
46
+ 'Parler TTS': 'parler'
47
+ }
48
+
49
+ SPACE_ID = os.getenv('SPACE_ID')
50
+ MAX_SAMPLE_TXT_LENGTH = 300
51
+ MIN_SAMPLE_TXT_LENGTH = 10
52
+ DB_DATASET_ID = os.getenv('DATASET_ID')
53
+ DB_NAME = "database.db"
54
+
55
+ # If /data available => means local storage is enabled => let's use it!
56
+ DB_PATH = f"/data/{DB_NAME}" if os.path.isdir("/data") else DB_NAME
57
+ print(f"Using {DB_PATH}")
58
+ # AUDIO_DATASET_ID = "ttseval/tts-arena-new"
59
+ CITATION_TEXT = """@misc{tts-arena,
60
+ title = {Text to Speech Arena},
61
+ author = {mrfakename and Srivastav, Vaibhav and Fourrier, ClΓ©mentine and Pouget, Lucain and Lacombe, Yoach and main and Gandhi, Sanchit},
62
+ year = 2024,
63
+ publisher = {Hugging Face},
64
+ howpublished = "\\url{https://huggingface.co/spaces/TTS-AGI/TTS-Arena}"
65
+ }"""
66
+
67
+ ####################################
68
+ # Functions
69
+ ####################################
70
+
71
+ def create_db_if_missing():
72
+ conn = get_db()
73
+ cursor = conn.cursor()
74
+ cursor.execute('''
75
+ CREATE TABLE IF NOT EXISTS model (
76
+ name TEXT UNIQUE,
77
+ upvote INTEGER,
78
+ downvote INTEGER
79
+ );
80
+ ''')
81
+ cursor.execute('''
82
+ CREATE TABLE IF NOT EXISTS vote (
83
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
84
+ username TEXT,
85
+ model TEXT,
86
+ vote INTEGER,
87
+ timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
88
+ );
89
+ ''')
90
+ cursor.execute('''
91
+ CREATE TABLE IF NOT EXISTS votelog (
92
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
93
+ username TEXT,
94
+ chosen TEXT,
95
+ rejected TEXT,
96
+ timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
97
+ );
98
+ ''')
99
+ cursor.execute('''
100
+ CREATE TABLE IF NOT EXISTS spokentext (
101
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
102
+ spokentext TEXT,
103
+ timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
104
+ );
105
+ ''')
106
+ def get_db():
107
+ return sqlite3.connect(DB_PATH)
108
+
109
+
110
+
111
+ ####################################
112
+ # Space initialization
113
+ ####################################
114
+
115
+ # Download existing DB
116
+ if not os.path.isfile(DB_PATH):
117
+ print("Downloading DB...")
118
+ try:
119
+ cache_path = hf_hub_download(repo_id=DB_DATASET_ID, repo_type='dataset', filename=DB_NAME)
120
+ shutil.copyfile(cache_path, DB_PATH)
121
+ print("Downloaded DB")
122
+ except Exception as e:
123
+ print("Error while downloading DB:", e)
124
+
125
+ # Create DB table (if doesn't exist)
126
+ create_db_if_missing()
127
+
128
+ # Sync local DB with remote repo every 5 minute (only if a change is detected)
129
+ scheduler = CommitScheduler(
130
+ repo_id=DB_DATASET_ID,
131
+ repo_type="dataset",
132
+ folder_path=Path(DB_PATH).parent,
133
+ every=5,
134
+ allow_patterns=DB_NAME,
135
  )
136
+
137
+ # Load audio dataset
138
+ # audio_dataset = load_dataset(AUDIO_DATASET_ID)
139
+
140
+ ####################################
141
+ # Router API
142
+ ####################################
143
+ router = Client("TTS-AGI/tts-router", hf_token=os.getenv('HF_TOKEN'))
144
+ ####################################
145
+ # Gradio app
146
+ ####################################
147
+ MUST_BE_LOGGEDIN = "Please login with Hugging Face to participate in the TTS Arena."
148
+ DESCR = """
149
+ # TTS Arena: Benchmarking TTS Models in the Wild
150
+ Vote to help the community find the best available text-to-speech model!
151
+ """.strip()
152
+ # INSTR = """
153
+ # ## Instructions
154
+
155
+ # * Listen to two anonymous models
156
+ # * Vote on which synthesized audio sounds more natural to you
157
+ # * If there's a tie, click Skip
158
+
159
+ # **When you're ready to begin, login and begin voting!** The model names will be revealed once you vote.
160
+ # """.strip()
161
+ INSTR = """
162
+ ## πŸ—³οΈ Vote
163
+ * Input text (English only) to synthesize audio (or press 🎲 for random text).
164
+ * Listen to the two audio clips, one after the other.
165
+ * Vote on which audio sounds more natural to you.
166
+ * _Note: Model names are revealed after the vote is cast._
167
+ Note: It may take up to 30 seconds to synthesize audio.
168
+ """.strip()
169
+ request = ''
170
+ if SPACE_ID:
171
+ request = f"""
172
+ ### Request a model
173
+ Please [create a Discussion](https://huggingface.co/spaces/{SPACE_ID}/discussions/new) to request a model.
174
+ """
175
+ ABOUT = f"""
176
+ ## πŸ“„ About
177
+ The TTS Arena evaluates leading speech synthesis models. It is inspired by LMsys's [Chatbot Arena](https://chat.lmsys.org/).
178
+ ### Motivation
179
+ The field of speech synthesis has long lacked an accurate method to measure the quality of different models. Objective metrics like WER (word error rate) are unreliable measures of model quality, and subjective measures such as MOS (mean opinion score) are typically small-scale experiments conducted with few listeners. As a result, these measurements are generally not useful for comparing two models of roughly similar quality. To address these drawbacks, we are inviting the community to rank models in an easy-to-use interface, and opening it up to the public in order to make both the opportunity to rank models, as well as the results, more easily accessible to everyone.
180
+ ### The Arena
181
+ The leaderboard allows a user to enter text, which will be synthesized by two models. After listening to each sample, the user can vote on which model sounds more natural. Due to the risks of human bias and abuse, model names are revealed only after a vote is submitted.
182
+ ### Credits
183
+ Thank you to the following individuals who helped make this project possible:
184
+ * VB ([Twitter](https://twitter.com/reach_vb) / [Hugging Face](https://huggingface.co/reach-vb))
185
+ * ClΓ©mentine Fourrier ([Twitter](https://twitter.com/clefourrier) / [Hugging Face](https://huggingface.co/clefourrier))
186
+ * Lucain Pouget ([Twitter](https://twitter.com/Wauplin) / [Hugging Face](https://huggingface.co/Wauplin))
187
+ * Yoach Lacombe ([Twitter](https://twitter.com/yoachlacombe) / [Hugging Face](https://huggingface.co/ylacombe))
188
+ * Main Horse ([Twitter](https://twitter.com/main_horse) / [Hugging Face](https://huggingface.co/main-horse))
189
+ * Sanchit Gandhi ([Twitter](https://twitter.com/sanchitgandhi99) / [Hugging Face](https://huggingface.co/sanchit-gandhi))
190
+ * ApolinΓ‘rio Passos ([Twitter](https://twitter.com/multimodalart) / [Hugging Face](https://huggingface.co/multimodalart))
191
+ * Pedro Cuenca ([Twitter](https://twitter.com/pcuenq) / [Hugging Face](https://huggingface.co/pcuenq))
192
+ {request}
193
+ ### Privacy statement
194
+ We may store text you enter and generated audio. We store a unique ID for each session. You agree that we may collect, share, and/or publish any data you input for research and/or commercial purposes.
195
+ ### License
196
+ Generated audio clips cannot be redistributed and may be used for personal, non-commercial use only.
197
+ Random sentences are sourced from a filtered subset of the [Harvard Sentences](https://www.cs.columbia.edu/~hgs/audio/harvard.html).
198
+ """.strip()
199
+ LDESC = """
200
+ ## πŸ† Leaderboard
201
+ Vote to help the community determine the best text-to-speech (TTS) models.
202
+ The leaderboard displays models in descending order of how natural they sound (based on votes cast by the community).
203
+ Important: In order to help keep results fair, the leaderboard hides results by default until the number of votes passes a threshold. Tick the `Reveal preliminary results` to show models without sufficient votes. Please note that preliminary results may be inaccurate.
204
+ """.strip()
205
+
206
+
207
+
208
+
209
+ # def reload_audio_dataset():
210
+ # global audio_dataset
211
+ # audio_dataset = load_dataset(AUDIO_DATASET_ID)
212
+ # return 'Reload Audio Dataset'
213
+
214
+ def del_db(txt):
215
+ if not txt.lower() == 'delete db':
216
+ raise gr.Error('You did not enter "delete db"')
217
+
218
+ # Delete local + remote
219
+ os.remove(DB_PATH)
220
+ delete_file(path_in_repo=DB_NAME, repo_id=DB_DATASET_ID, repo_type='dataset')
221
+
222
+ # Recreate
223
+ create_db_if_missing()
224
+ return 'Delete DB'
225
+
226
+ theme = gr.themes.Base(
227
+ font=[gr.themes.GoogleFont('Libre Franklin'), gr.themes.GoogleFont('Public Sans'), 'system-ui', 'sans-serif'],
228
  )
 
 
 
229
 
230
+ model_names = {
231
+ 'styletts2': 'StyleTTS 2',
232
+ 'tacotron': 'Tacotron',
233
+ 'tacotronph': 'Tacotron Phoneme',
234
+ 'tacotrondca': 'Tacotron DCA',
235
+ 'speedyspeech': 'Speedy Speech',
236
+ 'overflow': 'Overflow TTS',
237
+ 'vits': 'VITS',
238
+ 'vitsneon': 'VITS Neon',
239
+ 'neuralhmm': 'Neural HMM',
240
+ 'glow': 'Glow TTS',
241
+ 'fastpitch': 'FastPitch',
242
+ 'jenny': 'Jenny',
243
+ 'tortoise': 'Tortoise TTS',
244
+ 'xtts2': 'Coqui XTTSv2',
245
+ 'xtts': 'Coqui XTTS',
246
+ 'openvoice': 'MyShell OpenVoice',
247
+ 'elevenlabs': 'ElevenLabs',
248
+ 'openai': 'OpenAI',
249
+ 'hierspeech': 'HierSpeech++',
250
+ 'pheme': 'PolyAI Pheme',
251
+ 'speecht5': 'SpeechT5',
252
+ 'metavoice': 'MetaVoice-1B',
253
+ }
254
+ model_licenses = {
255
+ 'styletts2': 'MIT',
256
+ 'tacotron': 'BSD-3',
257
+ 'tacotronph': 'BSD-3',
258
+ 'tacotrondca': 'BSD-3',
259
+ 'speedyspeech': 'BSD-3',
260
+ 'overflow': 'MIT',
261
+ 'vits': 'MIT',
262
+ 'openvoice': 'MIT',
263
+ 'vitsneon': 'BSD-3',
264
+ 'neuralhmm': 'MIT',
265
+ 'glow': 'MIT',
266
+ 'fastpitch': 'Apache 2.0',
267
+ 'jenny': 'Jenny License',
268
+ 'tortoise': 'Apache 2.0',
269
+ 'xtts2': 'CPML (NC)',
270
+ 'xtts': 'CPML (NC)',
271
+ 'elevenlabs': 'Proprietary',
272
+ 'eleven': 'Proprietary',
273
+ 'openai': 'Proprietary',
274
+ 'hierspeech': 'MIT',
275
+ 'pheme': 'CC-BY',
276
+ 'speecht5': 'MIT',
277
+ 'metavoice': 'Apache 2.0',
278
+ 'elevenlabs': 'Proprietary',
279
+ 'whisperspeech': 'MIT',
280
+ }
281
+ model_links = {
282
+ 'styletts2': 'https://github.com/yl4579/StyleTTS2',
283
+ 'tacotron': 'https://github.com/NVIDIA/tacotron2',
284
+ 'speedyspeech': 'https://github.com/janvainer/speedyspeech',
285
+ 'overflow': 'https://github.com/shivammehta25/OverFlow',
286
+ 'vits': 'https://github.com/jaywalnut310/vits',
287
+ 'openvoice': 'https://github.com/myshell-ai/OpenVoice',
288
+ 'neuralhmm': 'https://github.com/ketranm/neuralHMM',
289
+ 'glow': 'https://github.com/jaywalnut310/glow-tts',
290
+ 'fastpitch': 'https://fastpitch.github.io/',
291
+ 'tortoise': 'https://github.com/neonbjb/tortoise-tts',
292
+ 'xtts2': 'https://huggingface.co/coqui/XTTS-v2',
293
+ 'xtts': 'https://huggingface.co/coqui/XTTS-v1',
294
+ 'elevenlabs': 'https://elevenlabs.io/',
295
+ 'openai': 'https://help.openai.com/en/articles/8555505-tts-api',
296
+ 'hierspeech': 'https://github.com/sh-lee-prml/HierSpeechpp',
297
+ 'pheme': 'https://github.com/PolyAI-LDN/pheme',
298
+ 'speecht5': 'https://github.com/microsoft/SpeechT5',
299
+ 'metavoice': 'https://github.com/metavoiceio/metavoice-src',
300
+ }
301
+ # def get_random_split(existing_split=None):
302
+ # choice = random.choice(list(audio_dataset.keys()))
303
+ # if existing_split and choice == existing_split:
304
+ # return get_random_split(choice)
305
+ # else:
306
+ # return choice
307
 
308
+ # def get_random_splits():
309
+ # choice1 = get_random_split()
310
+ # choice2 = get_random_split(choice1)
311
+ # return (choice1, choice2)
312
+ def model_license(name):
313
+ print(name)
314
+ for k, v in AVAILABLE_MODELS.items():
315
+ if k == name:
316
+ if v in model_licenses:
317
+ return model_licenses[v]
318
+ print('---')
319
+ return 'Unknown'
320
+ def get_leaderboard(reveal_prelim = False):
321
+ conn = get_db()
322
+ cursor = conn.cursor()
323
+ sql = 'SELECT name, upvote, downvote FROM model'
324
+ # if not reveal_prelim: sql += ' WHERE EXISTS (SELECT 1 FROM model WHERE (upvote + downvote) > 750)'
325
+ if not reveal_prelim: sql += ' WHERE (upvote + downvote) > 500'
326
+ cursor.execute(sql)
327
+ data = cursor.fetchall()
328
+ df = pd.DataFrame(data, columns=['name', 'upvote', 'downvote'])
329
+ # df['license'] = df['name'].map(model_license)
330
+ df['name'] = df['name'].replace(model_names)
331
+ df['votes'] = df['upvote'] + df['downvote']
332
+ # df['score'] = round((df['upvote'] / df['votes']) * 100, 2) # Percentage score
333
 
334
+ ## ELO SCORE
335
+ df['score'] = 1200
336
+ for i in range(len(df)):
337
+ for j in range(len(df)):
338
+ if i != j:
339
+ expected_a = 1 / (1 + 10 ** ((df['score'][j] - df['score'][i]) / 400))
340
+ expected_b = 1 / (1 + 10 ** ((df['score'][i] - df['score'][j]) / 400))
341
+ actual_a = df['upvote'][i] / df['votes'][i]
342
+ actual_b = df['upvote'][j] / df['votes'][j]
343
+ df.at[i, 'score'] += 32 * (actual_a - expected_a)
344
+ df.at[j, 'score'] += 32 * (actual_b - expected_b)
345
+ df['score'] = round(df['score'])
346
+ ## ELO SCORE
347
+ df = df.sort_values(by='score', ascending=False)
348
+ df['order'] = ['#' + str(i + 1) for i in range(len(df))]
349
+ # df = df[['name', 'score', 'upvote', 'votes']]
350
+ # df = df[['order', 'name', 'score', 'license', 'votes']]
351
+ df = df[['order', 'name', 'score', 'votes']]
352
+ return df
353
+ def mkuuid(uid):
354
+ if not uid:
355
+ uid = uuid.uuid4()
356
+ return uid
357
+ def upvote_model(model, uname):
358
+ conn = get_db()
359
+ cursor = conn.cursor()
360
+ cursor.execute('UPDATE model SET upvote = upvote + 1 WHERE name = ?', (model,))
361
+ if cursor.rowcount == 0:
362
+ cursor.execute('INSERT OR REPLACE INTO model (name, upvote, downvote) VALUES (?, 1, 0)', (model,))
363
+ cursor.execute('INSERT INTO vote (username, model, vote) VALUES (?, ?, ?)', (uname, model, 1,))
364
+ with scheduler.lock:
365
+ conn.commit()
366
+ cursor.close()
367
+ def log_text(text):
368
+ conn = get_db()
369
+ cursor = conn.cursor()
370
+ cursor.execute('INSERT INTO spokentext (spokentext) VALUES (?)', (text,))
371
+ with scheduler.lock:
372
+ conn.commit()
373
+ cursor.close()
374
+ def downvote_model(model, uname):
375
+ conn = get_db()
376
+ cursor = conn.cursor()
377
+ cursor.execute('UPDATE model SET downvote = downvote + 1 WHERE name = ?', (model,))
378
+ if cursor.rowcount == 0:
379
+ cursor.execute('INSERT OR REPLACE INTO model (name, upvote, downvote) VALUES (?, 0, 1)', (model,))
380
+ cursor.execute('INSERT INTO vote (username, model, vote) VALUES (?, ?, ?)', (uname, model, -1,))
381
+ with scheduler.lock:
382
+ conn.commit()
383
+ cursor.close()
384
+
385
+ def a_is_better(model1, model2, userid):
386
+ print("A is better", model1, model2)
387
+ if not model1 in AVAILABLE_MODELS.keys() and not model1 in AVAILABLE_MODELS.values():
388
+ raise gr.Error('Sorry, please try voting again.')
389
+ userid = mkuuid(userid)
390
+ if model1 and model2:
391
+ conn = get_db()
392
+ cursor = conn.cursor()
393
+ cursor.execute('INSERT INTO votelog (username, chosen, rejected) VALUES (?, ?, ?)', (str(userid), model1, model2,))
394
+ with scheduler.lock:
395
+ conn.commit()
396
+ cursor.close()
397
+ upvote_model(model1, str(userid))
398
+ downvote_model(model2, str(userid))
399
+ return reload(model1, model2, userid, chose_a=True)
400
+ def b_is_better(model1, model2, userid):
401
+ print("B is better", model1, model2)
402
+ if not model1 in AVAILABLE_MODELS.keys() and not model1 in AVAILABLE_MODELS.values():
403
+ raise gr.Error('Sorry, please try voting again.')
404
+ userid = mkuuid(userid)
405
+ if model1 and model2:
406
+ conn = get_db()
407
+ cursor = conn.cursor()
408
+ cursor.execute('INSERT INTO votelog (username, chosen, rejected) VALUES (?, ?, ?)', (str(userid), model2, model1,))
409
+ with scheduler.lock:
410
+ conn.commit()
411
+ cursor.close()
412
+ upvote_model(model2, str(userid))
413
+ downvote_model(model1, str(userid))
414
+ return reload(model1, model2, userid, chose_b=True)
415
+ def both_bad(model1, model2, userid):
416
+ userid = mkuuid(userid)
417
+ if model1 and model2:
418
+ downvote_model(model1, str(userid))
419
+ downvote_model(model2, str(userid))
420
+ return reload(model1, model2, userid)
421
+ def both_good(model1, model2, userid):
422
+ userid = mkuuid(userid)
423
+ if model1 and model2:
424
+ upvote_model(model1, str(userid))
425
+ upvote_model(model2, str(userid))
426
+ return reload(model1, model2, userid)
427
+ def reload(chosenmodel1=None, chosenmodel2=None, userid=None, chose_a=False, chose_b=False):
428
+ # Select random splits
429
+ # row = random.choice(list(audio_dataset['train']))
430
+ # options = list(random.choice(list(audio_dataset['train'])).keys())
431
+ # split1, split2 = random.sample(options, 2)
432
+ # choice1, choice2 = (row[split1], row[split2])
433
+ # if chosenmodel1 in model_names:
434
+ # chosenmodel1 = model_names[chosenmodel1]
435
+ # if chosenmodel2 in model_names:
436
+ # chosenmodel2 = model_names[chosenmodel2]
437
+ # out = [
438
+ # (choice1['sampling_rate'], choice1['array']),
439
+ # (choice2['sampling_rate'], choice2['array']),
440
+ # split1,
441
+ # split2
442
+ # ]
443
+ # if userid: out.append(userid)
444
+ # if chosenmodel1: out.append(f'This model was {chosenmodel1}')
445
+ # if chosenmodel2: out.append(f'This model was {chosenmodel2}')
446
+ # return out
447
+ # return (f'This model was {chosenmodel1}', f'This model was {chosenmodel2}', gr.update(visible=False), gr.update(visible=False))
448
+ # return (gr.update(variant='secondary', value=chosenmodel1, interactive=False), gr.update(variant='secondary', value=chosenmodel2, interactive=False))
449
+ out = [
450
+ gr.update(interactive=False, visible=False),
451
+ gr.update(interactive=False, visible=False)
452
+ ]
453
+ if chose_a == True:
454
+ out.append(gr.update(value=f'Your vote: {chosenmodel1}', interactive=False, visible=True))
455
+ out.append(gr.update(value=f'{chosenmodel2}', interactive=False, visible=True))
456
+ else:
457
+ out.append(gr.update(value=f'{chosenmodel1}', interactive=False, visible=True))
458
+ out.append(gr.update(value=f'Your vote: {chosenmodel2}', interactive=False, visible=True))
459
+ out.append(gr.update(visible=True))
460
+ return out
461
+
462
+ with gr.Blocks() as leaderboard:
463
+ gr.Markdown(LDESC)
464
+ # df = gr.Dataframe(interactive=False, value=get_leaderboard())
465
+ df = gr.Dataframe(interactive=False, min_width=0, wrap=True, column_widths=[30, 200, 50, 50])
466
+ with gr.Row():
467
+ reveal_prelim = gr.Checkbox(label="Reveal preliminary results", info="Show all models, including models with very few human ratings.", scale=1)
468
+ reloadbtn = gr.Button("Refresh", scale=3)
469
+ reveal_prelim.input(get_leaderboard, inputs=[reveal_prelim], outputs=[df])
470
+ leaderboard.load(get_leaderboard, inputs=[reveal_prelim], outputs=[df])
471
+ reloadbtn.click(get_leaderboard, inputs=[reveal_prelim], outputs=[df])
472
+ # gr.Markdown("DISCLAIMER: The licenses listed may not be accurate or up to date, you are responsible for checking the licenses before using the models. Also note that some models may have additional usage restrictions.")
473
+
474
+ # with gr.Blocks() as vote:
475
+ # useridstate = gr.State()
476
+ # gr.Markdown(INSTR)
477
+ # # gr.LoginButton()
478
+ # with gr.Row():
479
+ # gr.HTML('<div align="left"><h3>Model A</h3></div>')
480
+ # gr.HTML('<div align="right"><h3>Model B</h3></div>')
481
+ # model1 = gr.Textbox(interactive=False, visible=False, lines=1, max_lines=1)
482
+ # model2 = gr.Textbox(interactive=False, visible=False, lines=1, max_lines=1)
483
+ # # with gr.Group():
484
+ # # with gr.Row():
485
+ # # prevmodel1 = gr.Textbox(interactive=False, show_label=False, container=False, value="Vote to reveal model A")
486
+ # # prevmodel2 = gr.Textbox(interactive=False, show_label=False, container=False, value="Vote to reveal model B", text_align="right")
487
+ # # with gr.Row():
488
+ # # aud1 = gr.Audio(interactive=False, show_label=False, show_download_button=False, show_share_button=False, waveform_options={'waveform_progress_color': '#3C82F6'})
489
+ # # aud2 = gr.Audio(interactive=False, show_label=False, show_download_button=False, show_share_button=False, waveform_options={'waveform_progress_color': '#3C82F6'})
490
+ # with gr.Group():
491
+ # with gr.Row():
492
+ # with gr.Column():
493
+ # with gr.Group():
494
+ # prevmodel1 = gr.Textbox(interactive=False, show_label=False, container=False, value="Vote to reveal model A", lines=1, max_lines=1)
495
+ # aud1 = gr.Audio(interactive=False, show_label=False, show_download_button=False, show_share_button=False, waveform_options={'waveform_progress_color': '#3C82F6'})
496
+ # with gr.Column():
497
+ # with gr.Group():
498
+ # prevmodel2 = gr.Textbox(interactive=False, show_label=False, container=False, value="Vote to reveal model B", text_align="right", lines=1, max_lines=1)
499
+ # aud2 = gr.Audio(interactive=False, show_label=False, show_download_button=False, show_share_button=False, waveform_options={'waveform_progress_color': '#3C82F6'})
500
+
501
+
502
+ # with gr.Row():
503
+ # abetter = gr.Button("A is Better", variant='primary', scale=4)
504
+ # # skipbtn = gr.Button("Skip", scale=1)
505
+ # bbetter = gr.Button("B is Better", variant='primary', scale=4)
506
+ # with gr.Row():
507
+ # bothbad = gr.Button("Both are Bad", scale=2)
508
+ # skipbtn = gr.Button("Skip", scale=1)
509
+ # bothgood = gr.Button("Both are Good", scale=2)
510
+ # outputs = [aud1, aud2, model1, model2, useridstate, prevmodel1, prevmodel2]
511
+ # abetter.click(a_is_better, outputs=outputs, inputs=[model1, model2, useridstate])
512
+ # bbetter.click(b_is_better, outputs=outputs, inputs=[model1, model2, useridstate])
513
+ # skipbtn.click(b_is_better, outputs=outputs, inputs=[model1, model2, useridstate])
514
+
515
+ # bothbad.click(both_bad, outputs=outputs, inputs=[model1, model2, useridstate])
516
+ # bothgood.click(both_good, outputs=outputs, inputs=[model1, model2, useridstate])
517
+
518
+ # vote.load(reload, outputs=[aud1, aud2, model1, model2])
519
+ def doloudnorm(path):
520
+ data, rate = sf.read(path)
521
+ meter = pyln.Meter(rate)
522
+ loudness = meter.integrated_loudness(data)
523
+ loudness_normalized_audio = pyln.normalize.loudness(data, loudness, -12.0)
524
+ sf.write(path, loudness_normalized_audio, rate)
525
+
526
+ def doresample(path_to_wav):
527
+ pass
528
+ ##########################
529
+ # 2x speedup (hopefully) #
530
+ ##########################
531
+
532
+ def synthandreturn(text):
533
+ text = text.strip()
534
+ if len(text) > MAX_SAMPLE_TXT_LENGTH:
535
+ raise gr.Error(f'You exceeded the limit of {MAX_SAMPLE_TXT_LENGTH} characters')
536
+ if len(text) < MIN_SAMPLE_TXT_LENGTH:
537
+ raise gr.Error(f'Please input a text longer than {MIN_SAMPLE_TXT_LENGTH} characters')
538
+ if (
539
+ # test toxicity if not prepared text
540
+ text not in sents
541
+ and toxicity.predict(text)['toxicity'] > 0.8
542
+ ):
543
+ print(f'Detected toxic content! "{text}"')
544
+ raise gr.Error('Your text failed the toxicity test')
545
+ if not text:
546
+ raise gr.Error(f'You did not enter any text')
547
+ # Check language
548
+ try:
549
+ if not detect(text) == "en":
550
+ gr.Warning('Warning: The input text may not be in English')
551
+ except:
552
+ pass
553
+ # Get two random models
554
+ mdl1, mdl2 = random.sample(list(AVAILABLE_MODELS.keys()), 2)
555
+ log_text(text)
556
+ print("[debug] Using", mdl1, mdl2)
557
+ def predict_and_update_result(text, model, result_storage):
558
+ try:
559
+ if model in AVAILABLE_MODELS:
560
+ result = router.predict(text, AVAILABLE_MODELS[model].lower(), api_name="/synthesize")
561
+ else:
562
+ result = router.predict(text, model.lower(), api_name="/synthesize")
563
+ except:
564
+ raise gr.Error('Unable to call API, please try again :)')
565
+ print('Done with', model)
566
+ # try:
567
+ # doresample(result)
568
+ # except:
569
+ # pass
570
+ try:
571
+ with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as f:
572
+ audio = AudioSegment.from_file(result)
573
+ current_sr = audio.frame_rate
574
+ if current_sr > 24000:
575
+ audio = audio.set_frame_rate(24000)
576
+ try:
577
+ print('Trying to normalize audio')
578
+ audio = match_target_amplitude(audio, -20)
579
+ except:
580
+ print('[WARN] Unable to normalize audio')
581
+ audio.export(f.name, format="wav")
582
+ os.unlink(result)
583
+ result = f.name
584
+ except:
585
+ pass
586
+ if model in AVAILABLE_MODELS.keys(): model = AVAILABLE_MODELS[model]
587
+ print(model)
588
+ print(f"Running model {model}")
589
+ result_storage[model] = result
590
+ # try:
591
+ # doloudnorm(result)
592
+ # except:
593
+ # pass
594
+ mdl1k = mdl1
595
+ mdl2k = mdl2
596
+ print(mdl1k, mdl2k)
597
+ if mdl1 in AVAILABLE_MODELS.keys(): mdl1k=AVAILABLE_MODELS[mdl1]
598
+ if mdl2 in AVAILABLE_MODELS.keys(): mdl2k=AVAILABLE_MODELS[mdl2]
599
+ results = {}
600
+ print(f"Sending models {mdl1k} and {mdl2k} to API")
601
+ thread1 = threading.Thread(target=predict_and_update_result, args=(text, mdl1k, results))
602
+ thread2 = threading.Thread(target=predict_and_update_result, args=(text, mdl2k, results))
603
+
604
+ thread1.start()
605
+ thread2.start()
606
+ thread1.join()
607
+ thread2.join()
608
+ #debug
609
+ # print(results)
610
+ # print(list(results.keys())[0])
611
+ # y, sr = librosa.load(results[list(results.keys())[0]], sr=None)
612
+ # print(sr)
613
+ # print(list(results.keys())[1])
614
+ # y, sr = librosa.load(results[list(results.keys())[1]], sr=None)
615
+ # print(sr)
616
+ #debug
617
+ # outputs = [text, btn, r2, model1, model2, aud1, aud2, abetter, bbetter, prevmodel1, prevmodel2, nxtroundbtn]
618
+
619
+ print(f"Retrieving models {mdl1k} and {mdl2k} from API")
620
+ return (
621
+ text,
622
+ "Synthesize",
623
+ gr.update(visible=True), # r2
624
+ mdl1, # model1
625
+ mdl2, # model2
626
+ gr.update(visible=True, value=results[mdl1k]), # aud1
627
+ gr.update(visible=True, value=results[mdl2k]), # aud2
628
+ gr.update(visible=True, interactive=False), #abetter
629
+ gr.update(visible=True, interactive=False), #bbetter
630
+ gr.update(visible=False), #prevmodel1
631
+ gr.update(visible=False), #prevmodel2
632
+ gr.update(visible=False), #nxt round btn
633
  )
634
+ # return (
635
+ # text,
636
+ # "Synthesize",
637
+ # gr.update(visible=True), # r2
638
+ # mdl1, # model1
639
+ # mdl2, # model2
640
+ # # 'Vote to reveal model A', # prevmodel1
641
+ # gr.update(visible=True, value=router.predict(
642
+ # text,
643
+ # AVAILABLE_MODELS[mdl1],
644
+ # api_name="/synthesize"
645
+ # )), # aud1
646
+ # # 'Vote to reveal model B', # prevmodel2
647
+ # gr.update(visible=True, value=router.predict(
648
+ # text,
649
+ # AVAILABLE_MODELS[mdl2],
650
+ # api_name="/synthesize"
651
+ # )), # aud2
652
+ # gr.update(visible=True, interactive=True),
653
+ # gr.update(visible=True, interactive=True),
654
+ # gr.update(visible=False),
655
+ # gr.update(visible=False),
656
+ # gr.update(visible=False), #nxt round btn
657
+ # )
658
 
659
+ def unlock_vote(btn_index, aplayed, bplayed):
660
+ # sample played
661
+ if btn_index == 0:
662
+ aplayed = gr.State(value=True)
663
+ if btn_index == 1:
664
+ bplayed = gr.State(value=True)
665
 
666
+ # both audio samples played
667
+ if bool(aplayed) and bool(bplayed):
668
+ print('Both audio samples played, voting unlocked')
669
+ return [gr.update(interactive=True), gr.update(interactive=True), gr.update(), gr.update()]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
670
 
671
+ return [gr.update(), gr.update(), aplayed, bplayed]
672
+
673
+ def randomsent():
674
+ return random.choice(sents), '🎲'
675
+ def clear_stuff():
676
+ return "", "Synthesize", gr.update(visible=False), '', '', gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
677
+
678
+ def disable():
679
+ return [gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False)]
680
+ def enable():
681
+ return [gr.update(interactive=True), gr.update(interactive=True), gr.update(interactive=True)]
682
+ with gr.Blocks() as vote:
683
+ # sample played
684
+ #aplayed = gr.State(value=False)
685
+ #bplayed = gr.State(value=False)
686
+ # voter ID
687
+ useridstate = gr.State()
688
+ gr.Markdown(INSTR)
689
+ with gr.Group():
690
+ with gr.Row():
691
+ text = gr.Textbox(container=False, show_label=False, placeholder="Enter text to synthesize", lines=1, max_lines=1, scale=9999999, min_width=0)
692
+ randomt = gr.Button('🎲', scale=0, min_width=0, variant='tool')
693
+ randomt.click(randomsent, outputs=[text, randomt])
694
+ btn = gr.Button("Synthesize", variant='primary')
695
+ model1 = gr.Textbox(interactive=False, lines=1, max_lines=1, visible=False)
696
+ #model1 = gr.Textbox(interactive=False, lines=1, max_lines=1, visible=True)
697
+ model2 = gr.Textbox(interactive=False, lines=1, max_lines=1, visible=False)
698
+ #model2 = gr.Textbox(interactive=False, lines=1, max_lines=1, visible=True)
699
+ with gr.Row(visible=False) as r2:
700
+ with gr.Column():
701
+ with gr.Group():
702
+ aud1 = gr.Audio(interactive=False, show_label=False, show_download_button=False, show_share_button=False, waveform_options={'waveform_progress_color': '#3C82F6'})
703
+ abetter = gr.Button("A is better", variant='primary')
704
+ prevmodel1 = gr.Textbox(interactive=False, show_label=False, container=False, value="Vote to reveal model A", text_align="center", lines=1, max_lines=1, visible=False)
705
+ with gr.Column():
706
+ with gr.Group():
707
+ aud2 = gr.Audio(interactive=False, show_label=False, show_download_button=False, show_share_button=False, waveform_options={'waveform_progress_color': '#3C82F6'})
708
+ bbetter = gr.Button("B is better", variant='primary')
709
+ prevmodel2 = gr.Textbox(interactive=False, show_label=False, container=False, value="Vote to reveal model B", text_align="center", lines=1, max_lines=1, visible=False)
710
+ nxtroundbtn = gr.Button('Next round', visible=False)
711
+ # outputs = [text, btn, r2, model1, model2, prevmodel1, aud1, prevmodel2, aud2, abetter, bbetter]
712
+ outputs = [
713
+ text,
714
+ btn,
715
+ r2,
716
+ model1,
717
+ model2,
718
+ aud1,
719
+ aud2,
720
+ abetter,
721
+ bbetter,
722
+ prevmodel1,
723
+ prevmodel2,
724
+ nxtroundbtn
725
+ ]
726
+ """
727
+ text,
728
+ "Synthesize",
729
+ gr.update(visible=True), # r2
730
+ mdl1, # model1
731
+ mdl2, # model2
732
+ gr.update(visible=True, value=results[mdl1]), # aud1
733
+ gr.update(visible=True, value=results[mdl2]), # aud2
734
+ gr.update(visible=True, interactive=False), #abetter
735
+ gr.update(visible=True, interactive=False), #bbetter
736
+ gr.update(visible=False), #prevmodel1
737
+ gr.update(visible=False), #prevmodel2
738
+ gr.update(visible=False), #nxt round btn"""
739
+ btn.click(disable, outputs=[btn, abetter, bbetter]).then(synthandreturn, inputs=[text], outputs=outputs).then(enable, outputs=[btn, abetter, bbetter])
740
+ nxtroundbtn.click(clear_stuff, outputs=outputs)
741
+
742
+ # Allow interaction with the vote buttons only when both audio samples have finished playing
743
+ #aud1.stop(unlock_vote, outputs=[abetter, bbetter, aplayed, bplayed], inputs=[gr.State(value=0), aplayed, bplayed])
744
+ #aud2.stop(unlock_vote, outputs=[abetter, bbetter, aplayed, bplayed], inputs=[gr.State(value=1), aplayed, bplayed])
745
+
746
+ # nxt_outputs = [prevmodel1, prevmodel2, abetter, bbetter]
747
+ nxt_outputs = [abetter, bbetter, prevmodel1, prevmodel2, nxtroundbtn]
748
+ abetter.click(a_is_better, outputs=nxt_outputs, inputs=[model1, model2, useridstate])
749
+ bbetter.click(b_is_better, outputs=nxt_outputs, inputs=[model1, model2, useridstate])
750
+ # skipbtn.click(b_is_better, outputs=outputs, inputs=[model1, model2, useridstate])
751
+
752
+ # bothbad.click(both_bad, outputs=outputs, inputs=[model1, model2, useridstate])
753
+ # bothgood.click(both_good, outputs=outputs, inputs=[model1, model2, useridstate])
754
+
755
+ # vote.load(reload, outputs=[aud1, aud2, model1, model2])
756
+
757
+ with gr.Blocks() as about:
758
+ gr.Markdown(ABOUT)
759
+ # with gr.Blocks() as admin:
760
+ # rdb = gr.Button("Reload Audio Dataset")
761
+ # # rdb.click(reload_audio_dataset, outputs=rdb)
762
+ # with gr.Group():
763
+ # dbtext = gr.Textbox(label="Type \"delete db\" to confirm", placeholder="delete db")
764
+ # ddb = gr.Button("Delete DB")
765
+ # ddb.click(del_db, inputs=dbtext, outputs=ddb)
766
+ with gr.Blocks(theme=theme, css="footer {visibility: hidden}textbox{resize:none}", title="TTS Arena") as demo:
767
+ gr.Markdown(DESCR)
768
+ # gr.TabbedInterface([vote, leaderboard, about, admin], ['Vote', 'Leaderboard', 'About', 'Admin (ONLY IN BETA)'])
769
+ gr.TabbedInterface([vote, leaderboard, about], ['πŸ—³οΈ Vote', 'πŸ† Leaderboard', 'πŸ“„ About'])
770
+ if CITATION_TEXT:
771
+ with gr.Row():
772
+ with gr.Accordion("Citation", open=False):
773
+ gr.Markdown(f"If you use this data in your publication, please cite us!\n\nCopy the BibTeX citation to cite this source:\n\n```bibtext\n{CITATION_TEXT}\n```\n\nPlease remember that all generated audio clips should be assumed unsuitable for redistribution or commercial use.")
774
+
775
+
776
+ demo.queue(api_open=False, default_concurrency_limit=40).launch(show_api=False)