tts
@alexkroman1/aai/tts subpath barrel — the text-to-speech stage of a
pipeline agent.
Three vendors, one shape: each factory returns a serializable DESCRIPTOR
({ kind, options }), and you hand it to agent({ tts }). Nothing here
opens a socket or reads a credential — the host resolves the descriptor at
session start, so importing this barrel pulls in no vendor SDK.
Example
Section titled “Example”Swap the TTS stage of an otherwise default agent
import { agent } from "@alexkroman1/aai";import { CARTESIA_DEFAULT_VOICE, cartesiaTts } from "@alexkroman1/aai/tts";
export default agent({ name: "Support", // `stt` and `llm` keep their AssemblyAI defaults. tts: cartesiaTts({ voice: CARTESIA_DEFAULT_VOICE, model: "sonic-3" }),});Picking a voice is the one setting a TTS stage cannot infer, and an
unrecognised id has no authoring-time symptom: the agent connects, reports
ready and is permanently silent. For AssemblyAI the library voices are
ASSEMBLYAI_TTS_VOICES — read them there rather than trusting a name
from anywhere else, and note the TYPE cannot enforce it
(AssemblyAITtsVoice says why). A voice is always a descriptor
option — tts: assemblyAITts({ voice: "aai-michael" }) — so this
barrel is where one is chosen.
Credentials are never passed here. Each factory’s vendor names the env
var its key is read from — ASSEMBLYAI_API_KEY, CARTESIA_API_KEY,
RIME_API_KEY — and the host reads it out of the agent’s own environment
when the session starts. That is what keeps a descriptor safe to serialize
across the CLI → server → guest boundary. The variable NAMES are not
published: an author never types one, and the one case for repointing a
stage is apiKeyEnv on the AssemblyAI descriptor.
The descriptor type is on the ROOT barrel TOO
Section titled “The descriptor type is on the ROOT barrel TOO”TtsProvider — what a factory here returns — is also exported from
@alexkroman1/aai, beside the other three stage types, so an agent
annotating two stages writes one import rather than two. It stays here as
well: this is where the factory that produces one lives.
ProviderDescriptor, the base all four narrow, is on the root ALONE now —
one interface with four reference pages was three too many.
The host-side opener contract is on /runtime
Section titled “The host-side opener contract is on /runtime”Implementing a TTS vendor of your own — TtsOpenOptions, TtsSession,
TtsEvents, TtsError, TtsWordTiming, Unsubscribe — is a HOST job, and
those types live on @alexkroman1/aai-runtime beside registerTtsKind,
which is what you hand the opener to.
Functions
Section titled “Functions”assemblyAITts()
Section titled “assemblyAITts()”assemblyAITts(
options?):TtsProvider
Build an AssemblyAI streaming-TTS descriptor.
The API key is resolved host-side from the agent’s env
(ASSEMBLYAI_API_KEY); there is no factory-time key parameter, so the
descriptor stays free of secrets and safe to serialize.
Named assemblyAITts (not assemblyAI) so the STT
(assemblyAIStt), LLM (llm({ provider: "assemblyai" })), and TTS factories can be
imported side by side without aliasing.
Parameters
Section titled “Parameters”options?
Section titled “options?”Returns
Section titled “Returns”Example
Section titled “Example”import { agent } from "@alexkroman1/aai";import { assemblyAITts } from "@alexkroman1/aai/tts";
export default agent({ name: "Support", tts: assemblyAITts({ voice: "aai-michael" }),});The default pipeline’s stage is assemblyAITts() — the default voice —
so this is how its voice is changed. Pick from ASSEMBLYAI_TTS_VOICES
unless you mean a voice of your own — the service refuses an unknown one when
the session opens.
cartesiaTts()
Section titled “cartesiaTts()”cartesiaTts(
options?):TtsProvider
Build a Cartesia TTS descriptor for pipeline mode. The API key is resolved
host-side from the agent’s env (CARTESIA_API_KEY).
Parameters
Section titled “Parameters”options?
Section titled “options?”Returns
Section titled “Returns”Example
Section titled “Example”import { agent } from "@alexkroman1/aai";import { CARTESIA_DEFAULT_VOICE, cartesiaTts } from "@alexkroman1/aai/tts";
export default agent({ name: "Support", tts: cartesiaTts({ voice: CARTESIA_DEFAULT_VOICE, model: "sonic-3" }),});rimeTts()
Section titled “rimeTts()”rimeTts(
options?):TtsProvider
Build a Rime TTS descriptor for pipeline mode. The API key is resolved
host-side from the agent’s env (RIME_API_KEY).
Parameters
Section titled “Parameters”options?
Section titled “options?”Returns
Section titled “Returns”Example
Section titled “Example”import { agent } from "@alexkroman1/aai";import { RIME_DEFAULT_VOICE, rimeTts } from "@alexkroman1/aai/tts";
export default agent({ name: "Support", tts: rimeTts({ voice: RIME_DEFAULT_VOICE, model: "mistv2" }),});Interfaces
Section titled “Interfaces”AssemblyAITtsOptions
Section titled “AssemblyAITtsOptions”Input
Extends
Section titled “Extends”Properties
Section titled “Properties”apiKeyEnv?
Section titled “apiKeyEnv?”
optionalapiKeyEnv?:string
Env var holding this stage’s credential, replacing the provider default. Names a VARIABLE, not a key.
Inherited from
Section titled “Inherited from”ProviderCredentialOptions.apiKeyEnv
optionalhost?:string
Streaming-TTS host to dial, replacing ASSEMBLYAI_TTS_HOST (US). A bare
host, not a URL — the adapter owns the wss:// scheme and the /v1/ws
path, so a full URL here would be wrong in a way that only shows up at
connect.
"tts.eu.assemblyai.com" is EU residency (assemblyAIPipeline({ region: "eu" }) sets it). Any other value is a pre-release/staging cluster; one
generally issues its own keys, so point every AssemblyAI stage at the same
environment or the ones left on production reject the key.
language?
Section titled “language?”
optionallanguage?:"en"|"fr"|"de"|"it"|"pt"|"es"
Spoken language as an ISO 639-1 code ("en", "fr", "de", "es",
"it", "pt"). Omitted by default, which the service reads as English.
Translated internally to the service’s language name; see
ASSEMBLYAI_TTS_LANGUAGES for the supported set. An unsupported
code fails at build and connect time rather than muting the session.
voice?
Section titled “voice?”
optionalvoice?:AssemblyAITtsVoice
The voice_id: a library slug such as "aai-jane", "aai-michael" or
"aai-vera" (see ASSEMBLYAI_TTS_VOICES), or any other voice slug or
UUID the service knows. Defaults to ASSEMBLYAI_TTS_DEFAULT_VOICE.
Every library voice speaks every supported language.
CartesiaTtsOptions
Section titled “CartesiaTtsOptions”Input
Options for cartesiaTts.
Extends
Section titled “Extends”Properties
Section titled “Properties”apiKeyEnv?
Section titled “apiKeyEnv?”
optionalapiKeyEnv?:string
Env var holding this stage’s credential, replacing the provider default. Names a VARIABLE, not a key.
Inherited from
Section titled “Inherited from”ProviderCredentialOptions.apiKeyEnv
language?
Section titled “language?”
optionallanguage?:string
Spoken language hint. Defaults to "en".
model?
Section titled “model?”
optionalmodel?:string
Model ID. Defaults to "sonic-2".
voice?
Section titled “voice?”
optionalvoice?:string
Cartesia voice ID. Defaults to CARTESIA_DEFAULT_VOICE.
RimeTtsOptions
Section titled “RimeTtsOptions”Input
Options for rimeTts.
Extends
Section titled “Extends”Properties
Section titled “Properties”apiKeyEnv?
Section titled “apiKeyEnv?”
optionalapiKeyEnv?:string
Env var holding this stage’s credential, replacing the provider default. Names a VARIABLE, not a key.
Inherited from
Section titled “Inherited from”ProviderCredentialOptions.apiKeyEnv
language?
Section titled “language?”
optionallanguage?:string
Spoken language. Uses ISO 639-3 (three-letter codes).
Defaults to "eng" (English).
Note: Rime uses 3-letter codes — use "eng" not "en".
model?
Section titled “model?”
optionalmodel?:string
Rime model ID. Defaults to "mistv2" (Rime’s most compatible model).
Common values: "mistv2", "arcana".
voice?
Section titled “voice?”
optionalvoice?:string
Rime speaker ID. Defaults to RIME_DEFAULT_VOICE.
Type Aliases
Section titled “Type Aliases”AssemblyAITtsLanguage
Section titled “AssemblyAITtsLanguage”AssemblyAITtsLanguage = keyof typeof
ASSEMBLYAI_TTS_LANGUAGES
ISO 639-1 code for a language AssemblyAI streaming TTS speaks.
AssemblyAITtsVoice
Section titled “AssemblyAITtsVoice”AssemblyAITtsVoice =
"aai-alba"|"aai-anna"|"aai-charles"|"aai-eve"|"aai-george"|"aai-jane"|"aai-jean"|"aai-mary"|"aai-michael"|"aai-paul"|"aai-vera"|string&object
A voice_id: a slug from ASSEMBLYAI_TTS_VOICES, or any other slug or
voice UUID the service knows.
The (string & {}) arm is deliberate: the catalog is the service’s, not
ours, so a voice added after this release, an open-dataset voice, or the
author’s own cloned voice must still compile. So this type is
AUTOCOMPLETE, not a guard — an unlisted voice is warned about at build
time (assemblyAIVoiceWarning), never refused.
Variables
Section titled “Variables”ASSEMBLYAI_TTS_DEFAULT_VOICE
Section titled “ASSEMBLYAI_TTS_DEFAULT_VOICE”
constASSEMBLYAI_TTS_DEFAULT_VOICE:AssemblyAITtsVoice
Default voice when assemblyAITts() is called with no voice — the
service’s own default, so leaving it unset and naming it are the same session.
ASSEMBLYAI_TTS_LANGUAGES
Section titled “ASSEMBLYAI_TTS_LANGUAGES”
constASSEMBLYAI_TTS_LANGUAGES:object
ISO 639-1 code → the language query-param value the service accepts.
The streaming-TTS endpoint takes the full lowercase English name, not a
code: ?language=es is refused with Bad connection parameters: language: language 'es' not in supported set ['english', 'french', 'german', 'italian', 'portuguese', 'spanish']. That refusal arrives in-band after
the socket opens, so an unmapped code doesn’t fail the session — it leaves
the agent connected, “ready”, and permanently mute. Every other language
knob in the ecosystem (AssemblyAI STT’s language_codes, Cartesia) is a
code, so the codes are the SDK’s contract and this map is the translation.
Keys are the six languages every library voice speaks.
Type Declaration
Section titled “Type Declaration”
readonlyde:"german"
readonlyen:"english"
readonlyes:"spanish"
readonlyfr:"french"
readonlyit:"italian"
readonlypt:"portuguese"
ASSEMBLYAI_TTS_VOICES
Section titled “ASSEMBLYAI_TTS_VOICES”
constASSEMBLYAI_TTS_VOICES: readonlyAssemblyAITtsVoice[]
The AssemblyAI library voices, as the voice_id slugs the service takes.
Source: https://www.assemblyai.com/docs/tts/voices. Every one of them speaks
all six languages — language picks what a voice speaks, the voice only how
it sounds — so there is no voice/language pairing to get wrong.
A list rather than a map because a slug is all there is to know about one,
and a list is what z.enum takes: a form offering the caller a voice is
z.enum(ASSEMBLYAI_TTS_VOICES). Typed as a plain array, not a literal
tuple, so a voice added to the catalog is not a type change a reader’s
exhaustive check breaks on.
A constant rather than a sentence in a doc comment because a wrong voice id
is a refusal the service sends after the upgrade (3012 voice_not_found), so
nothing at authoring time can tell a typo from a working agent except a list
to check it against. The service’s own list (GET /v1/voices) has thousands
of open-dataset voices beside these; any of their slugs, a cloned voice’s
slug, or a voice UUID is a valid voice too.
CARTESIA_DEFAULT_VOICE
Section titled “CARTESIA_DEFAULT_VOICE”
constCARTESIA_DEFAULT_VOICE:string
Default voice used when callers invoke cartesiaTts() with no voice. This
is the same voice the example templates ship with, so a bare cartesiaTts()
works out of the box for new agents.
RIME_DEFAULT_VOICE
Section titled “RIME_DEFAULT_VOICE”
constRIME_DEFAULT_VOICE:string
Default Rime speaker used when callers invoke rimeTts() with no voice.
cove is a mistv2 speaker, matching the default model below — so a
bare rimeTts() works out of the box for new agents.
References
Section titled “References”fallback
Section titled “fallback”Re-exports fallback
ProviderCredentialOptions
Section titled “ProviderCredentialOptions”Re-exports ProviderCredentialOptions
TtsProvider
Section titled “TtsProvider”Re-exports TtsProvider