Estimated per-request cost for a completed TTS request, in nanodollars
(1/1,000,000 of a dollar — the same unit Request.cost_cents already uses for
chat/embeddings, despite the field's legacy name).
No TTS provider self-reports cost the way OpenRouter's chat completions do (there's
no usage object at all in an /audio/speech or xAI /tts response) — so unlike
Completion.extract_usage/1, this can't extract a real figure from the response. It
has to come from a hand-maintained rate table instead.
Rates as of 2026-07-16 — verify against each provider's current pricing page before trusting for billing-critical use. These will drift; this table needs periodic manual updates, same as any other hardcoded rate table. Sources:
- Mistral (
voxtral-mini-tts-2603): $16 / 1M characters — https://mistral.ai/pricing/api/ - xAI (Grok TTS — one flat rate regardless of model, since xAI TTS has no per-model pricing tiers): $4.20 / 1M characters — https://docs.x.ai/developers/pricing
- OpenAI (
gpt-4o-mini-tts): $0.60 / 1M input text tokens + $12 / 1M audio output tokens — https://developers.openai.com/api/docs/models/gpt-4o-mini-tts
Mistral and xAI bill per character, and input_chars is exact (String.length/1
on the request text), so their cost is exact given the rate is current. OpenAI bills
per token on both legs, but /audio/speech returns no token counts to read back —
estimating a token count from characters (further split into an input-text leg and
an audio-output leg) would compound two guesses, so this uses the commonly-cited
blended rate (~$0.015/minute of generated audio) applied to a duration estimated
from audio_bytes at the assumed bitrate instead — one estimate, not two. Treat it
as approximate wherever it's displayed.
Summary
Functions
Estimated cost in nanodollars for a completed TTS request, or nil if provider
isn't in the rate table — same as no cost being available today, not a new failure
mode. input_chars and audio_bytes are exactly what PhoenixKitAI.speak/3 already
records in the request's metadata.
Functions
@spec cost_nanodollars(String.t(), non_neg_integer(), non_neg_integer()) :: non_neg_integer() | nil
Estimated cost in nanodollars for a completed TTS request, or nil if provider
isn't in the rate table — same as no cost being available today, not a new failure
mode. input_chars and audio_bytes are exactly what PhoenixKitAI.speak/3 already
records in the request's metadata.