Spaces:
Running
Running
File size: 8,065 Bytes
42966de f43c5ad 6385f1b 98b32f1 a9471a7 5814747 a9471a7 5814747 1bd5a81 4ac8df6 5814747 98b32f1 42966de a9471a7 42966de 98b32f1 42966de f43c5ad 6385f1b 9813b68 f43c5ad 6385f1b 614dae3 fb7e56c 6385f1b 8991bd4 4e85e92 5814747 c05f1b3 8991bd4 e847c01 42966de 0dbb78f 2c2c365 4e85e92 15934ba 1bd5a81 512ecf5 055f404 15934ba 055f404 7b9da97 3020c69 7b9da97 98b32f1 7b9da97 1777fa6 7b9da97 055f404 5814747 055f404 5814747 055f404 5814747 055f404 5814747 055f404 e0954fa 055f404 5814747 055f404 5814747 e0954fa 055f404 7b9da97 055f404 42966de 3020c69 98b32f1 97e46d3 42966de dac7224 3020c69 98b32f1 9813b68 dfb71ed 614dae3 42966de 5814747 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
import gradio as gr
import tempfile
import openai
import requests
import os
from functools import partial
def tts(
input_text: str,
model: str,
voice: str,
api_key: str,
response_format: str = "mp3",
speed: float = 1.0,
) -> str:
"""
Convert input text to speech using OpenAI's Text-to-Speech API.
Parameters:
input_text (str): The text to be converted to speech.
model (str): The model to use for synthesis (e.g., 'tts-1', 'tts-1-hd').
voice (str): The voice profile to use (e.g., 'alloy', 'echo', 'fable', etc.).
api_key (str): OpenAI API key.
response_format (str): The audio format of the output file (default is 'mp3').
speed (float): The speed of the synthesized speech.
Returns:
str: File path to the generated audio file.
Raises:
gr.Error: If input parameters are invalid or API call fails.
"""
if not api_key.strip():
raise gr.Error(
"API key is required. Get an API key at: https://platform.openai.com/account/api-keys"
)
if not input_text.strip():
raise gr.Error("Input text cannot be empty.")
openai.api_key = api_key
try:
response = openai.audio.speech.create(
input=input_text,
voice=voice,
model=model,
response_format=response_format,
speed=speed,
)
except openai.OpenAIError as e:
# Catch-all for OpenAI exceptions
raise gr.Error(f"An OpenAI error occurred: {e}")
except Exception as e:
# Catch any other exceptions
raise gr.Error(f"An unexpected error occurred: {e}")
if not hasattr(response, "audio"):
raise gr.Error(
"Invalid response from OpenAI API. The response does not contain audio content."
)
# Save the audio content to a temporary file
audio_content = response.audio
file_extension = f".{response_format}"
with tempfile.NamedTemporaryFile(suffix=file_extension, delete=False) as temp_file:
temp_file.write(audio_content)
temp_file_path = temp_file.name
return temp_file_path
def main():
"""
Main function to create and launch the Gradio interface.
"""
MODEL_OPTIONS = ["tts-1", "tts-1-hd"]
VOICE_OPTIONS = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"]
RESPONSE_FORMAT_OPTIONS = ["mp3", "opus", "aac", "flac", "wav", "pcm"]
# Predefine voice previews URLs
VOICE_PREVIEW_URLS = {
voice: f"https://cdn.openai.com/API/docs/audio/{voice}.wav"
for voice in VOICE_OPTIONS
}
# Download audio previews to disk before initiating the interface
PREVIEW_DIR = "voice_previews"
os.makedirs(PREVIEW_DIR, exist_ok=True)
VOICE_PREVIEW_FILES = {}
for voice, url in VOICE_PREVIEW_URLS.items():
local_file_path = os.path.join(PREVIEW_DIR, f"{voice}.wav")
if not os.path.exists(local_file_path):
try:
response = requests.get(url)
response.raise_for_status()
with open(local_file_path, "wb") as f:
f.write(response.content)
except requests.exceptions.RequestException as e:
print(f"Failed to download {voice} preview: {e}")
VOICE_PREVIEW_FILES[voice] = local_file_path
# Set static paths for Gradio to serve
gr.set_static_paths(paths=[PREVIEW_DIR])
# Create the 'preview_audio' component
preview_audio = gr.Audio(
interactive=False,
label="Echo",
value=VOICE_PREVIEW_FILES['echo'],
visible=True,
show_download_button=False,
show_share_button=False,
autoplay=False,
)
with gr.Blocks(title="OpenAI - Text to Speech") as demo:
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Voice Preview")
# Function to play the selected voice sample
def play_voice_sample(voice):
return gr.update(
value=VOICE_PREVIEW_FILES[voice],
label=voice.capitalize(),
)
with gr.Group():
# Create buttons for each voice
for voice in VOICE_OPTIONS:
voice_button = gr.Button(
value=f"{voice.capitalize()}",
variant="secondary",
size="sm",
)
voice_button.click(
fn=partial(play_voice_sample, voice=voice),
outputs=preview_audio,
)
# Place the audio player below the buttons
preview_audio.render()
with gr.Column(scale=1):
api_key_input = gr.Textbox(
label="OpenAI API Key",
info="https://platform.openai.com/account/api-keys",
type="password",
placeholder="Enter your OpenAI API Key",
)
model_dropdown = gr.Dropdown(
choices=MODEL_OPTIONS,
label="Model",
value="tts-1",
info="Select tts-1 for speed or tts-1-hd for quality.",
)
voice_dropdown = gr.Dropdown(
choices=VOICE_OPTIONS,
label="Voice Options",
value="echo",
)
response_format_dropdown = gr.Dropdown(
choices=RESPONSE_FORMAT_OPTIONS,
label="Response Format",
value="mp3",
)
speed_slider = gr.Slider(
minimum=0.25,
maximum=4.0,
step=0.05,
label="Voice Speed",
value=1.0,
)
with gr.Column(scale=2):
# Initialize the input textbox with the desired label
input_textbox = gr.Textbox(
label="Input Text (0000 / 4096 chars)",
lines=10,
placeholder="Type your text here...",
)
# Function to update the label with the character count
def update_label(input_text):
char_count = len(input_text)
new_label = f"Input Text ({char_count:04d} / 4096 chars)"
return gr.update(label=new_label)
# Update the label when the text changes, with progress hidden
input_textbox.change(
fn=update_label,
inputs=input_textbox,
outputs=input_textbox,
show_progress='hidden', # Hide the progress indicator
)
submit_button = gr.Button(
"Convert Text to Speech",
variant="primary",
)
with gr.Column(scale=1):
output_audio = gr.Audio(label="Output Audio")
# Define the event handler for the submit button with error handling
def on_submit(
input_text, model, voice, api_key, response_format, speed
):
audio_file = tts(
input_text, model, voice, api_key, response_format, speed
)
return audio_file
# Trigger the conversion when the submit button is clicked
submit_button.click(
fn=on_submit,
inputs=[
input_textbox,
model_dropdown,
voice_dropdown,
api_key_input,
response_format_dropdown,
speed_slider,
],
outputs=output_audio,
)
# Launch the Gradio app with error display enabled
demo.launch(show_error=True)
if __name__ == "__main__":
main()
|