daswer123's picture
Upload 2 files
0d5d091 verified
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
)