OpenRouter 文本转语音 API 五分钟教程

OpenRouter:Announcements(RSS)·2026-09-11 08:00·15小时前
AI 导读

OpenRouter 通过 OpenAI 兼容的 POST /api/v1/audio/speech 端点提供文本转语音服务,一个 API key 可调用多家供应商的 TTS 模型。

OpenRouter:Announcements(RSS)
56AI 编辑部评分,满分 100

OpenRouter 文本转语音 API 五分钟教程

2026-09-11 08:00· 15小时前
AI 导读

OpenRouter 通过 OpenAI 兼容的 POST /api/v1/audio/speech 端点提供文本转语音服务,一个 API key 可调用多家供应商的 TTS 模型。

OpenRouter Text-to-Speech: API Tutorial in 5 Minutes

We support text-to-speech through the OpenAI-compatible POST /api/v1/audio/speech endpoint. Send text, a model, and a supported voice, then save or stream the audio. One API key reaches TTS models from multiple providers using the same request structure.

This tutorial covers authentication, synthesis, response validation, streaming, and model or voice changes.

Tl;dr

  • Send TTS requests to https://openrouter.ai/api/v1/audio/speech.
  • Use the OpenAI Python SDK by setting base_url to https://openrouter.ai/api/v1.
  • Change the voice value in one line when the model supports another voice. Change the matching model and voice together when you switch providers.

Diagram showing a request with text, voice, and output format entering POST /api/v1/audio/speech, reaching the Mistral Voxtral Mini TTS model with xAI and Microsoft speech models as available alternatives, and returning one MP3 audio response

You name the model in the request body. The endpoint, authentication, and response handling stay the same whichever provider’s speech model you pick.

Our audio API announcement covers the wider launch. For speech-to-text, use our .

What you need to use OpenRouter text-to-speech

Create an OpenRouter API key and store it in an environment variable to keep it out of your source code.

On macOS or Linux, set the variable for your current terminal session:

export OPENROUTER_API_KEY="your-api-key"

All examples use https://openrouter.ai/api/v1 as the base URL and send the key in the Authorization: Bearer header.

The endpoint accepts two required fields plus a voice that most models require:

  • model selects the speech model.
  • input contains the text you want the model to speak.
  • voice selects a voice supported by that model. You can only omit it when the provider documents a default voice, so treat it as required in practice.

response_format and speed are optional, but explicitly setting the output format makes the response more predictable because format support varies by model. Our endpoint defaults to PCM when you omit response_format, while Mistral Voxtral Mini TTS accepts only MP3, and speed changes the speaking rate only on models that support it.

A successful request returns raw audio bytes, while a non-successful request returns JSON. Validate the response before writing it to an audio file.

With the key and response behavior clear, you can generate the first audio file.

Generate your first MP3 with cURL

The following request uses Mistral Voxtral Mini TTS and its en_paul_neutral voice. It saves the returned bytes directly to output.mp3.

curl --silent \
  --show-error \
  --fail-with-body \
  --request POST \
  --url https://openrouter.ai/api/v1/audio/speech \
  --header "Authorization: Bearer $OPENROUTER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "model": "mistralai/voxtral-mini-tts-2603",
    "input": "OpenRouter turns this text into speech through one API endpoint.",
    "voice": "en_paul_neutral",
    "response_format": "mp3"
  }' \
  --dump-header output.headers \
  --output output.mp3

These flags help you handle failed requests correctly. --fail-with-body makes cURL exit with an error on a 4xx or 5xx response, and because --output is set, it writes the server’s JSON error body into output.mp3 instead of the terminal. When the command fails, read the error with cat output.mp3 and delete the file before retrying, so you don’t play a JSON file as audio. --dump-header saves the response headers so you can confirm the content type and capture the generation ID.

Before playing the audio, confirm that output.mp3 exists and contains data:

ls -lh output.mp3

On macOS, you can play it with afplay output.mp3. On Linux, use an installed player such as ffplay.

When you move this request into application code, confirm that the request succeeded and that the response contains audio before saving it. These checks prevent a JSON error response from being written to an MP3 file.

Generate and save speech with Python

Install requests if your project doesn’t already use it:

python -m pip install requests

This example checks the HTTP status and verifies that we returned MP3 data before saving the file:

import os
from pathlib import Path

import requests

response = requests.post(
    "https://openrouter.ai/api/v1/audio/speech",
    headers={
        "Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "model": "mistralai/voxtral-mini-tts-2603",
        "input": (
            "OpenRouter turns this text into speech through one API endpoint."
        ),
        "voice": "en_paul_neutral",
        "response_format": "mp3",
    },
    timeout=60,
)

response.raise_for_status()

content_type = response.headers.get("Content-Type", "").split(";")[0]
if content_type != "audio/mpeg":
    raise RuntimeError(f"Expected audio/mpeg, received {content_type}")

Path("output.mp3").write_bytes(response.content)

generation_id = response.headers.get("X-Generation-Id")
print(f"Saved output.mp3. Generation ID: {generation_id}")

raise_for_status() raises an exception when the API returns a 4xx or 5xx response, preventing the application from saving the error body as audio. If the request succeeds, the content-type check confirms that the response contains audio before writing it to a file. Record the X-Generation-Id so you can trace the request or provide a reference when contacting support.

The same validation applies when an SDK manages the response stream. The next example keeps the OpenRouter base URL and moves the file handling into the OpenAI Python client.

Stream the response with the OpenAI Python SDK

Our TTS endpoint follows the OpenAI Audio Speech API shape. You can point the OpenAI client at our base URL and stream the HTTP response to a file:

import os
from pathlib import Path

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["OPENROUTER_API_KEY"],
    base_url="https://openrouter.ai/api/v1",
)

with client.audio.speech.with_streaming_response.create(
    model="mistralai/voxtral-mini-tts-2603",
    voice="en_paul_neutral",
    input="OpenRouter can stream this response into an audio file.",
    response_format="mp3",
) as response:
    response.stream_to_file(Path("output.mp3"))

This pattern reads the response incrementally while saving the file. Progressive playback requires a player that buffers the incoming chunks.

JavaScript can read the same response through arrayBuffer(). This example checks the status and content type before it creates the file:

import { writeFile } from "node:fs/promises";

const response = await fetch(
  "https://openrouter.ai/api/v1/audio/speech",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "mistralai/voxtral-mini-tts-2603",
      input: "OpenRouter returns audio bytes to JavaScript.",
      voice: "en_paul_neutral",
      response_format: "mp3",
    }),
  },
);

if (!response.ok) {
  throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}

const contentType = response.headers.get("content-type")?.split(";")[0];
if (contentType !== "audio/mpeg") {
  await response.body?.cancel();
  throw new Error(`Expected audio/mpeg, received ${contentType}`);
}

await writeFile("output.mp3", Buffer.from(await response.arrayBuffer()));
console.log(response.headers.get("x-generation-id"));

Choose MP3 when you need a smaller file that works with standard audio players. PCM avoids compression overhead and can reduce latency in compatible real-time streaming pipelines. We return MP3 as audio/mpeg and PCM as audio/pcm, optionally with rate and channels parameters, although the available formats depend on the selected model. Mistral Voxtral Mini TTS accepts MP3 only, so requesting PCM returns a 400 error. Playing raw PCM also requires the correct audio settings because changing the file extension to .mp3 doesn’t convert the audio format.

The transport code remains the same across supported models. The model and voice fields must remain a valid pair.

Change the TTS model and voice

Voice identifiers belong to specific models. A voice comparison within the same model can change one line. For example, the current Grok Voice TTS 1.0 model page lists five built-in voices: eve, ara, rex, sal, and leo.

Start with this model and voice pair:

"model": "x-ai/grok-voice-tts-1.0",
"voice": "eve"

Then change only the voice line:

- "voice": "eve"
+ "voice": "ara"

The Grok example also demonstrates a provider change from Mistral to xAI. Update the model and voice together, since each provider exposes its own model and voice IDs, while the endpoint, authentication, input, and response checks remain unchanged:

- "model": "mistralai/voxtral-mini-tts-2603",
- "voice": "en_paul_neutral"
+ "model": "x-ai/grok-voice-tts-1.0",
+ "voice": "eve"

Confirm both values on the selected model page before sending the request because model availability and voice catalogs can change.

Use the Models API to retrieve the current TTS models:

curl "https://openrouter.ai/api/v1/models?output_modalities=speech"

You can also browse our .

Model IDExample voicesNotable option
mistralai/voxtral-mini-tts-2603en_paul_neutralMP3 output through the OpenRouter speech endpoint
x-ai/grok-voice-tts-1.0eve, ara, rex, sal, leoFive built-in voices across 20+ languages
microsoft/mai-voice-2en-US-Harper:MAI-Voice-2speed, Azure style, and styledegree

Our TTS documentation describes provider-specific options you can pass through provider.options.<provider> for models that support them. No OpenAI speech model is in the live catalog as of September 2026, so check the current model list before you rely on a provider-specific field.

Microsoft MAI-Voice-2 accepts Azure voice names. It also supports a documented speed range from 0.5 to 2.0 and expressive Azure options:

{
  "model": "microsoft/mai-voice-2",
  "input": "Welcome to the product update.",
  "voice": "en-US-Harper:MAI-Voice-2",
  "response_format": "mp3",
  "speed": 1.0,
  "provider": {
    "options": {
      "azure": {
        "style": "cheerful",
        "styledegree": 1.2
      }
    }
  }
}

These controls remain provider-specific. Unsupported providers may ignore speed, and styles depend on the selected voice. Keep provider options beside the matching model configuration.

Model and voice selection determine which formats and expressive controls are available. The production path must preserve those settings with each generation record.

Prepare the integration for production

Split long input at sentence or paragraph boundaries, request each segment in order, and combine the audio with format-aware tooling. This improves reliability and returns the first segment sooner.

Apply the same response checks to every segment:

  • Stop on non-successful HTTP status codes.
  • Confirm Content-Type matches the requested format.
  • Reject empty responses.
  • Record X-Generation-Id with the model, voice, format, and application request ID.
  • Classify the response before retrying so permanent request failures don’t enter the backoff loop.

Retry 429, 502, 503, 524, and 529 responses because rate limits, provider errors, temporary unavailability, timeouts, and provider overload can clear on a later attempt. Follow the Retry-After header when the response includes one. Otherwise, use capped exponential backoff and stop after a small number of attempts. Don’t retry 400, 401, or 402 responses until you correct the request, credentials, or available credits.

TTS models are priced per character of input text. Pricing varies by model and provider, so check the current model page or Models API before estimating production cost.

These controls cover reliability, traceability, and cost. The remaining failures usually come from saving an error body as audio or combining a model with an unsupported voice or format.

Troubleshoot common OpenRouter TTS errors

Why does the MP3 contain JSON?

The API returned an error, and the program saved its body without checking the status. Call raise_for_status() or inspect the status code before writing the response.

Why is the audio file empty or corrupted?

An empty or unreadable file usually means the request returned no audio data or the response was saved in the wrong format. Check the response size and Content-Type before saving it. Save audio/mpeg as MP3, and handle audio/pcm as raw PCM with the correct player settings because changing the extension to .mp3 doesn’t convert the audio.

Why does OpenRouter reject the voice?

Voice identifiers vary by model. Check the selected model page and send one of its supported voices. Recheck the voice whenever you change the model.

Why does a provider option have no effect?

Provider controls only reach the matching provider. Put OpenAI instructions under provider.options.openai and Azure style controls under provider.options.azure. Some providers silently ignore unsupported speed values.

With the response checks and provider-specific settings covered, the remaining questions focus on the endpoint, OpenAI SDK compatibility, and finding current TTS models.

FAQ

Does OpenRouter have text-to-speech?

Yes. Send a POST request to https://openrouter.ai/api/v1/audio/speech with a model, text input, and a voice the model supports. We return raw audio bytes in a format supported by the selected model.

Is OpenRouter TTS compatible with the OpenAI SDK?

Yes. Set the SDK base URL to https://openrouter.ai/api/v1 and use your OpenRouter API key. Model IDs, voice IDs, and provider-specific controls must still match the model you select.

How do I use a text-to-speech API?

Send an authenticated POST request to https://openrouter.ai/api/v1/audio/speech with model, input, and voice. Set a supported response_format, check the HTTP status and content type, then write the returned audio bytes to a file or pass them to a compatible player.

What is TTS in the OpenAI API?

Text-to-speech converts text input into generated audio through the Audio Speech API. We use the same request structure, so OpenAI SDK clients can call supported OpenRouter TTS models after you change the base URL and provide an OpenRouter API key.

How do I find current OpenRouter TTS models?

Request GET /api/v1/models?output_modalities=speech or browse the . Use the model page to confirm supported voices and current pricing.

The endpoint, authentication, and response checks stay consistent across these workflows. Model-specific voices, formats, and controls are the values you confirm before each integration or comparison.

Generate speech with OpenRouter

With the endpoint, model, voice, and response checks in place, you can produce a playable audio file through cURL, Python, JavaScript, or the OpenAI SDK. The request structure remains consistent across TTS models, while each model determines the available voices, formats, and provider controls.

Create an API key when you’re ready to generate your first file. Browse our and TTS reference as you compare models or prepare the integration for production.

来源:OpenRouter:Announcements(RSS)· openrouter.ai