Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,4 @@ cython_debug/
#.idea/

/phonemize_words.py
/test_eleven_labs.py
43 changes: 30 additions & 13 deletions bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Any, Optional
import logging
from pathlib import Path
from eleven_labs_api import ElevenLabsAPI

DEBUG = os.getenv("DEBUG")
AUDIO_DIR = os.getenv("AUDIO_DIR", "/audio")
Expand All @@ -14,6 +15,7 @@
RAW_PREFIX_SHORT = "!b"
SPACE_PREFIX = RAW_PREFIX + " "
BOT_TOKEN = os.getenv("BOT_TOKEN")
ELEVEN_LABS_TOKEN = os.getenv("ELEVEN_LABS_TOKEN")
BOT_DESCRIPTION = ("A bot to generate alternate names for Benedict Cumberbatch.\n"
"\n"
f"Usage: {RAW_PREFIX_SHORT} [command] [arguments]\n"
Expand All @@ -34,18 +36,22 @@ def add_indented_commands(self, _commands, *, heading, max_size=None):
max_size = super().get_max_size(_commands) + self.indent
return super().add_indented_commands(_commands, heading=heading, max_size=max_size)

defaultHelpCommand = CustomHelp(
show_parameter_descriptions=False,
no_category="Commands",
command_attrs={
"aliases": ["?"],
"help": "Get general help information or help about a specific command"
}
bot = commands.Bot(
command_prefix=commands.when_mentioned_or(SPACE_PREFIX, "!b "),
description=BOT_DESCRIPTION,
intents=intents,
help_command=CustomHelp(
show_parameter_descriptions=False,
no_category="Commands",
command_attrs={
"aliases": ["?"],
"help": "Get general help information or help about a specific command"
}
)
)
bot = commands.Bot(command_prefix=commands.when_mentioned_or(SPACE_PREFIX, "!b "), description=BOT_DESCRIPTION,
intents=intents,
help_command=defaultHelpCommand)

name_api = Generator()
eleven_labs_api = ElevenLabsAPI(ELEVEN_LABS_TOKEN)

g_last_name = "Benedict Cumberbatch"
g_last_phone = "benedict cumberbatch"
Expand All @@ -62,8 +68,12 @@ async def _speak(ctx: commands.Context) -> Optional[Any]:
if not vc or not vc.is_connected():
return await ctx.reply("I am not connected to a voice channel.", mention_author=False)
if not vc.is_playing():
name_api.vocalize(g_last_phone)
audio_source = Path(AUDIO_DIR) / "output.wav"
_count = eleven_labs_api.get_remaining_character_count()
if _count < 20:
name_api.vocalize(g_last_phone)
audio_source = Path(AUDIO_DIR) / "output.wav"
else:
audio_source = eleven_labs_api.get_spoken_name(g_last_name, AUDIO_DIR)
return vc.play(discord.FFmpegPCMAudio(executable=FFMPEG_EXEC, source=str(audio_source)))
else:
return await ctx.reply("Audio is already playing.", mention_author=False)
Expand All @@ -78,7 +88,6 @@ async def _gen(ctx: commands.Context):
await _speak(ctx)



@bot.event
async def on_ready():
print(f'Logged in as {bot.user.name} - {bot.user.id}')
Expand Down Expand Up @@ -176,6 +185,14 @@ async def autospeak(ctx: commands.Context, subcmd: str = "on"):
return await ctx.reply(f"Autospeak off")


# Hidden Commands
@bot.command(name="count",
hidden=True)
async def count(ctx: commands.Context):
cnt = eleven_labs_api.get_remaining_character_count()
return await ctx.reply(f"{cnt} characters")


def run(token=BOT_TOKEN):
if DEBUG:
print(f"Using token: {token}")
Expand Down
51 changes: 51 additions & 0 deletions eleven_labs_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from elevenlabs.client import ElevenLabs
from elevenlabs.types import VoiceSettings
from dataclasses import dataclass
from pathlib import Path
from typing import Union

MODEL_ID = "eleven_turbo_v2_5"
OUTPUT_FORMAT = "mp3_44100_128"
MAX_CHARACTERS = 10000

class ElevenLabsAPI:

@dataclass
class VoiceIDs:
Clyde = "wyWA56cQNU2KqUW4eCsI"
Charles = "zNsotODqUhvbJ5wMG7Ei"

def __init__(self, token: str):
self.client = ElevenLabs(api_key=token)
self.character_count = 0
self.update_character_count()

def get_spoken_name(self, name: str, audio_dir: Union[Path, str],
voice_id: str = VoiceIDs.Charles, speed: float = 1.0,
regen: bool = False) -> Path:
name_id = name.replace(" ", "_")
file = Path(audio_dir) / f"{name_id}.mp3"
if file.exists() and not regen:
return file

voice_settings = VoiceSettings(speed=speed)
audio_stream = self.client.text_to_speech.convert(
text=name,
voice_id=voice_id,
model_id=MODEL_ID,
output_format=OUTPUT_FORMAT,
voice_settings=voice_settings
)
with open(file, "wb") as f:
for chunk in audio_stream:
f.write(chunk)

self.update_character_count()
return file

def update_character_count(self):
subscription = self.client.user.subscription.get()
self.character_count = subscription.character_count

def get_remaining_character_count(self):
return MAX_CHARACTERS - self.character_count
Binary file modified requirements.txt
Binary file not shown.