Cast Config Reference — cast_<slug>_<TAG>.json
The cast config file assigns ElevenLabs voices to characters, configures stereo
positioning and audio effects, and optionally defines broadcast preamble and postamble
blocks read by a host. One file covers an entire episode; it is read by xil produce,
xil daw, xil mix, and xil studio.
Filename pattern: cast_<slug>_<TAG>.json
(e.g. cast_the413_S03E02.json, cast_nightowls_V01C03.json)
Top-level Structure
{
"show": "The 4 1 3",
"season": 3,
"episode": 2,
"title": "The Weight of the Letters",
"season_title": "The Architect",
"artist": "XIL Pipeline",
"preamble": { ... },
"postamble": { ... },
"cast": { ... }
}
| Field | Type | Required | Description |
|---|---|---|---|
show |
string | yes | Show name (informational; slug derived from project.json) |
season |
int | no | Season number; used in preamble {season} placeholder and ID3 metadata |
episode |
int | yes* | Episode number; used in preamble {episode} placeholder |
tag_override |
string | no | Raw non-episodic tag (e.g. V01C03, D01). When set, overrides season/episode for tag derivation |
title |
string | no | Episode title; used in preamble {title} placeholder and ID3 metadata |
season_title |
string | no | Season arc title; used in preamble {season_title} placeholder |
artist |
string | no | Artist credit written to MP3/WAV ID3 tags. Default: "XIL Pipeline" |
preamble |
object | no | Broadcast intro block (see below) |
postamble |
object | no | Broadcast outro block (see below) |
cast |
object | yes | Map of speaker key → voice config (see below) |
* episode is required unless tag_override is set.
cast Block
Each key must match a speaker key used in the production script (all lowercase, no
spaces — e.g. adam, mr_patterson). Keys are matched case-sensitively against the
speaker field of parsed dialogue entries.
Cast Member Fields
"adam": {
"full_name": "Adam Santos",
"voice_id": "6wrQFQPrvgNyJY74SxwG",
"pan": 0.0,
"filter": false,
"role": "Host/Narrator. American male, early 20s. Warm, intimate...",
"stability": 0.5,
"similarity_boost": 0.75,
"style": 0.0,
"use_speaker_boost": true,
"language_code": "en"
}
| Field | Type | Required | Description |
|---|---|---|---|
full_name |
string | yes | Character display name (used in ID3 tags and voice sample filenames) |
voice_id |
string | yes | ElevenLabs voice ID. Set to "TBD" when not yet assigned — pipeline will skip TTS for this speaker |
pan |
float −1.0 to 1.0 | yes | Stereo position. 0.0 = centre, −1.0 = full left, 1.0 = full right |
filter |
bool | yes | true applies a phone-speaker bandpass filter (telephone/radio effect) |
role |
string | yes | Character description passed as previous_text context to ElevenLabs |
stability |
float 0–1 | no | Voice stability. 0.0 = expressive/variable, 1.0 = monotone/consistent. null uses the voice's ElevenLabs default |
similarity_boost |
float 0–1 | no | Adherence to the original cloned voice. 1.0 = strict match. null uses the voice default |
style |
float 0–1 | no | Style exaggeration relative to the original speaker. 0.0 = neutral. null uses the voice default |
use_speaker_boost |
bool | no | Boosts similarity to the original speaker at the cost of slightly higher latency. null uses the voice default |
language_code |
string | no | ISO 639-1 code for ElevenLabs text normalisation (e.g. "en", "de", "uk" for British English). null = auto-detect |
Pan Guide
| Value | Position | Typical use |
|---|---|---|
0.0 |
Centre | Host/narrator, solo speaker |
−0.15 to −0.3 |
Left | Female character A |
0.15 to 0.3 |
Right | Male character B |
−0.5 / 0.5 |
Hard L/R | Distinct telephone or off-screen voice |
Avoid values beyond ±0.4 for dialogue — extreme panning fatigues listeners on headphones.
Voice Settings Guide
| Parameter | Lower | Higher | Suggested starting point |
|---|---|---|---|
stability |
More emotional variation | Predictable, consistent | 0.5 |
similarity_boost |
Looser, more creative | Strict clone adherence | 0.75 |
style |
Neutral delivery | Exaggerated expressiveness | 0.0 |
Omitting any of these fields (or setting to null) inherits the ElevenLabs voice default.
Use xil voice-sample --episode TAG to audition voice changes before committing them.
preamble and postamble Blocks
Both blocks are optional and share an identical schema. They control TTS speaking rate
only — the spoken text lives in the production script as PREAMBLE and POSTAMBLE
section blocks, not in the cast config.
| Field | Type | Required | Description |
|---|---|---|---|
speaker |
string | yes | Cast key of the reader (must exist in cast) |
speed |
float 0.7–1.2 | no | TTS speaking rate override for this section. 1.0 = normal speed; 0.85 = slightly slowed for broadcast clarity |
xil produce applies the speed override when generating stems for entries whose
section field is "preamble" or "postamble". All other voice settings (voice ID,
stability, pan) come from the speaker's cast entry as normal.
The spoken text, music cues ([INTRO MUSIC], [OUTRO MUSIC]), and section placement
are written in the production script:
===
PREAMBLE
TINA Welcome to the show. Season 1, Episode 1, Pilot.
[INTRO MUSIC]
===
COLD OPEN
…
===
POSTAMBLE
[OUTRO MUSIC]
TINA That was the show. Thank you for listening.
===
END OF EPISODE
Preamble/postamble voice stems follow the same {seq:03d}_preamble_{speaker}.mp3 naming
convention as all other dialogue stems. Music stems are generated by xil sfx via the
standard SFX pipeline using INTRO MUSIC / OUTRO MUSIC entries in the sfx config.
Non-episodic Tags
For content that isn't organised as S01E01 (audiobooks, shorts, one-offs), use
tag_override instead of season/episode:
tag_override is used verbatim for all file path derivations (stems/signals/V01C01/,
parsed/parsed_signals_V01C01.json, etc.). It must match ^[A-Za-z0-9_-]+$.
Auto-generated Skeleton
When you run xil parse with --episode TAG and no cast file exists yet, a skeleton
is written automatically:
{
"show": "THE 413", "season": 1, "episode": 1, "title": "...",
"cast": {
"adam": { "voice_id": "TBD", "pan": 0.0, "filter": false, "role": "" },
...
}
}
Fill in each voice_id using xil discover-voices to browse available ElevenLabs
voices, then audition assignments with xil voice-sample --episode TAG.
Field Reference Summary
Top-level
| Field | Type | Default | Notes |
|---|---|---|---|
show |
string | — | Required |
season |
int | null |
Optional; used in tag and placeholders |
episode |
int | — | Required unless tag_override is set |
tag_override |
string | null |
Non-episodic tag; overrides season/episode |
title |
string | null |
Episode title for metadata and placeholders |
season_title |
string | null |
Arc title for {season_title} placeholder |
artist |
string | "XIL Pipeline" |
ID3 Artist tag on all audio outputs |
preamble |
object | null |
Broadcast intro |
postamble |
object | null |
Broadcast outro |
cast |
object | — | Required |
Cast Member
| Field | Type | Default | Notes |
|---|---|---|---|
full_name |
string | — | Required |
voice_id |
string | — | Required; "TBD" defers generation |
pan |
float −1–1 | — | Required |
filter |
bool | — | Required |
role |
string | — | Required; used as TTS context |
stability |
float 0–1 | voice default | Optional |
similarity_boost |
float 0–1 | voice default | Optional |
style |
float 0–1 | voice default | Optional |
use_speaker_boost |
bool | voice default | Optional |
language_code |
string | auto | Optional; ISO 639-1 |
Preamble / Postamble
| Field | Type | Default | Notes |
|---|---|---|---|
speaker |
string | — | Required; must be a key in cast |
speed |
float 0.7–1.2 | voice default | Optional TTS rate override for this section |
Complete Minimal Example
{
"show": "Night Owls",
"season": 1,
"episode": 3,
"title": "The Long Shift",
"cast": {
"jordan": {
"full_name": "Jordan Blake",
"voice_id": "abc123ElevenLabsVoiceID",
"pan": 0.0,
"filter": false,
"role": "Host. American, warm, late-night energy."
},
"caller": {
"full_name": "The Caller",
"voice_id": "xyz456ElevenLabsVoiceID",
"pan": 0.35,
"filter": true,
"role": "Nervous, mid-30s, calls in anonymously."
}
}
}
Complete Preamble/Postamble Example
Cast config (cast_nightowls_S01E03.json):
{
"show": "Night Owls",
"season": 1,
"episode": 3,
"title": "The Long Shift",
"season_title": "Season of Static",
"preamble": { "speaker": "host", "speed": 0.9 },
"postamble": { "speaker": "host", "speed": 0.9 },
"cast": {
"host": {
"full_name": "Jordan Blake",
"voice_id": "abc123ElevenLabsVoiceID",
"pan": 0.0,
"filter": false,
"role": "Host. American, warm, late-night energy.",
"stability": 0.5,
"similarity_boost": 0.75,
"style": 0.0,
"use_speaker_boost": true,
"language_code": "en"
}
}
}
Script (scripts/nightowls/S01E03_the_long_shift.md, beginning and end):
===
PREAMBLE
HOST You're listening to Night Owls. [pause] Season of Static [pause] Episode 3 [pause] "The Long Shift".
[INTRO MUSIC]
===
COLD OPEN
…
===
POSTAMBLE
[OUTRO MUSIC]
HOST That was Night Owls, Episode 3, "The Long Shift". [pause] Thank you for listening.
===
END OF EPISODE
See Also
- SFX Config Reference — intro/outro music lives in the sfx config under
INTRO MUSIC/OUTRO MUSICkeys, not in the cast config xil discover-voices— browse and search available ElevenLabs voicesxil voice-sample --episode TAG— generate short TTS samples to audition voice assignmentsxil produce --dry-run --episode TAG— preview TTS character cost before committing