Spaces:
Running
Running
File size: 11,142 Bytes
0d5d091 |
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 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
import time
import gradio as gr
import os
from typing import Optional
from dotenv import load_dotenv
from elevenlabs_wrapper import ElevenLabsManager
class ElevenLabsApp:
def __init__(self):
self.manager: Optional[ElevenLabsManager] = None
# Load API key from .env
load_dotenv()
self.api_key = os.getenv('ELEVENLABS_API_KEY')
# Try to validate API key on initialization
self.show_interface = False
self.initial_voices = []
if self.api_key:
try:
self.manager = ElevenLabsManager(api_key=self.api_key)
self.initial_voices = self.get_filtered_voices("all")
self.show_interface = True
except Exception as e:
print(f"Failed to validate initial API key: {str(e)}")
self.create_interface()
def validate_api_key(self, api_key: str):
try:
self.manager = ElevenLabsManager(api_key=api_key)
voices = self.get_filtered_voices("all")
initial_voice = voices[0] if voices else None
return "API key validated successfully!", gr.update(visible=True), gr.update(visible=False), gr.update(choices=voices, value=initial_voice)
except Exception as e:
return f"Error: {str(e)}", gr.update(visible=False), gr.update(visible=True), gr.update(choices=[], value=None)
def get_filtered_voices(self, filter_type: str):
if not self.manager:
return []
voices = self.manager.get_voices(filter_type)
voice_list = [f"{voice['name']} ({voice['category']})" for voice in voices]
return voice_list
def update_voice_list(self, filter_type: str):
voices = self.get_filtered_voices(filter_type)
initial_voice = voices[0] if voices else None
return gr.update(choices=voices, value=initial_voice)
def clone_voice(self, name: str, description: str, files):
if not self.manager:
return "Please validate API key first", None
try:
file_paths = [f.name for f in files]
voice_id = self.manager.clone_voice(name, file_paths, description)
voices = self.get_filtered_voices("all")
return f"Voice cloned successfully! Voice ID: {voice_id}", None
except Exception as e:
return f"Error cloning voice: {str(e)}", None
def delete_voice(self, voice_name: str):
if not self.manager or not voice_name:
return "Please select a voice to delete"
try:
voice_id = self.manager.find_voice_by_name(voice_name.split(" (")[0])
if voice_id:
success = self.manager.delete_voice(voice_id)
if success:
return "Voice deleted successfully!"
return "Failed to delete voice"
return "Voice not found"
except Exception as e:
return f"Error deleting voice: {str(e)}"
def set_model(self, model_name: str):
if not self.manager:
return "Please validate API key first"
try:
self.manager.set_model(model_name)
return f"Model changed to {model_name}"
except Exception as e:
return f"Error changing model: {str(e)}"
def generate_speech(self, text: str, voice_name: str, stability: float, similarity_boost: float, model: str):
if not self.manager:
return "Please validate API key first", None
try:
if not text.strip():
return "Please enter some text", None
if not voice_name:
return "Please select a voice", None
self.manager.set_stability(stability)
self.manager.set_similarity_boost(similarity_boost)
self.manager.set_model(model)
voice_id = self.manager.find_voice_by_name(voice_name.split(" (")[0])
audio = self.manager.generate_audio(text, voice_id)
filename = str(time.time()) + ".wav"
os.makedirs("temp", exist_ok=True)
output_path = os.path.join("temp", filename)
self.manager.save_audio(audio, output_path)
return "Speech generated successfully!", output_path
except Exception as e:
return f"Error generating speech: {str(e)}", None
def create_interface(self):
with gr.Blocks() as app:
gr.Markdown("# ElevenLabs Text-to-Speech Interface")
with gr.Row():
api_key_input = gr.Textbox(
label="Enter your ElevenLabs API key",
type="password",
placeholder="Enter API key here...",
value=self.api_key if self.api_key else ""
)
validate_btn = gr.Button("Validate API Key")
api_status = gr.Textbox(label="Status", interactive=False)
main_interface = gr.Column(visible=self.show_interface)
with main_interface:
with gr.Row():
with gr.Column(scale=2):
with gr.Accordion(label="Voice", open=True):
voice_filter = gr.Dropdown(
choices=["all", "cloned", "non-cloned"],
label="Filter Voices",
value="all"
)
with gr.Row():
voice_dropdown = gr.Dropdown(
label="Select Voice",
interactive=True,
choices=self.initial_voices,
value=self.initial_voices[0] if self.initial_voices else None
)
refresh_btn = gr.Button("Refresh Voices")
delete_btn = gr.Button("Delete Selected Voice")
delete_status = gr.Textbox(
label="Deletion Status",
interactive=False
)
with gr.Accordion("Voice Settings", open=False):
model_dropdown = gr.Dropdown(
choices=["eleven_turbo_v2_5", "eleven_multilingual_v2"],
value="eleven_turbo_v2_5",
label="Model"
)
stability = gr.Slider(
minimum=0,
maximum=1,
value=0.5,
label="Stability",
info="Higher values make the voice more consistent"
)
similarity_boost = gr.Slider(
minimum=0,
maximum=1,
value=0.75,
label="Similarity Boost",
info="Higher values make the voice more similar to the original"
)
with gr.Accordion("Clone New Voice", open=False):
clone_name = gr.Textbox(
label="Voice Name",
placeholder="Enter a name for your cloned voice"
)
clone_description = gr.Textbox(
label="Voice Description",
placeholder="Enter a description for your voice"
)
clone_files = gr.File(
label="Upload Audio Files",
file_count="multiple"
)
clone_btn = gr.Button("Clone Voice")
clone_status = gr.Textbox(
label="Cloning Status",
interactive=False
)
with gr.Column(scale=3):
text_input = gr.Textbox(
label="Text to Convert",
placeholder="Enter text here...",
lines=5
)
generate_btn = gr.Button("Generate Speech", variant="primary")
with gr.Row():
status_box = gr.Textbox(
label="Generation Status",
interactive=False
)
audio_output = gr.Audio(
label="Generated Speech",
type="filepath"
)
api_key_view = gr.Column(visible=not self.show_interface)
with api_key_view:
gr.Markdown("Please enter your API key to continue")
validate_btn.click(
fn=self.validate_api_key,
inputs=[api_key_input],
outputs=[api_status, main_interface, api_key_view, voice_dropdown]
)
voice_filter.change(
fn=self.update_voice_list,
inputs=[voice_filter],
outputs=[voice_dropdown]
)
refresh_btn.click(
fn=self.update_voice_list,
inputs=[voice_filter],
outputs=[voice_dropdown]
)
clone_btn.click(
fn=self.clone_voice,
inputs=[clone_name, clone_description, clone_files],
outputs=[clone_status, audio_output]
).then(
fn=self.update_voice_list,
inputs=[voice_filter],
outputs=[voice_dropdown]
)
delete_btn.click(
fn=self.delete_voice,
inputs=[voice_dropdown],
outputs=[delete_status]
).then(
fn=self.update_voice_list,
inputs=[voice_filter],
outputs=[voice_dropdown]
)
generate_btn.click(
fn=self.generate_speech,
inputs=[text_input, voice_dropdown, stability, similarity_boost, model_dropdown],
outputs=[status_box, audio_output]
)
return app
if __name__ == "__main__":
app = ElevenLabsApp()
app.create_interface().launch(
inbrowser=True
) |