Dialogue can be generated by the ElevenLabs cloud service or by Chatterbox Turbo, an open-source model that runs on your own machine. For a quick trial with almost no setup, gTTS reads the whole script in a single voice. Every backend works with the Python and Rust versions, and you choose per run.
ElevenLabs
Commercial API, the default
Nothing to install beyond the pipeline itself. Add your API key and every character in the cast gets a voice from the ElevenLabs library. The same key also generates sound effects. Run with --dry-run first to see the character cost before any credits are spent.
# get a key at elevenlabs.io, then
export ELEVENLABS_API_KEY=your_key_here
xil-produce --episode S01E01 --dry-run
xil-produce --episode S01E01
Chatterbox Turbo
Open-source model from Hugging Face, runs locally
Free to run once it's set up, on an NVIDIA GPU or on the CPU alone. Model weights download from Hugging Face on first use, and each character is cloned from a short reference recording you provide. It lives in its own virtual environment so its PyTorch dependencies stay out of the main install, and the pipeline finds it automatically.
# one reference clip per character, over 5 seconds
voice_refs/<speaker_key>.wav
# if the model repo is gated for your account
export HF_TOKEN=hf_...
xil-produce --episode S01E01 --backend chatterbox-turbo
gTTS
Free, minimal setup, single voice
The original proof of concept, and still the fastest way to hear a script end to end. There's no API key, no GPU, and no voice setup; every character is read in the same voice. Useful for checking timing and flow before committing to a full render.
xil-produce --episode S01E01 --backend gtts
Scripts can be shared between backends. Under Chatterbox Turbo, any bracketed tag it doesn't recognize is stripped, so ElevenLabs-only cues can stay in the script.
Setting up a backend
Each backend has its own setup needs:
- gTTS works as soon as the optional extras are installed.
- ElevenLabs needs an account and a key.
- Chatterbox Turbo needs its own Python environment and a reference clip for each voice.
Two optional local tools work the same way: Whisper checks rendered lines against the script, and MMAudio makes sound effects on your own GPU. See Local tools below.
Two environment variables keep your show separate from the pipeline's own software:
XIL_PROJECTROOT is your show's workspace—scripts, generated audio, and configs.
XIL_CODEROOT is where the pipeline and any local-model environments, like venv-chatterbox/, venv-whisper/, and venv-mmaudio/, are installed.
Both are optional; each defaults to your current folder if unset.
ElevenLabs
-
Create an API key
Sign in at elevenlabs.io, then open Profile and choose API Keys. Your plan's character allowance is what renders spend.
-
Set it in your shell
export ELEVENLABS_API_KEY=your_key_here
To keep it across sessions, add that line to ~/.bashrc or ~/.zshrc. Check it with echo $ELEVENLABS_API_KEY.
-
Pick voices for the cast
Browse and audition voices with xil-voices, then assign them in the show's cast file, cast_<slug>_<TAG>.json.
-
Preview the cost, then render
xil-produce --episode S01E01 --dry-run
xil-produce --episode S01E01
Only the commands that call the API need the key: xil-produce, xil-sfx, xil-studio, xil-sample, and xil-cues --generate. Parsing, DAW export, and mastering work without it.
Chatterbox Turbo
-
Build the environment
Chatterbox pulls in PyTorch, so it gets its own virtual environment, venv-chatterbox/. One command builds it in your code root (XIL_CODEROOT), picks CUDA or CPU PyTorch for your hardware, installs Chatterbox, and checks that it works. The pipeline then finds it automatically.
xil setup chatterbox --dry-run # show the commands first
xil setup chatterbox
It uses uv when installed, otherwise python3.13 -m venv and pip. Force a build with --device cuda or --device cpu; running it again on a working environment does nothing. Model weights download from Hugging Face on the first render. If the model repository is gated for your account, run huggingface-cli login or set HF_TOKEN first.
By hand instead (CUDA 12.4 shown; use .../whl/cpu for CPU only)
cd "$XIL_CODEROOT"
python3.13 -m venv venv-chatterbox
venv-chatterbox/bin/pip install 'torch==2.6.0' 'torchaudio==2.6.0' \
--index-url https://download.pytorch.org/whl/cu124
venv-chatterbox/bin/pip install chatterbox-tts pydub
-
Record a reference clip per character
Save one clip for each speaker as voice_refs/<speaker_key>.wav. Each clip must be longer than 5 seconds.
-
Render
xil-produce --episode S01E01 --backend chatterbox-turbo
If your environment lives somewhere else, point to its Python with --chatterbox-python PATH. Both the Python and Rust versions use the same environment.
Local tools: Whisper and MMAudio
-
Whisper, to check rendered lines
xil stem-verify can transcribe every rendered line with Faster-Whisper, and xil stem-compare then flags lines that do not match the script. Whisper gets its own environment, venv-whisper/. It does not need PyTorch, so it is small.
xil setup whisper
xil stem-verify --episode S01E01
On an NVIDIA GPU it runs on CUDA. If the GPU libraries are missing, it falls back to the CPU by itself.
-
MMAudio, for local sound effects
MMAudio makes sound effects on your own GPU (about 6 GB of video memory) instead of calling ElevenLabs. It is not on PyPI, so setup clones it next to venv-mmaudio/ (this needs git). It uses Python 3.12, because MMAudio does not install on 3.13. The model weights, about 6 GB, download on the first run into the same folder.
xil setup mmaudio --dry-run # show the commands first
xil setup mmaudio
xil sfx --episode S01E01 --gen-sfx --sfx-backend mmaudio --mmaudio-accept-noncommercial
Non-commercial only. MMAudio's code is MIT licensed, but its model weights are CC BY-NC 4.0. Audio it makes must not appear in a show that earns money. The pipeline refuses to start it without --mmaudio-accept-noncommercial, and it tags every clip it makes.
-
Get the right Python
Install uv first. Setup then fetches the Python version each tool needs. Without uv, setup uses whatever python3 you have and warns you if the version is wrong.