This project contains a CLI (Command Line Interface) tool that generates Text-to-Speech (TTS) audio files for World of Warcraft quests and gossip texts. The tool uses data fetched from a local MySQL database and the ElevenLabs TTS API to generate the audio files. It also contains an addon for playing and queuing the text in game.
VoiceOver Discord: https://discord.gg/VdhUmA8ZCt
- Initialize quest and gossip text database
- Fetch quest and gossip texts from a local MySQL database.
- Generate TTS audio files using the ElevenLabs TTS API.
- Supports multiple races and genders.
- Generates lookup tables for use in addon.
- Parallel processing for faster generation.
Below is for developers only. Go to releases if youre looking to install the addon.
- python 3.10+
- docker (for the database)
- Make a python virtual environment. (make sure to source it after creating)
python -m venv .venv
- Install the required packages.
pip install -r requirements.txt
- Copy the .env.example file to .env and fill in your ElevenLabs API Key and database credentials. The included database values are fine if you're going to use the docker-compose file.
cp .env.example .env
- Start the MySQL DB
docker compose up -d
- Seed the MySQL DB
python cli-main.py init-db
The generation scripts assume you have voices created in Elevenlabs named in the format race-gender
. For the exact races the script checks your elevenlabs account for, refer to tts_cli\consts.py
. Gender will always either be male
or female
. ex: orc-male
. You will need to create your own voice clones. A good place to get samples is @ https://www.wowhead.com/sounds/npc-greetings/name:orc
To use the interactive CLI tool, run the following command:
python cli-main.py
Currently there are no voice translations available for languages other than english. However, if you want to use the addon with a non English client, you can still do so by creating the lookup tables in the client's respective language.
To create the lookup tables, you can use the following command, with LANGUAGE_CODE
representing the required language for the client:
python cli-main.py gen_lookup_tables --lang=LANGUAGE_CODE
The default selection, when no language code is provided, is English. Please be aware that the quality of text completion for translations in languages other than English can vary significantly.
The following language codes are supported:
Language Code | Language |
---|---|
enUS | English |
enGB | English |
koKR | Korean |
frFR | French |
deDE | German |
zhCN | Simplified Chinese |
zhTW | Traditional Chinese |
esES | European Spanish |
esMX | Mexican Spanish |
ruRU | Russian |
The generated TTS audio files will be saved in the sounds folder, with separate subfolders for quests and gossip. Lookup tables and sound length tables will also be generated for use in the addon.
Copy over the generated
folder to the VoiceOverData_Vanilla folder, then the VoiceOver and VoiceOverData_Vanilla folder to World of Warcraft/_classic_era_/Interface/AddOns
. Alternatively, you can syslink instead of copying for faster development.
Example syslink:
export WOW_DIR=PATH_OF_YOUR_WOW_DIR
ln -s ./VoiceOver "$WOW_DIR/_classic_era_/Interface/AddOns"
ln -s ./VoiceOver_Vanilla "$WOW_DIR/_classic_era_/Interface/AddOns"
If you want to contribute to this project, please feel free to open an issue or submit a pull request.
The dataframe schema before calling the preprocess_dataframe
function consists of the following columns:
Column | Description |
---|---|
source |
Indicates the type of interaction, can be 'accept', 'progress', 'complete', or 'gossip' |
quest |
The quest ID or empty string if it's a gossip interaction |
text |
The text template content of the interaction |
DisplayRaceID |
The race ID of the NPC involved in the interaction |
DisplaySexID |
The gender ID of the NPC involved in the interaction |
name |
The name of the NPC involved in the interaction |
type |
The type of the NPC involved in the interaction ('creature', 'gameobject', or 'item') |
id |
The creature/gameobject/item ID of the NPC involved in the interaction |
DisplayRaceID = -1
is used for interactions with inanimate NPCs: gameobjects, items etc. It's mapped to a voice called "narrator" in RACE_DICT
.
The preprocess_dataframe
function adds the following new fields to the dataframe:
Column | Description |
---|---|
race |
The race of the NPC, mapped from DisplayRaceID using RACE_DICT |
gender |
The gender of the NPC, mapped from DisplaySexID using GENDER_DICT |
voice_name |
The voice name, which is a combination of the race and gender fields |
templateText_race_gender |
A combination of the text, race, and gender fields |
templateText_race_gender_hash |
A hash of the templateText_race_gender field |
cleanedText |
text after rendering template |