Spaces:
Running
Running
File size: 7,985 Bytes
42966de f43c5ad 6385f1b 98b32f1 a9471a7 98b32f1 a9471a7 98b32f1 a9471a7 97e46d3 9813b68 97e46d3 42966de 3020c69 42966de 98b32f1 42966de 98b32f1 9813b68 98b32f1 42966de 98b32f1 42966de a9471a7 42966de 98b32f1 42966de f43c5ad 6385f1b 9813b68 f43c5ad 6385f1b 614dae3 fb7e56c 6385f1b e847c01 42966de 0dbb78f 98b32f1 0dbb78f 98b32f1 7b9da97 3020c69 7b9da97 98b32f1 7b9da97 1777fa6 7b9da97 42966de 3020c69 98b32f1 97e46d3 42966de dac7224 3020c69 98b32f1 9813b68 dfb71ed 614dae3 42966de 98b32f1 42966de ce4caa3 |
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 234 235 236 237 |
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 to use when generating the audio.
api_key (str): OpenAI API key.
response_format (str): Format of the output audio. Defaults to 'mp3'.
speed (float): Speed of the generated audio. Defaults to 1.0.
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.")
if len(input_text) > 4096:
raise gr.Error("Input text exceeds the maximum length of 4096 characters.")
if speed < 0.25 or speed > 4.0:
raise gr.Error("Speed must be between 0.25 and 4.0.")
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
data = {
"model": model,
"input": input_text,
"voice": voice,
"response_format": response_format,
"speed": speed,
}
try:
response = requests.post(
"https://api.openai.com/v1/audio/speech",
headers=headers,
json=data,
)
response.raise_for_status()
except requests.exceptions.HTTPError as http_err:
raise gr.Error(f"HTTP error occurred: {http_err} - {response.text}")
except Exception as err:
raise gr.Error(f"An error occurred: {err}")
# The content will be the audio file content
audio_content = response.content
file_extension = response_format.lower()
# PCM is raw data, so it does not have a standard file extension
if file_extension == "pcm":
file_extension = "raw"
with tempfile.NamedTemporaryFile(
suffix=f".{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])
with gr.Blocks(title="OpenAI - Text to Speech") as demo:
with gr.Row():
with gr.Column(scale=1):
with gr.Group():
preview_audio = gr.Audio(
interactive=False,
label="Preview Audio",
value=None,
visible=True,
)
# Function to play the selected voice sample
def play_voice_sample(voice):
return gr.update(value=VOICE_PREVIEW_FILES[voice])
# 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,
)
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",
info="The voice to use when generating the audio.",
)
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):
input_textbox = gr.Textbox(
label="Input Text",
lines=10,
placeholder="Type your text here...",
)
# Add a character counter below the input textbox
char_count_text = gr.Markdown("0 / 4096")
# Function to update the character count
def update_char_count(input_text):
char_count = len(input_text)
return f"**{char_count} / 4096**"
# Update character count when the user stops typing
input_textbox.change(
fn=update_char_count,
inputs=input_textbox,
outputs=char_count_text,
)
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() |