Spaces:
Running
Running
matdmiller
commited on
Commit
·
8dde6b0
1
Parent(s):
78370f2
fix audio file safari
Browse files
app.ipynb
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
-
"execution_count":
|
6 |
"id": "3bedf0dc-8d8e-4ede-a9e6-b8f35136aa00",
|
7 |
"metadata": {},
|
8 |
"outputs": [],
|
@@ -12,19 +12,10 @@
|
|
12 |
},
|
13 |
{
|
14 |
"cell_type": "code",
|
15 |
-
"execution_count":
|
16 |
"id": "667802a7-0f36-4136-a381-e66210b20462",
|
17 |
"metadata": {},
|
18 |
-
"outputs": [
|
19 |
-
{
|
20 |
-
"name": "stdout",
|
21 |
-
"output_type": "stream",
|
22 |
-
"text": [
|
23 |
-
"OPENAI_API_KEY environment variable was found.\n",
|
24 |
-
"GRADIO_PASSWORD environment variable was found.\n"
|
25 |
-
]
|
26 |
-
}
|
27 |
-
],
|
28 |
"source": [
|
29 |
"#| export\n",
|
30 |
"#tts_openai_secrets.py content:\n",
|
@@ -53,7 +44,7 @@
|
|
53 |
},
|
54 |
{
|
55 |
"cell_type": "code",
|
56 |
-
"execution_count":
|
57 |
"id": "4d9863fc-969e-409b-8e20-b9c3cd2cc3e7",
|
58 |
"metadata": {},
|
59 |
"outputs": [],
|
@@ -67,7 +58,7 @@
|
|
67 |
},
|
68 |
{
|
69 |
"cell_type": "code",
|
70 |
-
"execution_count":
|
71 |
"id": "4f486d3a",
|
72 |
"metadata": {},
|
73 |
"outputs": [],
|
@@ -81,6 +72,8 @@
|
|
81 |
"from math import ceil\n",
|
82 |
"from multiprocessing.pool import ThreadPool\n",
|
83 |
"from functools import partial\n",
|
|
|
|
|
84 |
"from tenacity import (\n",
|
85 |
" retry,\n",
|
86 |
" stop_after_attempt,\n",
|
@@ -90,18 +83,23 @@
|
|
90 |
},
|
91 |
{
|
92 |
"cell_type": "code",
|
93 |
-
"execution_count":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
"id": "0ffd33b4-cb9b-4c01-bff6-4c3102854ab6",
|
95 |
"metadata": {},
|
96 |
-
"outputs": [
|
97 |
-
{
|
98 |
-
"name": "stdout",
|
99 |
-
"output_type": "stream",
|
100 |
-
"text": [
|
101 |
-
"successfully got tts model list: ['tts-1-hd-1106', 'tts-1-hd', 'tts-1', 'tts-1-1106']\n"
|
102 |
-
]
|
103 |
-
}
|
104 |
-
],
|
105 |
"source": [
|
106 |
"#| export\n",
|
107 |
"try:\n",
|
@@ -113,7 +111,7 @@
|
|
113 |
},
|
114 |
{
|
115 |
"cell_type": "code",
|
116 |
-
"execution_count":
|
117 |
"id": "2ddbca5d-4b04-43ab-afaf-430802980e78",
|
118 |
"metadata": {},
|
119 |
"outputs": [],
|
@@ -124,7 +122,7 @@
|
|
124 |
},
|
125 |
{
|
126 |
"cell_type": "code",
|
127 |
-
"execution_count":
|
128 |
"id": "8eb7e7d5-7121-4762-b8d1-e5a9539e2b36",
|
129 |
"metadata": {},
|
130 |
"outputs": [],
|
@@ -135,7 +133,7 @@
|
|
135 |
},
|
136 |
{
|
137 |
"cell_type": "code",
|
138 |
-
"execution_count":
|
139 |
"id": "52d373be-3a79-412e-8ca2-92bb443fa52d",
|
140 |
"metadata": {},
|
141 |
"outputs": [],
|
@@ -147,7 +145,7 @@
|
|
147 |
},
|
148 |
{
|
149 |
"cell_type": "code",
|
150 |
-
"execution_count":
|
151 |
"id": "24674094-4d47-4e48-b591-55faabcff8df",
|
152 |
"metadata": {},
|
153 |
"outputs": [],
|
@@ -188,7 +186,7 @@
|
|
188 |
},
|
189 |
{
|
190 |
"cell_type": "code",
|
191 |
-
"execution_count":
|
192 |
"id": "e6224ae5-3792-42b2-8392-3abd42998a50",
|
193 |
"metadata": {},
|
194 |
"outputs": [],
|
@@ -213,20 +211,26 @@
|
|
213 |
" # Concatenate this segment to the combined segment\n",
|
214 |
" combined += audio_segment\n",
|
215 |
"\n",
|
216 |
-
"
|
217 |
-
" #
|
218 |
-
"
|
219 |
-
"
|
|
|
|
|
|
|
|
|
220 |
"\n",
|
221 |
-
" #
|
222 |
-
" combined_mp3.seek(0)\n",
|
223 |
"\n",
|
224 |
-
"
|
|
|
|
|
|
|
225 |
]
|
226 |
},
|
227 |
{
|
228 |
"cell_type": "code",
|
229 |
-
"execution_count":
|
230 |
"id": "4691703d-ed0f-4481-8006-b2906289b780",
|
231 |
"metadata": {},
|
232 |
"outputs": [],
|
@@ -246,7 +250,7 @@
|
|
246 |
},
|
247 |
{
|
248 |
"cell_type": "code",
|
249 |
-
"execution_count":
|
250 |
"id": "e34bb4aa-698c-4452-8cda-bd02b38f7122",
|
251 |
"metadata": {},
|
252 |
"outputs": [],
|
@@ -289,14 +293,14 @@
|
|
289 |
},
|
290 |
{
|
291 |
"cell_type": "code",
|
292 |
-
"execution_count":
|
293 |
"id": "5388e860",
|
294 |
"metadata": {},
|
295 |
"outputs": [],
|
296 |
"source": [
|
297 |
"#| export\n",
|
298 |
"def create_speech(input_text, model='tts-1', voice='alloy', profile: gr.OAuthProfile|None=None, progress=gr.Progress()):\n",
|
299 |
-
" assert authorized() is not None,'Unauthorized M'\n",
|
300 |
" # Split the input text into chunks\n",
|
301 |
" chunks = split_text(input_text)\n",
|
302 |
"\n",
|
@@ -340,7 +344,7 @@
|
|
340 |
},
|
341 |
{
|
342 |
"cell_type": "code",
|
343 |
-
"execution_count":
|
344 |
"id": "236dd8d3-4364-4731-af93-7dcdec6f18a1",
|
345 |
"metadata": {},
|
346 |
"outputs": [],
|
@@ -352,7 +356,7 @@
|
|
352 |
},
|
353 |
{
|
354 |
"cell_type": "code",
|
355 |
-
"execution_count":
|
356 |
"id": "0523a158-ee07-48b3-9350-ee39d4deee7f",
|
357 |
"metadata": {},
|
358 |
"outputs": [],
|
@@ -369,7 +373,7 @@
|
|
369 |
},
|
370 |
{
|
371 |
"cell_type": "code",
|
372 |
-
"execution_count":
|
373 |
"id": "b5b29507-92bc-453d-bcc5-6402c17e9a0d",
|
374 |
"metadata": {},
|
375 |
"outputs": [],
|
@@ -386,19 +390,10 @@
|
|
386 |
},
|
387 |
{
|
388 |
"cell_type": "code",
|
389 |
-
"execution_count":
|
390 |
"id": "e4fb3159-579b-4271-bc96-4cd1e2816eca",
|
391 |
"metadata": {},
|
392 |
-
"outputs": [
|
393 |
-
{
|
394 |
-
"name": "stderr",
|
395 |
-
"output_type": "stream",
|
396 |
-
"text": [
|
397 |
-
"/Users/mathewmiller/anaconda3/envs/gradio1/lib/python3.11/site-packages/gradio/oauth.py:138: UserWarning: Gradio does not support OAuth features outside of a Space environment. To help you debug your app locally, the login and logout buttons are mocked with your profile. To make it work, your machine must be logged in to Huggingface.\n",
|
398 |
-
" warnings.warn(\n"
|
399 |
-
]
|
400 |
-
}
|
401 |
-
],
|
402 |
"source": [
|
403 |
"#| export\n",
|
404 |
"with gr.Blocks(title='OpenAI TTS', head='OpenAI TTS') as app:\n",
|
@@ -429,7 +424,7 @@
|
|
429 |
},
|
430 |
{
|
431 |
"cell_type": "code",
|
432 |
-
"execution_count":
|
433 |
"id": "a00648a1-891b-470b-9959-f5d502055713",
|
434 |
"metadata": {},
|
435 |
"outputs": [],
|
@@ -492,7 +487,7 @@
|
|
492 |
},
|
493 |
{
|
494 |
"cell_type": "code",
|
495 |
-
"execution_count":
|
496 |
"id": "0420310d-930b-4904-8bd4-3458ad8bdbd3",
|
497 |
"metadata": {},
|
498 |
"outputs": [],
|
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
+
"execution_count": null,
|
6 |
"id": "3bedf0dc-8d8e-4ede-a9e6-b8f35136aa00",
|
7 |
"metadata": {},
|
8 |
"outputs": [],
|
|
|
12 |
},
|
13 |
{
|
14 |
"cell_type": "code",
|
15 |
+
"execution_count": null,
|
16 |
"id": "667802a7-0f36-4136-a381-e66210b20462",
|
17 |
"metadata": {},
|
18 |
+
"outputs": [],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
"source": [
|
20 |
"#| export\n",
|
21 |
"#tts_openai_secrets.py content:\n",
|
|
|
44 |
},
|
45 |
{
|
46 |
"cell_type": "code",
|
47 |
+
"execution_count": null,
|
48 |
"id": "4d9863fc-969e-409b-8e20-b9c3cd2cc3e7",
|
49 |
"metadata": {},
|
50 |
"outputs": [],
|
|
|
58 |
},
|
59 |
{
|
60 |
"cell_type": "code",
|
61 |
+
"execution_count": null,
|
62 |
"id": "4f486d3a",
|
63 |
"metadata": {},
|
64 |
"outputs": [],
|
|
|
72 |
"from math import ceil\n",
|
73 |
"from multiprocessing.pool import ThreadPool\n",
|
74 |
"from functools import partial\n",
|
75 |
+
"from pathlib import Path\n",
|
76 |
+
"import uuid\n",
|
77 |
"from tenacity import (\n",
|
78 |
" retry,\n",
|
79 |
" stop_after_attempt,\n",
|
|
|
83 |
},
|
84 |
{
|
85 |
"cell_type": "code",
|
86 |
+
"execution_count": null,
|
87 |
+
"id": "ecb7f207-0fc2-4d19-a313-356c05776832",
|
88 |
+
"metadata": {},
|
89 |
+
"outputs": [],
|
90 |
+
"source": [
|
91 |
+
"#| export\n",
|
92 |
+
"TEMP = os.environ['TMPDIR']\n",
|
93 |
+
"TEMP_DIR = Path(TEMP)\n",
|
94 |
+
"print('TEMP Dir:', TEMP_DIR)"
|
95 |
+
]
|
96 |
+
},
|
97 |
+
{
|
98 |
+
"cell_type": "code",
|
99 |
+
"execution_count": null,
|
100 |
"id": "0ffd33b4-cb9b-4c01-bff6-4c3102854ab6",
|
101 |
"metadata": {},
|
102 |
+
"outputs": [],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
"source": [
|
104 |
"#| export\n",
|
105 |
"try:\n",
|
|
|
111 |
},
|
112 |
{
|
113 |
"cell_type": "code",
|
114 |
+
"execution_count": null,
|
115 |
"id": "2ddbca5d-4b04-43ab-afaf-430802980e78",
|
116 |
"metadata": {},
|
117 |
"outputs": [],
|
|
|
122 |
},
|
123 |
{
|
124 |
"cell_type": "code",
|
125 |
+
"execution_count": null,
|
126 |
"id": "8eb7e7d5-7121-4762-b8d1-e5a9539e2b36",
|
127 |
"metadata": {},
|
128 |
"outputs": [],
|
|
|
133 |
},
|
134 |
{
|
135 |
"cell_type": "code",
|
136 |
+
"execution_count": null,
|
137 |
"id": "52d373be-3a79-412e-8ca2-92bb443fa52d",
|
138 |
"metadata": {},
|
139 |
"outputs": [],
|
|
|
145 |
},
|
146 |
{
|
147 |
"cell_type": "code",
|
148 |
+
"execution_count": null,
|
149 |
"id": "24674094-4d47-4e48-b591-55faabcff8df",
|
150 |
"metadata": {},
|
151 |
"outputs": [],
|
|
|
186 |
},
|
187 |
{
|
188 |
"cell_type": "code",
|
189 |
+
"execution_count": null,
|
190 |
"id": "e6224ae5-3792-42b2-8392-3abd42998a50",
|
191 |
"metadata": {},
|
192 |
"outputs": [],
|
|
|
211 |
" # Concatenate this segment to the combined segment\n",
|
212 |
" combined += audio_segment\n",
|
213 |
"\n",
|
214 |
+
" #### Return Bytes Method\n",
|
215 |
+
" # # Export the combined segment to a new mp3 file\n",
|
216 |
+
" # # Use a BytesIO object to handle this in memory\n",
|
217 |
+
" # combined_mp3 = io.BytesIO()\n",
|
218 |
+
" # combined.export(combined_mp3, format=\"mp3\")\n",
|
219 |
+
"\n",
|
220 |
+
" # # Seek to the start so it's ready for reading\n",
|
221 |
+
" # combined_mp3.seek(0)\n",
|
222 |
"\n",
|
223 |
+
" # return combined_mp3.getvalue()\n",
|
|
|
224 |
"\n",
|
225 |
+
" #### Return Filepath Method\n",
|
226 |
+
" filepath = TEMP_DIR/(str(uuid.uuid4())+'.mp3')\n",
|
227 |
+
" combined.export(filepath, format=\"mp3\")\n",
|
228 |
+
" return str(filepath)"
|
229 |
]
|
230 |
},
|
231 |
{
|
232 |
"cell_type": "code",
|
233 |
+
"execution_count": null,
|
234 |
"id": "4691703d-ed0f-4481-8006-b2906289b780",
|
235 |
"metadata": {},
|
236 |
"outputs": [],
|
|
|
250 |
},
|
251 |
{
|
252 |
"cell_type": "code",
|
253 |
+
"execution_count": null,
|
254 |
"id": "e34bb4aa-698c-4452-8cda-bd02b38f7122",
|
255 |
"metadata": {},
|
256 |
"outputs": [],
|
|
|
293 |
},
|
294 |
{
|
295 |
"cell_type": "code",
|
296 |
+
"execution_count": null,
|
297 |
"id": "5388e860",
|
298 |
"metadata": {},
|
299 |
"outputs": [],
|
300 |
"source": [
|
301 |
"#| export\n",
|
302 |
"def create_speech(input_text, model='tts-1', voice='alloy', profile: gr.OAuthProfile|None=None, progress=gr.Progress()):\n",
|
303 |
+
" assert authorized(profile) is not None,'Unauthorized M'\n",
|
304 |
" # Split the input text into chunks\n",
|
305 |
" chunks = split_text(input_text)\n",
|
306 |
"\n",
|
|
|
344 |
},
|
345 |
{
|
346 |
"cell_type": "code",
|
347 |
+
"execution_count": null,
|
348 |
"id": "236dd8d3-4364-4731-af93-7dcdec6f18a1",
|
349 |
"metadata": {},
|
350 |
"outputs": [],
|
|
|
356 |
},
|
357 |
{
|
358 |
"cell_type": "code",
|
359 |
+
"execution_count": null,
|
360 |
"id": "0523a158-ee07-48b3-9350-ee39d4deee7f",
|
361 |
"metadata": {},
|
362 |
"outputs": [],
|
|
|
373 |
},
|
374 |
{
|
375 |
"cell_type": "code",
|
376 |
+
"execution_count": null,
|
377 |
"id": "b5b29507-92bc-453d-bcc5-6402c17e9a0d",
|
378 |
"metadata": {},
|
379 |
"outputs": [],
|
|
|
390 |
},
|
391 |
{
|
392 |
"cell_type": "code",
|
393 |
+
"execution_count": null,
|
394 |
"id": "e4fb3159-579b-4271-bc96-4cd1e2816eca",
|
395 |
"metadata": {},
|
396 |
+
"outputs": [],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
397 |
"source": [
|
398 |
"#| export\n",
|
399 |
"with gr.Blocks(title='OpenAI TTS', head='OpenAI TTS') as app:\n",
|
|
|
424 |
},
|
425 |
{
|
426 |
"cell_type": "code",
|
427 |
+
"execution_count": null,
|
428 |
"id": "a00648a1-891b-470b-9959-f5d502055713",
|
429 |
"metadata": {},
|
430 |
"outputs": [],
|
|
|
487 |
},
|
488 |
{
|
489 |
"cell_type": "code",
|
490 |
+
"execution_count": 53,
|
491 |
"id": "0420310d-930b-4904-8bd4-3458ad8bdbd3",
|
492 |
"metadata": {},
|
493 |
"outputs": [],
|
app.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
# AUTOGENERATED! DO NOT EDIT! File to edit: app.ipynb.
|
2 |
|
3 |
# %% auto 0
|
4 |
-
__all__ = ['secret_import_failed', '
|
5 |
-
'queue_kwargs', 'split_text', 'concatenate_mp3', 'create_speech_openai', 'create_speech2',
|
6 |
-
'get_input_text_len', 'get_generation_cost', 'authorized']
|
7 |
|
8 |
# %% app.ipynb 1
|
9 |
#tts_openai_secrets.py content:
|
@@ -38,6 +38,8 @@ from datetime import datetime
|
|
38 |
from math import ceil
|
39 |
from multiprocessing.pool import ThreadPool
|
40 |
from functools import partial
|
|
|
|
|
41 |
from tenacity import (
|
42 |
retry,
|
43 |
stop_after_attempt,
|
@@ -45,24 +47,29 @@ from tenacity import (
|
|
45 |
) # for exponential backoff
|
46 |
|
47 |
# %% app.ipynb 4
|
|
|
|
|
|
|
|
|
|
|
48 |
try:
|
49 |
tts_models = [o.id for o in openai.models.list().data if 'tts' in o.id]
|
50 |
print('successfully got tts model list:', tts_models)
|
51 |
except:
|
52 |
tts_models = ['tts-1']
|
53 |
|
54 |
-
# %% app.ipynb
|
55 |
tts_voices = ['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer']
|
56 |
|
57 |
-
# %% app.ipynb
|
58 |
clean_text_prompt = """Your job is to clean up text that is going to be fed into a text to speech (TTS) model. You must remove parts of the text that would not normally be spoken such as reference marks `[1]`, spurious citations such as `(Reddy et al., 2021; Wu et al., 2022; Chang et al., 2022; Kondratyuk et al., 2023)` and any other part of the text that is not normally spoken. Please also clean up sections and headers so they are on new lines with proper numbering. You must also clean up any math formulas that are salvageable from being copied from a scientific paper. If they are garbled and do not make sense then remove them. You must carefully perform the text cleanup so it is translated into speech that is easy to listen to however you must not modify the text otherwise. It is critical that you repeat all of the text without modifications except for the cleanup activities you've been instructed to do. Also you must clean all of the text you are given, you may not omit any of it or stop the cleanup task early."""
|
59 |
|
60 |
|
61 |
-
# %% app.ipynb
|
62 |
#Number of threads created PER USER REQUEST. This throttels the # of API requests PER USER request. This is in ADDITION to the Gradio threads.
|
63 |
OPENAI_CLIENT_TTS_THREADS = 10
|
64 |
|
65 |
-
# %% app.ipynb
|
66 |
def split_text(input_text, max_length=4000, lookback=1000):
|
67 |
# If the text is shorter than the max_length, return it as is
|
68 |
if len(input_text) <= max_length:
|
@@ -95,7 +102,7 @@ def split_text(input_text, max_length=4000, lookback=1000):
|
|
95 |
|
96 |
return chunks
|
97 |
|
98 |
-
# %% app.ipynb
|
99 |
def concatenate_mp3(mp3_files):
|
100 |
if len(mp3_files) == 1:
|
101 |
return mp3_files[0]
|
@@ -115,17 +122,23 @@ def concatenate_mp3(mp3_files):
|
|
115 |
# Concatenate this segment to the combined segment
|
116 |
combined += audio_segment
|
117 |
|
118 |
-
|
119 |
-
#
|
120 |
-
|
121 |
-
|
|
|
122 |
|
123 |
-
# Seek to the start so it's ready for reading
|
124 |
-
combined_mp3.seek(0)
|
125 |
|
126 |
-
return combined_mp3.getvalue()
|
127 |
|
128 |
-
|
|
|
|
|
|
|
|
|
|
|
129 |
def create_speech_openai(chunk_idx, input, model='tts-1', voice='alloy', speed=1.0, **kwargs):
|
130 |
client = openai.OpenAI()
|
131 |
|
@@ -137,7 +150,7 @@ def create_speech_openai(chunk_idx, input, model='tts-1', voice='alloy', speed=1
|
|
137 |
client.close()
|
138 |
return chunk_idx, response.content
|
139 |
|
140 |
-
# %% app.ipynb
|
141 |
def create_speech2(input_text, model='tts-1', voice='alloy', profile: gr.OAuthProfile|None=None, progress=gr.Progress(), **kwargs):
|
142 |
print('cs2-profile:',profile)
|
143 |
assert authorized(profile) is not None,'Unauthorized M'
|
@@ -173,9 +186,9 @@ def create_speech2(input_text, model='tts-1', voice='alloy', profile: gr.OAuthPr
|
|
173 |
return combined_audio
|
174 |
|
175 |
|
176 |
-
# %% app.ipynb
|
177 |
def create_speech(input_text, model='tts-1', voice='alloy', profile: gr.OAuthProfile|None=None, progress=gr.Progress()):
|
178 |
-
assert authorized() is not None,'Unauthorized M'
|
179 |
# Split the input text into chunks
|
180 |
chunks = split_text(input_text)
|
181 |
|
@@ -217,11 +230,11 @@ def create_speech(input_text, model='tts-1', voice='alloy', profile: gr.OAuthPro
|
|
217 |
return combined_audio
|
218 |
|
219 |
|
220 |
-
# %% app.ipynb
|
221 |
def get_input_text_len(input_text):
|
222 |
return len(input_text)
|
223 |
|
224 |
-
# %% app.ipynb
|
225 |
def get_generation_cost(input_text, tts_model_dropdown):
|
226 |
text_len = len(input_text)
|
227 |
if tts_model_dropdown.endswith('-hd'):
|
@@ -230,7 +243,7 @@ def get_generation_cost(input_text, tts_model_dropdown):
|
|
230 |
cost = text_len/1000 * 0.015
|
231 |
return "${:,.3f}".format(cost)
|
232 |
|
233 |
-
# %% app.ipynb
|
234 |
def authorized(profile: gr.OAuthProfile=None) -> str:
|
235 |
print('Profile:', profile)
|
236 |
if profile is not None and profile.username in ["matdmiller"]:
|
@@ -239,7 +252,7 @@ def authorized(profile: gr.OAuthProfile=None) -> str:
|
|
239 |
print('Unauthorized',profile)
|
240 |
return None
|
241 |
|
242 |
-
# %% app.ipynb
|
243 |
with gr.Blocks(title='OpenAI TTS', head='OpenAI TTS') as app:
|
244 |
gr.Markdown("# OpenAI TTS")
|
245 |
gr.Markdown("""Start typing below and then click **Go** to create the speech from your text. The current limit is 4,000 characters.
|
@@ -265,13 +278,13 @@ For requests longer than 4,000 chars they will be broken into chunks of 4,000 or
|
|
265 |
app.load(authorized, None, m)
|
266 |
|
267 |
|
268 |
-
# %% app.ipynb
|
269 |
# launch_kwargs = {'auth':('username',GRADIO_PASSWORD),
|
270 |
# 'auth_message':'Please log in to Mat\'s TTS App with username: username and password.'}
|
271 |
launch_kwargs = {}
|
272 |
queue_kwargs = {'default_concurrency_limit':10}
|
273 |
|
274 |
-
# %% app.ipynb
|
275 |
#.py launch
|
276 |
if __name__ == "__main__":
|
277 |
app.queue(**queue_kwargs)
|
|
|
1 |
# AUTOGENERATED! DO NOT EDIT! File to edit: app.ipynb.
|
2 |
|
3 |
# %% auto 0
|
4 |
+
__all__ = ['secret_import_failed', 'TEMP', 'TEMP_DIR', 'tts_voices', 'clean_text_prompt', 'OPENAI_CLIENT_TTS_THREADS',
|
5 |
+
'launch_kwargs', 'queue_kwargs', 'split_text', 'concatenate_mp3', 'create_speech_openai', 'create_speech2',
|
6 |
+
'create_speech', 'get_input_text_len', 'get_generation_cost', 'authorized']
|
7 |
|
8 |
# %% app.ipynb 1
|
9 |
#tts_openai_secrets.py content:
|
|
|
38 |
from math import ceil
|
39 |
from multiprocessing.pool import ThreadPool
|
40 |
from functools import partial
|
41 |
+
from pathlib import Path
|
42 |
+
import uuid
|
43 |
from tenacity import (
|
44 |
retry,
|
45 |
stop_after_attempt,
|
|
|
47 |
) # for exponential backoff
|
48 |
|
49 |
# %% app.ipynb 4
|
50 |
+
TEMP = os.environ['TMPDIR']
|
51 |
+
TEMP_DIR = Path(TEMP)
|
52 |
+
print('TEMP Dir:', TEMP_DIR)
|
53 |
+
|
54 |
+
# %% app.ipynb 5
|
55 |
try:
|
56 |
tts_models = [o.id for o in openai.models.list().data if 'tts' in o.id]
|
57 |
print('successfully got tts model list:', tts_models)
|
58 |
except:
|
59 |
tts_models = ['tts-1']
|
60 |
|
61 |
+
# %% app.ipynb 6
|
62 |
tts_voices = ['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer']
|
63 |
|
64 |
+
# %% app.ipynb 7
|
65 |
clean_text_prompt = """Your job is to clean up text that is going to be fed into a text to speech (TTS) model. You must remove parts of the text that would not normally be spoken such as reference marks `[1]`, spurious citations such as `(Reddy et al., 2021; Wu et al., 2022; Chang et al., 2022; Kondratyuk et al., 2023)` and any other part of the text that is not normally spoken. Please also clean up sections and headers so they are on new lines with proper numbering. You must also clean up any math formulas that are salvageable from being copied from a scientific paper. If they are garbled and do not make sense then remove them. You must carefully perform the text cleanup so it is translated into speech that is easy to listen to however you must not modify the text otherwise. It is critical that you repeat all of the text without modifications except for the cleanup activities you've been instructed to do. Also you must clean all of the text you are given, you may not omit any of it or stop the cleanup task early."""
|
66 |
|
67 |
|
68 |
+
# %% app.ipynb 8
|
69 |
#Number of threads created PER USER REQUEST. This throttels the # of API requests PER USER request. This is in ADDITION to the Gradio threads.
|
70 |
OPENAI_CLIENT_TTS_THREADS = 10
|
71 |
|
72 |
+
# %% app.ipynb 9
|
73 |
def split_text(input_text, max_length=4000, lookback=1000):
|
74 |
# If the text is shorter than the max_length, return it as is
|
75 |
if len(input_text) <= max_length:
|
|
|
102 |
|
103 |
return chunks
|
104 |
|
105 |
+
# %% app.ipynb 10
|
106 |
def concatenate_mp3(mp3_files):
|
107 |
if len(mp3_files) == 1:
|
108 |
return mp3_files[0]
|
|
|
122 |
# Concatenate this segment to the combined segment
|
123 |
combined += audio_segment
|
124 |
|
125 |
+
#### Return Bytes Method
|
126 |
+
# # Export the combined segment to a new mp3 file
|
127 |
+
# # Use a BytesIO object to handle this in memory
|
128 |
+
# combined_mp3 = io.BytesIO()
|
129 |
+
# combined.export(combined_mp3, format="mp3")
|
130 |
|
131 |
+
# # Seek to the start so it's ready for reading
|
132 |
+
# combined_mp3.seek(0)
|
133 |
|
134 |
+
# return combined_mp3.getvalue()
|
135 |
|
136 |
+
#### Return Filepath Method
|
137 |
+
filepath = TEMP_DIR/(str(uuid.uuid4())+'.mp3')
|
138 |
+
combined.export(filepath, format="mp3")
|
139 |
+
return str(filepath)
|
140 |
+
|
141 |
+
# %% app.ipynb 11
|
142 |
def create_speech_openai(chunk_idx, input, model='tts-1', voice='alloy', speed=1.0, **kwargs):
|
143 |
client = openai.OpenAI()
|
144 |
|
|
|
150 |
client.close()
|
151 |
return chunk_idx, response.content
|
152 |
|
153 |
+
# %% app.ipynb 12
|
154 |
def create_speech2(input_text, model='tts-1', voice='alloy', profile: gr.OAuthProfile|None=None, progress=gr.Progress(), **kwargs):
|
155 |
print('cs2-profile:',profile)
|
156 |
assert authorized(profile) is not None,'Unauthorized M'
|
|
|
186 |
return combined_audio
|
187 |
|
188 |
|
189 |
+
# %% app.ipynb 13
|
190 |
def create_speech(input_text, model='tts-1', voice='alloy', profile: gr.OAuthProfile|None=None, progress=gr.Progress()):
|
191 |
+
assert authorized(profile) is not None,'Unauthorized M'
|
192 |
# Split the input text into chunks
|
193 |
chunks = split_text(input_text)
|
194 |
|
|
|
230 |
return combined_audio
|
231 |
|
232 |
|
233 |
+
# %% app.ipynb 14
|
234 |
def get_input_text_len(input_text):
|
235 |
return len(input_text)
|
236 |
|
237 |
+
# %% app.ipynb 15
|
238 |
def get_generation_cost(input_text, tts_model_dropdown):
|
239 |
text_len = len(input_text)
|
240 |
if tts_model_dropdown.endswith('-hd'):
|
|
|
243 |
cost = text_len/1000 * 0.015
|
244 |
return "${:,.3f}".format(cost)
|
245 |
|
246 |
+
# %% app.ipynb 16
|
247 |
def authorized(profile: gr.OAuthProfile=None) -> str:
|
248 |
print('Profile:', profile)
|
249 |
if profile is not None and profile.username in ["matdmiller"]:
|
|
|
252 |
print('Unauthorized',profile)
|
253 |
return None
|
254 |
|
255 |
+
# %% app.ipynb 17
|
256 |
with gr.Blocks(title='OpenAI TTS', head='OpenAI TTS') as app:
|
257 |
gr.Markdown("# OpenAI TTS")
|
258 |
gr.Markdown("""Start typing below and then click **Go** to create the speech from your text. The current limit is 4,000 characters.
|
|
|
278 |
app.load(authorized, None, m)
|
279 |
|
280 |
|
281 |
+
# %% app.ipynb 18
|
282 |
# launch_kwargs = {'auth':('username',GRADIO_PASSWORD),
|
283 |
# 'auth_message':'Please log in to Mat\'s TTS App with username: username and password.'}
|
284 |
launch_kwargs = {}
|
285 |
queue_kwargs = {'default_concurrency_limit':10}
|
286 |
|
287 |
+
# %% app.ipynb 20
|
288 |
#.py launch
|
289 |
if __name__ == "__main__":
|
290 |
app.queue(**queue_kwargs)
|