wow-voiceover – Turtle WoW

wow-voiceover – Turtle WoW

Client Version: 1.12



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:


  • 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.


  • python 3.9+
  • docker (for the database)


  1. Make a python virtual enviornment. (make sure to source it after creating)
python -m venv .venv
  1. Install the required packages.
pip install -r requirements.txt
  1. 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
  1. Start the MySQL DB
docker compose up -d
  1. Seed the MySQL DB
python init-db

Voice Setup

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 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 @


To use the interactive CLI tool, run the following command:



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.

Addon Install

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:

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.

CLI Docs

Dataframe Schema

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.

New Fields Added by preprocess_dataframe

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