Skip to main content
kRouter
All posts
How kRouter works

How to use kRouter as a unified text-to-speech API

One /v1/audio/speech endpoint for 15 text-to-speech providers, from OpenAI and ElevenLabs to Edge TTS, three of them free with no key.

Kodelyth · The team behind kRouter
· Updated
4 min read

Most people think of an AI router as the thing that switches between GPT and Claude. Speech has the same problem in a worse form: OpenAI, Gemini, ElevenLabs, MiniMax and the rest each have their own request shape, their own voice names and their own auth. Supporting three of them means three integrations.

kRouter puts all of them behind one OpenAI-style endpoint, POST /v1/audio/speech.

What changed in this post

The first version listed four TTS providers, passed the voice in a voice field, and quoted per-character prices. kRouter now has more than a dozen TTS providers, the voice goes in the model string rather than a separate field, and the prices were not ours to quote. This version is current as of v0.5.163.

The providers

kRouter has 15 TTS providers. Twelve of them use your own key for that service: OpenAI, Gemini, ElevenLabs, MiniMax (global and China), NVIDIA, Deepgram, Fish Audio, Inworld, Hyperbolic, OpenRouter and AWS Polly.

Three need no key at all:

  • Edge TTS (edge-tts), Microsoft's neural voices
  • Google TTS (google-tts), Google Translate's voices, chosen by language code
  • Local device (local-device), your operating system's own voices through macOS say or Windows SAPI; it needs ffmpeg

The request

The model field carries the provider, and usually the model and voice too: provider/model/voice, or provider/voice to use that provider's default model. Put the voice there: as of v0.5.163 kRouter ignores a separate voice field, and a voice named in model is the one that is used.

curl http://localhost:20128/v1/audio/speech \
  -H "Content-Type: application/json" \
  -d '{"model": "edge-tts/en-US-AriaNeural", "input": "This is routing through kRouter."}' \
  --output speech.mp3

The response is raw audio, usually MP3; Gemini returns WAV. Add ?response_format=json to the URL to get {"audio": "<base64>", "format": "mp3"} instead, with the real format named.

A few model strings:

Model stringWhat it means
openai/tts-1-hd/shimmerOpenAI, model tts-1-hd, voice shimmer
openai/alloyOpenAI's default model (gpt-4o-mini-tts), voice alloy
gemini/gemini-2.5-flash-preview-tts/KoreGemini TTS, voice Kore
edge-tts/en-US-AriaNeuralEdge TTS, no key needed
google-tts/enGoogle TTS in English, no key needed

Do not guess voice names. kRouter lists them:

# Every TTS model kRouter knows
curl http://localhost:20128/v1/models/tts
 
# Voices for one provider, with the full model string for each
curl "http://localhost:20128/v1/audio/voices?provider=edge-tts&lang=en"

The voices endpoint covers Edge TTS, ElevenLabs, Deepgram, Inworld and local device voices. Each entry's model field is the exact string to send.

From a script on the same machine you do not need an API key. From anywhere else, send Authorization: Bearer <key> with a key from the dashboard's Endpoint page.

With the OpenAI SDK

The OpenAI SDKs require a voice argument. Pass the same voice you named in the model string, which is the one that decides:

from openai import OpenAI
 
client = OpenAI(base_url="http://localhost:20128/v1", api_key="<your kRouter key>")
 
response = client.audio.speech.create(
    model="openai/tts-1-hd/shimmer",
    voice="shimmer",  # required by the SDK; the voice in `model` wins
    input="Welcome to the show.",
)
response.write_to_file("intro.mp3")

Fallback between voices

A combo works for speech the same way it does for chat. Make a fallback combo whose entries are TTS model strings -- say a paid voice first and edge-tts/en-US-AriaNeural last -- and send the combo's name as the model. If the first provider fails or is out of quota, the next one answers. If you have several accounts on one provider, kRouter picks between them with the same Zenith scoring it uses for chat.

Expect the voice to change when it falls back. Different providers do not sound alike, so this suits notifications and drafts better than a finished narration.

Beyond speech

Transcription (/v1/audio/transcriptions), image generation (/v1/images/generations), embeddings, web search and fetch use the same idea. The multimodal gateway post and the multimodal and agent skills docs cover them. For agents, kRouter ships a krouter-tts skill on the dashboard's Skills page that teaches Claude Code and similar tools to call this endpoint.

Get started

npm install -g @sifxprime/krouter
krouter -t

Edge TTS, Google TTS and local device voices work with no setup. For the others, add the provider's key on the dashboard's Providers page.

Common questions

Which kRouter TTS voices are free?

Edge TTS, Google TTS and your operating system's own voices need no API key. Every other TTS provider uses your own key and bills you directly.

Where do I put the voice?

In the model string: provider/model/voice, or provider/voice for the default model. As of v0.5.163 kRouter ignores a separate voice field, so if your SDK requires one, pass the same voice in both places.

How do I find valid voice names?

Call GET /v1/audio/voices?provider=edge-tts (or elevenlabs, deepgram, inworld, local-device). Each result includes the full model string to send.

Can I fall back from one TTS provider to another?

Yes. Put TTS model strings in a fallback combo and send the combo name as the model. The voice will change when it falls back.

Kodelyth · The team behind kRouter

Published by Kodelyth, the team that builds kRouter. Posts are drafted with AI assistance and reviewed by a person before they go out. kRouter is free and MIT licensed.

Install kRouter