Text-to-speech API

Send a string, get an audio file back. One request, one response, and the response body is the audio — no job to submit, no URL to poll, nothing to download later. It is the same endpoint shape as OpenAI’s, so an existing client usually needs a new base URL and nothing more.

OpenAI-compatiblemp3, wav, opus, flacApache 2.0 weightsNo per-seat licence

What this actually does

It reads text aloud. You give it a sentence and a voice; it gives you back an mp3 — or a wav, opus or flac — that you can play, stream to a caller, or save next to an article. There is no conversation and no prompt to write. Text in, audio out.

The model is Kokoro 82M, an 82-million-parameter speech model published under Apache 2.0. Small is the point: it is cheap to run and quick to answer, and it does not announce itself as synthetic in the first sentence the way small models used to.

What people build with it

  • The voice of an agent — the other half of a voice loop: speech in through transcription, text through a chat model, speech back out through this.
  • Listenable articles and digests — an audio version of a newsletter, a report or a document, generated once at publish time and served as a file.
  • Accessibility in your own product — reading your interface out loud, priced per character of what you actually read rather than per user who might.
  • Notifications worth hearing — spoken alerts in a kiosk, a car, a warehouse or a game, anywhere a screen is the wrong output device.
  • Narration at volume — product descriptions, lesson scripts, IVR prompts: thousands of short clips where a per-character price is the difference between viable and not.

Call it

POST /v1/audio/speech, with a JSON body. The response is the audio itself rather than JSON, so in curl you want --output — without it, curl prints an mp3 to your terminal.

curlbash
curl https://api.infersia.com/v1/audio/speech \
  -H "Authorization: Bearer $INFERSIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "hexgrad/kokoro-82m",
    "input": "Your parcel is out for delivery and should arrive before six.",
    "voice": "af_heart",
    "response_format": "mp3"
  }' \
  --output speech.mp3

The same call with the official OpenAI SDK. No plugin and no fork — a different base_url and a model id:

speak.pypython
from openai import OpenAI
import os

client = OpenAI(
    base_url="https://api.infersia.com/v1",
    api_key=os.environ["INFERSIA_API_KEY"],
)

speech = client.audio.speech.create(
    model="hexgrad/kokoro-82m",
    input="Your parcel is out for delivery and should arrive before six.",
    voice="af_heart",
    response_format="mp3",
)

with open("speech.mp3", "wb") as f:
    f.write(speech.content)

Voices, formats and speed

Several voices ship with the weights, across a few accents and both registers. af_heart is the one in the example above; the full set is published with the model itself, so the names never drift from what the server will accept. The model page links straight to it.

ParameterWhat it takes
inputThe text to read. Up to 4,096 characters per request.
voiceA voice name, e.g. af_heart.
response_formatmp3 (the default), wav, opus or flac.
speedAdjusts the pace of delivery.

opus is the one to reach for if the audio is going down a phone line or a WebRTC session; wav if something downstream is going to re-encode it anyway and you would rather not stack two lossy passes.

Reading something longer than a paragraph

input is capped at 4,096 characters per request — OpenAI’s own limit, kept deliberately so a client written against their API does not discover a different one in production. Split longer text client-side. Splitting at sentence boundaries is not just tidier: the joins land where a listener already expects a pause, so the result sounds better than one long synthesis would have.

narrate.pypython
import re

# 4,096 characters per request, so long text is split before it is sent.
# Splitting on sentence boundaries also sounds better than splitting on a
# character count — a join at a full stop is a pause a listener expects.
def chunks(text, limit=4000):
    buf = ""
    for sentence in re.split(r"(?<=[.!?])\s+", text):
        if len(buf) + len(sentence) + 1 > limit:
            yield buf
            buf = sentence
        else:
            buf = f"{buf} {sentence}".strip()
    if buf:
        yield buf

article_text = open("article.txt", encoding="utf-8").read()

# Concatenated mp3 frames play as one file. For wav or flac, decode and join
# properly instead — those carry a header that describes the whole stream.
with open("article.mp3", "wb") as out:
    for part in chunks(article_text):
        speech = client.audio.speech.create(
            model="hexgrad/kokoro-82m",
            input=part,
            voice="af_heart",
            response_format="mp3",
        )
        out.write(speech.content)

What it costs

How that compares

Speech is billed per character almost everywhere, which makes this one of the rare comparisons that is arithmetic rather than argument. Every figure below was read off the vendor’s own pricing page on 7 August 2026.

ProviderModelPublished price
OpenAItts-1$15.00 / 1M characters
OpenAItts-1-hd$30.00 / 1M characters
DeepgramAura-1
pay-as-you-go — $15.00 per 1M
$0.0150 / 1k characters
DeepgramAura-2
pay-as-you-go — $30.00 per 1M
$0.030 / 1k characters

Sources, fetched 7 August 2026: developers.openai.com/api/docs/pricing and deepgram.com/pricing. Prices change and this table does not update itself — check the source before you make a decision on it. ElevenLabs and Cartesia are not listed because their published pricing is subscription tiers with included allowances rather than a per-character list price, and dividing a plan by its allowance would be our arithmetic wearing their name.

Why the gap is this wide

Kokoro is an 82-million-parameter model. The GPU time it takes to read a sentence is genuinely small, and open weights mean there is no licence fee stacked on top of the compute. We would rather pass that through and be the obvious choice for the workloads nobody runs at fifteen dollars a million characters — narrating every product page, voicing every notification — than price against what the market is used to paying.

Where to go next

The model

Precision served, the full voice list, accepted parameters and licence.

kokoro-82m →

The docs

Authentication, error shapes, rate limits and how billing is metered.

Quickstart →

The playground

Type a sentence, pick a voice and listen, before writing any code.

Open the playground →

Your text is not retained

What we keep about a synthesis is the character count we billed you on, its cost and whether it succeeded. Our usage table has no column the input text could be written into, so keeping it would take a schema migration rather than a lapse — the reasoning is set out in full on the transparency page.

Text-to-speech API · Infersia