Spaces:
Running
Running
jonathanagustin
commited on
Commit
•
3dad746
1
Parent(s):
32d9c19
Upload folder using huggingface_hub
Browse files
app.py
CHANGED
@@ -4,23 +4,8 @@ import openai
|
|
4 |
import requests
|
5 |
import os
|
6 |
|
7 |
-
|
8 |
def tts(input_text: str, model: str, voice: str, api_key: str) -> str:
|
9 |
-
|
10 |
-
Convert input text to speech using OpenAI's Text-to-Speech API.
|
11 |
-
|
12 |
-
Parameters:
|
13 |
-
input_text (str): The text to be converted to speech.
|
14 |
-
model (str): The model to use for synthesis (e.g., 'tts-1', 'tts-1-hd').
|
15 |
-
voice (str): The voice profile to use (e.g., 'alloy', 'echo', 'fable', etc.).
|
16 |
-
api_key (str): OpenAI API key.
|
17 |
-
|
18 |
-
Returns:
|
19 |
-
str: File path to the generated audio file.
|
20 |
-
|
21 |
-
Raises:
|
22 |
-
gr.Error: If input parameters are invalid or API call fails.
|
23 |
-
"""
|
24 |
if not api_key.strip():
|
25 |
raise gr.Error(
|
26 |
"API key is required. Get an API key at: https://platform.openai.com/account/api-keys"
|
@@ -34,10 +19,8 @@ def tts(input_text: str, model: str, voice: str, api_key: str) -> str:
|
|
34 |
try:
|
35 |
response = openai.Audio.create(text=input_text, voice=voice, model=model)
|
36 |
except openai.OpenAIError as e:
|
37 |
-
# Catch-all for OpenAI exceptions
|
38 |
raise gr.Error(f"An OpenAI error occurred: {e}")
|
39 |
except Exception as e:
|
40 |
-
# Catch any other exceptions
|
41 |
raise gr.Error(f"An unexpected error occurred: {e}")
|
42 |
|
43 |
if not hasattr(response, "audio"):
|
@@ -51,11 +34,7 @@ def tts(input_text: str, model: str, voice: str, api_key: str) -> str:
|
|
51 |
|
52 |
return temp_file_path
|
53 |
|
54 |
-
|
55 |
def main():
|
56 |
-
"""
|
57 |
-
Main function to create and launch the Gradio interface.
|
58 |
-
"""
|
59 |
MODEL_OPTIONS = ["tts-1", "tts-1-hd"]
|
60 |
VOICE_OPTIONS = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"]
|
61 |
|
@@ -83,10 +62,99 @@ def main():
|
|
83 |
VOICE_PREVIEW_FILES[voice] = local_file_path
|
84 |
|
85 |
# Set static paths for Gradio to serve
|
86 |
-
|
87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
|
89 |
-
with gr.Blocks() as demo:
|
90 |
with gr.Row():
|
91 |
with gr.Column(scale=1):
|
92 |
api_key_input = gr.Textbox(
|
@@ -102,19 +170,29 @@ def main():
|
|
102 |
choices=VOICE_OPTIONS, label="Voice Options", value="echo"
|
103 |
)
|
104 |
|
105 |
-
# Add voice previews using HTML
|
106 |
gr.Markdown("### Voice Previews")
|
107 |
for voice in VOICE_OPTIONS:
|
108 |
# Use the relative path for the audio file
|
109 |
audio_url = f"file/{PREVIEW_DIR}/{voice}.wav"
|
110 |
-
# Create
|
111 |
html_snippet = f'''
|
112 |
-
<div
|
113 |
-
<
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
</div>
|
119 |
'''
|
120 |
gr.HTML(html_snippet)
|
@@ -146,4 +224,4 @@ def main():
|
|
146 |
|
147 |
|
148 |
if __name__ == "__main__":
|
149 |
-
main()
|
|
|
4 |
import requests
|
5 |
import os
|
6 |
|
|
|
7 |
def tts(input_text: str, model: str, voice: str, api_key: str) -> str:
|
8 |
+
# (Same as before)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
if not api_key.strip():
|
10 |
raise gr.Error(
|
11 |
"API key is required. Get an API key at: https://platform.openai.com/account/api-keys"
|
|
|
19 |
try:
|
20 |
response = openai.Audio.create(text=input_text, voice=voice, model=model)
|
21 |
except openai.OpenAIError as e:
|
|
|
22 |
raise gr.Error(f"An OpenAI error occurred: {e}")
|
23 |
except Exception as e:
|
|
|
24 |
raise gr.Error(f"An unexpected error occurred: {e}")
|
25 |
|
26 |
if not hasattr(response, "audio"):
|
|
|
34 |
|
35 |
return temp_file_path
|
36 |
|
|
|
37 |
def main():
|
|
|
|
|
|
|
38 |
MODEL_OPTIONS = ["tts-1", "tts-1-hd"]
|
39 |
VOICE_OPTIONS = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"]
|
40 |
|
|
|
62 |
VOICE_PREVIEW_FILES[voice] = local_file_path
|
63 |
|
64 |
# Set static paths for Gradio to serve
|
65 |
+
gr.static(PREVIEW_DIR)
|
66 |
+
|
67 |
+
with gr.Blocks(theme=gr.themes.Default()) as demo:
|
68 |
+
# Include global CSS styles for the audio elements
|
69 |
+
gr.HTML("""
|
70 |
+
<style>
|
71 |
+
.audio-player {
|
72 |
+
width: 5rem;
|
73 |
+
height: 5rem;
|
74 |
+
margin-bottom: 10px;
|
75 |
+
cursor: pointer;
|
76 |
+
}
|
77 |
+
|
78 |
+
.icon-container {
|
79 |
+
width: 100%;
|
80 |
+
height: 100%;
|
81 |
+
background-color: var(--color-background-secondary);
|
82 |
+
color: var(--color-text-inverse);
|
83 |
+
display: flex;
|
84 |
+
justify-content: center;
|
85 |
+
align-items: center;
|
86 |
+
border-radius: 50%;
|
87 |
+
position: relative;
|
88 |
+
}
|
89 |
+
|
90 |
+
.audio-icon {
|
91 |
+
width: 50%;
|
92 |
+
height: 50%;
|
93 |
+
}
|
94 |
+
|
95 |
+
.audio-player.playing .icon-container {
|
96 |
+
background-color: var(--color-brand-primary);
|
97 |
+
}
|
98 |
+
|
99 |
+
.voice-preview {
|
100 |
+
display: flex;
|
101 |
+
align-items: center;
|
102 |
+
margin-bottom: 1rem;
|
103 |
+
}
|
104 |
+
|
105 |
+
.voice-preview p {
|
106 |
+
margin-left: 10px;
|
107 |
+
font-weight: bold;
|
108 |
+
color: var(--color-text-primary);
|
109 |
+
}
|
110 |
+
</style>
|
111 |
+
""")
|
112 |
+
|
113 |
+
# Add JavaScript for handling play/pause
|
114 |
+
gr.HTML("""
|
115 |
+
<script>
|
116 |
+
function togglePlay(voice) {
|
117 |
+
const player = document.getElementById('audio-player-' + voice);
|
118 |
+
const container = document.getElementById('icon-container-' + voice);
|
119 |
+
const icon = document.getElementById('audio-icon-' + voice);
|
120 |
+
if (player.paused) {
|
121 |
+
// Pause any other playing audios
|
122 |
+
const audios = document.querySelectorAll('audio');
|
123 |
+
audios.forEach(function(audio) {
|
124 |
+
if (audio !== player) {
|
125 |
+
audio.pause();
|
126 |
+
audio.currentTime = 0;
|
127 |
+
const otherVoice = audio.id.replace('audio-player-', '');
|
128 |
+
document.getElementById('icon-container-' + otherVoice).classList.remove('playing');
|
129 |
+
document.getElementById('audio-icon-' + otherVoice).innerHTML = playIcon;
|
130 |
+
}
|
131 |
+
});
|
132 |
+
player.play();
|
133 |
+
container.classList.add('playing');
|
134 |
+
icon.innerHTML = pauseIcon;
|
135 |
+
} else {
|
136 |
+
player.pause();
|
137 |
+
container.classList.remove('playing');
|
138 |
+
icon.innerHTML = playIcon;
|
139 |
+
}
|
140 |
+
player.onended = function() {
|
141 |
+
container.classList.remove('playing');
|
142 |
+
icon.innerHTML = playIcon;
|
143 |
+
};
|
144 |
+
}
|
145 |
+
|
146 |
+
const playIcon = `
|
147 |
+
<svg class="audio-icon" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
148 |
+
<path d="M6.5 5.5v9l7-4.5-7-4.5z"/>
|
149 |
+
</svg>`;
|
150 |
+
|
151 |
+
const pauseIcon = `
|
152 |
+
<svg class="audio-icon" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
153 |
+
<path d="M6 5h3v10H6V5zm5 0h3v10h-3V5z"/>
|
154 |
+
</svg>`;
|
155 |
+
</script>
|
156 |
+
""")
|
157 |
|
|
|
158 |
with gr.Row():
|
159 |
with gr.Column(scale=1):
|
160 |
api_key_input = gr.Textbox(
|
|
|
170 |
choices=VOICE_OPTIONS, label="Voice Options", value="echo"
|
171 |
)
|
172 |
|
173 |
+
# Add voice previews using custom HTML audio players
|
174 |
gr.Markdown("### Voice Previews")
|
175 |
for voice in VOICE_OPTIONS:
|
176 |
# Use the relative path for the audio file
|
177 |
audio_url = f"file/{PREVIEW_DIR}/{voice}.wav"
|
178 |
+
# Create custom HTML audio player
|
179 |
html_snippet = f'''
|
180 |
+
<div class="voice-preview">
|
181 |
+
<div class="audio-player" onclick="togglePlay('{voice}')">
|
182 |
+
<div class="icon-container" id="icon-container-{voice}">
|
183 |
+
<div id="audio-icon-{voice}">
|
184 |
+
<!-- Heroicon Play Button SVG -->
|
185 |
+
<svg class="audio-icon" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
186 |
+
<path d="M6.5 5.5v9l7-4.5-7-4.5z"/>
|
187 |
+
</svg>
|
188 |
+
</div>
|
189 |
+
</div>
|
190 |
+
<audio id="audio-player-{voice}" style="display:none;">
|
191 |
+
<source src="{audio_url}" type="audio/wav">
|
192 |
+
Your browser does not support the audio element.
|
193 |
+
</audio>
|
194 |
+
</div>
|
195 |
+
<p>{voice.capitalize()}</p>
|
196 |
</div>
|
197 |
'''
|
198 |
gr.HTML(html_snippet)
|
|
|
224 |
|
225 |
|
226 |
if __name__ == "__main__":
|
227 |
+
main()
|