Models and voices
The station's words can come from a language model and its voice from a speech engine, both plugins. With no model it writes its own breaks from its phrasings; with no voice it plays records. A model makes the presenter better. It never stands between the station and silence.
Fig. 1. Settings → Words. Which plugin it asks is under Settings → Providers.
Talking without a model
Every break has more than one writer, tried in order: a model first, if you have switched it on, and behind it the station's own phrasings. They are the floor: instant, and unable to fail, so a model that is slow, missing or failed a check costs a better sentence rather than a silent station. The phrasings are written on each character (Voice → Characters, "Their own phrasings"), one per line, and a character with none falls back to the station's own rather than silencing it. See breaks.
A model writing the talk breaks is off by default, and so is a model choosing the records. See the programme for what the station does instead.
One plugin, as many providers as you add
The language model plugin keeps a table of providers. Each row has a name you choose and a kind: OpenAI-compatible (a local Ollama or vLLM, or OpenAI, Groq, Mistral and OpenRouter at their own addresses), Anthropic, or Gemini.
The name is how a model is addressed: a model on the row you called ollama is ollama:gpt-oss, and one on the row you called claude is claude:claude-sonnet-5. A model named without its provider is refused rather than guessed at. An API key typed into the table is encrypted, never shown again and never returned by the API. For OpenAI-compatible providers you also tick which models can be given tools, because no such server reports it.
A model for each job
Settings → Providers names the plugin the station asks. Settings → Words then gives each job its own switch and its own model: the talk breaks listeners hear; choosing records, which is research rather than a sentence; reading articles for trivia, with a second call checking each fact against the words that state it; reading each character back to itself, nightly; thinking up things your characters have lived through, nightly, none of which airs until you keep it unless you have let that character develop on its own; and writing a character when you press Write. So a station can write its breaks on a hosted model and do its reading on a local one, picking names from what your providers actually offer.
Each job's models are a list, tried in order. Add from every model your providers offer, move them up or down, or remove them. The first model on the list is asked first. If it fails before it says anything (its server is down, it answers an error, it times out, or it has been retired), the station asks the next model on the list straight away, inside the same wait. A model that failed is asked last for the next minute, so a dead server costs one try rather than one per call. A list left empty uses the plugin's own default model, and productions (features, phone-ins and banter between co-hosts) have a list of their own.
The station asks its model one thing at a time, because a local model is one set of weights on one graphics card. A talk break waits its turn only so long before the phrasings write it, and background jobs run at the lowest priority, so a break always gets the model first. The station puts no cap on what a hosted provider bills; Check-up → What it cost lists every call.
Voices
Four speech plugins are bundled:
- Kokoro speaks through any OpenAI-compatible speech server, and ships pointed at the Kokoro server in the
latestandfullimages. A voice can be a blend, such asaf_bella(2)+af_sky(1). - Chatterbox reads from reference clips rather than named presets. It manages its model on the graphics card, and can let it go once the station has been off the air for a while (15 minutes by default), which matters when a local language model wants the same card.
- Rhapsode speaks through a server that holds several engines at once. A voice there belongs to one engine, so its table names both, and one station can read its news in one engine's voice and its breaks in another's. The server says what each engine can do — which cues it performs, how much text it takes, which audio formats it can encode — so the station asks instead of assuming, and the server decides what is on the card: the plugin only says how long to keep it there.
- ElevenLabs is the hosted one: paste an API key and nothing runs on your machine. The Voices table offers your account's own voices by name, and each row can set Stability and Similarity (and Style and Speed, on the models that read them). The model defaults to Eleven v4, which performs laughs, sighs, gasps and a cleared throat, and reads a line hushed or rushed. Test connection says how much of your plan's characters are spent; when they run out the plugin stops and says so rather than retrying. Every character the station speaks is billed by ElevenLabs, and what your plan allows you to do with the audio is between you and them. A voice from ElevenLabs' library is somebody's recorded voice, licensed to that marketplace, so check its terms before putting it on air.
The slim image brings no voice: point a speech plugin at a machine with a graphics card, or use ElevenLabs.
A voice is a name the station uses, such as host, newsreader or a character's own, and each speech plugin's Voices table says what that name sounds like on its engine. Where the engine can perform, a script may carry a cue: a presenter may laugh, chuckle, sigh or gasp, and a caller on a phone-in may also cough, clear their throat, sniff or groan, because on a telephone that is the realism. Only cues the loaded engine reports are offered; what a script can carry lists every tag and where each is allowed. To give a character a voice of its own, see making a voice.
From words to audio
Writing a break and speaking it are separate stages, so a failed render is retried with the words already written. A break whose audio is not ready when its turn comes is skipped, never waited for, so a broken speech engine cannot cost the station silence. The voice is levelled like the records and kept slightly under them, by an amount set under Settings → Playout.
A character can also have a soundboard, short sounds it may hit mid-sentence. None ships with the station: anything this project redistributed would have to be public domain, and none has been sourced. Upload your own.
How a word is said
Pronunciations are a table. The station fills it from the pronunciation keys printed in Wikipedia articles it already holds. Where it is sure which word a key belongs to it uses the entry; where it is not it proposes one, which is not said until you accept it, and a rejected one stays rejected. Figures are rewritten before an engine sees them, so "$17.1 billion" is read as "17.1 billion dollars", and a price in front of a noun as "a 100 billion dollar spaceport".
Broadcasting in another language
Set Language under Settings → Stream to a language tag such as de, fr or es, and the presenter writes and speaks in it. Leave it empty, or set any English tag, and the station is English as before.
What changes:
- Every break, phone-in and programme is written in that language. Record titles and people's names stay as written. A character written with Write gets its sample lines, catchphrases, stories and phrasings in that language; a character you already have keeps what it has, so rewrite its lines in the new language yourself.
- The station's own English phrasings are switched off, because an English sentence on a French station is worse than none. Your phrasings and your characters' still apply, but the time and the greeting can't be filled in any language but English, so leave them out of those. A break with no model answer and no phrasing to fall back on is left out. A warm-up, a jingle or a dedication plays only if somebody wrote a line for it in the station's language.
- Numbers, times and symbols go to the voice as written, for the engine to read in its own language, and the pronunciations the station found in English articles are not used. Yours still are.
- Checks that only understand English words, such as naming the wrong part of the day, are off. When the station can't tell whether a break mentioned the time or the weather, it assumes it did, so a break that runs late is replaced rather than going out stale.
- The weather names places in the station's language.
The voice has to speak the language too. Rhapsode and Chatterbox's multilingual model are told which language to use. Rhapsode, and Chatterbox for whichever model is loaded, report which languages they speak, and the station writes a warning to its log once if yours isn't among them. ElevenLabs reports the languages of the model you chose, and the station tells Flash v2.5 which one to use; the other ElevenLabs models read the language off the text. With Kokoro, choose voices built for the language. The Wikipedia plugin has its own language setting, since a station may still want its facts from English Wikipedia.
In the console
Settings → Providers for which plugin writes and which one speaks, beside every other job more than one of your plugins can do; Settings → Words for the model per job; the language model plugin's page, under Settings → Plugins, for the providers themselves. Voice in the rail, or the V key, holds Voices (with a preview of each), Pronunciations, Soundboard, and What it said: every break written, and every one declined.