Spaces:
Paused
Paused
Upload app.py
Browse files
app.py
CHANGED
@@ -18,6 +18,172 @@ logger = logging.getLogger(__name__)
|
|
18 |
ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
|
19 |
set_api_key(ELEVENLABS_API_KEY)
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
# Create the voice command group
|
22 |
voice_group = app_commands.Group(name="voice", description="Voice generation commands")
|
23 |
|
|
|
18 |
ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
|
19 |
set_api_key(ELEVENLABS_API_KEY)
|
20 |
|
21 |
+
def get_available_voices():
|
22 |
+
"""Fetch only custom voices from ElevenLabs account"""
|
23 |
+
all_voices = voices()
|
24 |
+
return {voice.name: voice.voice_id for voice in all_voices if not voice.category == "premade"}
|
25 |
+
|
26 |
+
def get_remaining_credits():
|
27 |
+
"""Get remaining character credits from ElevenLabs"""
|
28 |
+
user = User.from_api()
|
29 |
+
subscription = user.subscription
|
30 |
+
return {
|
31 |
+
"character_count": subscription.character_count,
|
32 |
+
"character_limit": subscription.character_limit
|
33 |
+
}
|
34 |
+
|
35 |
+
def format_credits_message(credits_info):
|
36 |
+
"""Format credits information into a readable message"""
|
37 |
+
return f"Credits Remaining: {credits_info['character_count']}"
|
38 |
+
|
39 |
+
# Discord bot setup
|
40 |
+
class VoiceBot(discord.Client):
|
41 |
+
def __init__(self):
|
42 |
+
super().__init__(intents=discord.Intents.default())
|
43 |
+
self.tree = app_commands.CommandTree(self)
|
44 |
+
|
45 |
+
async def setup_hook(self):
|
46 |
+
await self.tree.sync()
|
47 |
+
|
48 |
+
client = VoiceBot()
|
49 |
+
|
50 |
+
@client.tree.command(name="list", description="List all available voices")
|
51 |
+
async def voice_list(interaction: discord.Interaction):
|
52 |
+
await interaction.response.defer()
|
53 |
+
available_voices = get_available_voices()
|
54 |
+
voice_list = "\n".join([f"• {name}" for name in available_voices.keys()])
|
55 |
+
credits_info = get_remaining_credits()
|
56 |
+
credits_msg = format_credits_message(credits_info)
|
57 |
+
|
58 |
+
embed = discord.Embed(
|
59 |
+
title="Available Voices",
|
60 |
+
description=f"{voice_list}\n\n{credits_msg}",
|
61 |
+
color=0x2B2D31
|
62 |
+
)
|
63 |
+
await interaction.followup.send(embed=embed)
|
64 |
+
|
65 |
+
async def voice_autocomplete(
|
66 |
+
interaction: discord.Interaction,
|
67 |
+
current: str,
|
68 |
+
) -> List[app_commands.Choice[str]]:
|
69 |
+
voices = list(get_available_voices().keys())
|
70 |
+
return [
|
71 |
+
app_commands.Choice(name=voice, value=voice)
|
72 |
+
for voice in voices if current.lower() in voice.lower()
|
73 |
+
][:25]
|
74 |
+
|
75 |
+
@client.tree.command(name="create", description="Create a voice message")
|
76 |
+
@app_commands.describe(
|
77 |
+
text="Text to convert to speech",
|
78 |
+
voice_name="Select a voice to use",
|
79 |
+
stability="Voice stability (0-1)",
|
80 |
+
clarity="Voice clarity (0-1)",
|
81 |
+
style="Speaking style (0-1)"
|
82 |
+
)
|
83 |
+
@app_commands.autocomplete(voice_name=voice_autocomplete)
|
84 |
+
async def voice_create(
|
85 |
+
interaction: discord.Interaction,
|
86 |
+
text: str,
|
87 |
+
voice_name: str,
|
88 |
+
stability: float = 0.5,
|
89 |
+
clarity: float = 0.75,
|
90 |
+
style: float = 0.5
|
91 |
+
):
|
92 |
+
await interaction.response.defer()
|
93 |
+
|
94 |
+
available_voices = get_available_voices()
|
95 |
+
if voice_name not in available_voices:
|
96 |
+
embed = discord.Embed(
|
97 |
+
title="Voice Not Found",
|
98 |
+
description=f"The voice '{voice_name}' was not found. Use `/list` to see available voices.",
|
99 |
+
color=0x2B2D31
|
100 |
+
)
|
101 |
+
await interaction.followup.send(embed=embed)
|
102 |
+
return
|
103 |
+
|
104 |
+
try:
|
105 |
+
voice_settings = VoiceSettings(
|
106 |
+
stability=stability,
|
107 |
+
similarity_boost=clarity,
|
108 |
+
style=style,
|
109 |
+
use_speaker_boost=True
|
110 |
+
)
|
111 |
+
|
112 |
+
audio = generate(
|
113 |
+
text=text,
|
114 |
+
voice=Voice(
|
115 |
+
voice_id=available_voices[voice_name],
|
116 |
+
settings=voice_settings
|
117 |
+
)
|
118 |
+
)
|
119 |
+
|
120 |
+
# Save audio to temporary file
|
121 |
+
with open("temp.mp3", "wb") as f:
|
122 |
+
f.write(audio)
|
123 |
+
|
124 |
+
# Get updated credits
|
125 |
+
credits_info = get_remaining_credits()
|
126 |
+
credits_msg = format_credits_message(credits_info)
|
127 |
+
|
128 |
+
embed = discord.Embed(
|
129 |
+
title="Voice Generated",
|
130 |
+
description=f"Voice: {voice_name}\n{credits_msg}",
|
131 |
+
color=0x2B2D31
|
132 |
+
)
|
133 |
+
await interaction.followup.send(
|
134 |
+
embed=embed,
|
135 |
+
file=discord.File("temp.mp3")
|
136 |
+
)
|
137 |
+
|
138 |
+
# Clean up
|
139 |
+
os.remove("temp.mp3")
|
140 |
+
|
141 |
+
except Exception as e:
|
142 |
+
logger.error(f"Error generating audio: {str(e)}", exc_info=True)
|
143 |
+
await interaction.followup.send(f"Error generating audio: {str(e)}")
|
144 |
+
|
145 |
+
@client.event
|
146 |
+
async def on_ready():
|
147 |
+
logger.info(f"Bot is ready and logged in as {client.user}")
|
148 |
+
try:
|
149 |
+
synced = await client.tree.sync()
|
150 |
+
logger.info(f"Synced {len(synced)} command(s)")
|
151 |
+
except Exception as e:
|
152 |
+
logger.error(f"Failed to sync commands: {e}")
|
153 |
+
|
154 |
+
# Start Discord bot in a separate thread
|
155 |
+
def start_discord_bot():
|
156 |
+
"""Start the Discord bot"""
|
157 |
+
DISCORD_TOKEN = os.getenv("DISCORD_BOT_TOKEN")
|
158 |
+
if not DISCORD_TOKEN:
|
159 |
+
logger.error("DISCORD_BOT_TOKEN not found!")
|
160 |
+
return
|
161 |
+
|
162 |
+
logger.info("Starting Discord bot...")
|
163 |
+
try:
|
164 |
+
client.run(DISCORD_TOKEN)
|
165 |
+
except Exception as e:
|
166 |
+
logger.error(f"Failed to start Discord bot: {str(e)}")
|
167 |
+
import os
|
168 |
+
import gradio as gr
|
169 |
+
import threading
|
170 |
+
import discord
|
171 |
+
from discord import app_commands
|
172 |
+
from typing import List
|
173 |
+
from elevenlabs import set_api_key, voices, generate, Voice, VoiceSettings, User
|
174 |
+
import tempfile
|
175 |
+
import speech_recognition as sr
|
176 |
+
from pydub import AudioSegment
|
177 |
+
import logging
|
178 |
+
|
179 |
+
# Set up logging
|
180 |
+
logging.basicConfig(level=logging.INFO)
|
181 |
+
logger = logging.getLogger(__name__)
|
182 |
+
|
183 |
+
# Set your ElevenLabs API key
|
184 |
+
ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
|
185 |
+
set_api_key(ELEVENLABS_API_KEY)
|
186 |
+
|
187 |
# Create the voice command group
|
188 |
voice_group = app_commands.Group(name="voice", description="Voice generation commands")
|
189 |
|