跳到正文
原文
OpenRouter:Announcements(RSS)·· 21 天前精选AI 评分63

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

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

AI 导读

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

推荐理由

教程给出 OpenRouter 统一 TTS 端点的完整调用与校验方法,换模型只改 model 和 voice 两行即可迁移。

正文 · AI 翻译

我们通过 OpenAI 兼容的 POST /api/v1/audio/speech 端点支持文本转语音。发送文本、模型和支持的语音,然后保存或流式传输音频。一个 API 密钥即可使用相同的请求结构访问来自 多个提供商 的 TTS 模型。

本教程涵盖身份验证、合成、响应验证、流式传输以及模型或语音更改。

简而言之

  • 将 TTS 请求发送到 https://openrouter.ai/api/v1/audio/speech。
  • 使用 OpenAI Python SDK,将 base_url 设置为 https://openrouter.ai/api/v1。
  • 当模型支持其他语音时,只需更改一行中的 voice 值。切换提供商时,请同时更改匹配的模型和语音。

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

你在请求正文中指定模型。无论选择哪个提供商的语音模型,端点、身份验证和响应处理都保持不变。

我们的 音频 API 公告 涵盖了更广泛的发布内容。如需语音转文本,请使用我们的 转录指南。

使用 OpenRouter 文本转语音需要什么

创建 OpenRouter API 密钥 并将其存储在环境变量中,以免出现在源代码里。

在 macOS 或 Linux 上,为当前终端会话设置变量:

export OPENROUTER_API_KEY="your-api-key"

所有示例都使用 https://openrouter.ai/api/v1 作为基础 URL,并在 Authorization: Bearer 标头 中发送密钥。

该端点接受两个必填字段,以及大多数模型都需要的语音:

  • model 选择语音模型。
  • input 包含你希望模型朗读的文本。
  • voice 选择该模型支持的语音。仅当提供商 记录了默认语音 时,你才可以省略它,因此实际上应将其视为必填项。

response_format 和 speed 是可选的,但显式设置输出格式会使响应更可预测,因为格式支持因模型而异。省略 response_format 时,我们的端点默认为 PCM,而 Mistral Voxtral Mini TTS 仅接受 MP3,并且 speed 仅在支持它的模型上更改语速。

成功的请求返回原始音频字节,而不成功的请求返回 JSON。在将其写入音频文件之前,请验证响应。

明确了密钥和响应行为后,你就可以生成第一个音频文件了。

使用 cURL 生成你的第一个 MP3

以下请求使用 Mistral Voxtral Mini TTS 及其 en_paul_neutral 语音。它将返回的字节直接保存到 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

这些标志可帮助你正确处理失败的请求。--fail-with-body 使 cURL 在收到 4xx 或 5xx 响应时以错误退出,并且由于设置了 --output,它会将服务器的 JSON 错误正文写入 output.mp3 而不是终端。当命令失败时,使用 cat output.mp3 读取错误并在重试前删除文件,以免将 JSON 文件作为音频播放。--dump-header 保存响应标头,以便你可以确认内容类型并捕获生成 ID。

在播放音频之前,请确认 output.mp3 存在且包含数据:

ls -lh output.mp3

在 macOS 上,你可以使用 afplay output.mp3 播放它。在 Linux 上,请使用已安装的播放器,例如 ffplay。

当你将此请求移入应用程序代码时,请在保存之前确认请求成功且响应包含音频。这些检查可防止将 JSON 错误响应写入 MP3 文件。

使用 Python 生成并保存语音

如果你的项目尚未使用 requests,请安装它:

python -m pip install requests

此示例在保存文件之前检查 HTTP 状态并验证我们返回了 MP3 数据:

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}")

当 API 返回 4xx 或 5xx 响应时,raise_for_status() 会抛出异常,从而阻止应用程序将错误响应体保存为音频。如果请求成功,content-type 检查会确认响应中包含音频,然后再将其写入文件。记录 X-Generation-Id,以便追踪请求或在联系支持时提供参考。

当 SDK 管理响应流时,同样的验证也适用。下一个示例保留 OpenRouter 基础 URL,并将文件处理移入 OpenAI Python 客户端。

使用 OpenAI Python SDK 流式传输响应

我们的 TTS 端点遵循 OpenAI Audio Speech API 的结构。你可以将 OpenAI 客户端指向我们的基础 URL,并将 HTTP 响应流式写入文件:

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"))

此模式在保存文件的同时增量读取响应。渐进式播放需要能够缓冲传入数据块的播放器。

JavaScript 可以通过 arrayBuffer() 读取相同的响应。此示例在创建文件之前检查状态和内容类型:

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"));

当你需要更小且能兼容标准音频播放器的文件时,请选择 MP3。PCM 避免了压缩开销,并可在兼容的实时流式管道中降低延迟。我们返回 MP3 为 audio/mpeg,PCM 为 audio/pcm,可选地带有 rate 和 channels 参数,不过可用格式取决于所选模型。Mistral Voxtral Mini TTS 仅接受 MP3,因此请求 PCM 会返回 400 错误。播放原始 PCM 还需要正确的音频设置,因为将文件扩展名改为 .mp3 并不会转换音频格式。

传输代码在受支持的模型之间保持不变。模型和语音字段必须保持为有效的配对。

更改 TTS 模型和语音

语音标识符属于特定模型。在同一模型内比较语音只需更改一行。例如,当前的 Grok Voice TTS 1.0 模型页面 列出了五个内置语音:eve、ara、rex、sal 和 leo。

从这个模型和语音配对开始:

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

然后只更改语音那一行:

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

Grok 示例还展示了从 Mistral 到 xAI 的提供商变更。请同时更新模型和语音,因为每个提供商都公开自己的模型和语音 ID,而端点、身份验证、输入和响应检查保持不变:

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

在发送请求之前,请在所选模型页面上确认这两个值,因为模型可用性和语音目录可能会发生变化。

使用 Models API 检索当前的 TTS 模型:

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

你也可以浏览我们的 文本转语音模型集合。

模型 ID示例语音显著选项
mistralai/voxtral-mini-tts-2603en_paul_neutral通过 OpenRouter 语音端点输出 MP3
x-ai/grok-voice-tts-1.0eve、ara、rex、sal、leo五个内置语音,支持 20 多种语言
microsoft/mai-voice-2en-US-Harper:MAI-Voice-2speed、Azure style 和 styledegree

我们的 TTS 文档 描述了你可以通过 provider.options.<provider> 为支持这些选项的模型传递的提供商特定选项。截至 2026 年 9 月,实时目录中没有 OpenAI 语音模型,因此在依赖提供商特定字段之前,请检查当前模型列表。

Microsoft MAI-Voice-2 接受 Azure 语音名称。它还支持文档中说明的 speed 范围(0.5 到 2.0)以及富有表现力的 Azure 选项:

{
  "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
      }
    }
  }
}

这些控件仍然是提供商特定的。不支持的提供商可能会忽略 speed,并且样式取决于所选语音。请将提供商选项放在匹配的模型配置旁边。

模型和语音选择决定了哪些格式和表现力控件可用。生产路径必须在每条生成记录中保留这些设置。

为生产环境准备集成

在句子或段落边界处拆分长输入,按顺序请求每个分段,并使用能识别格式的工具合并音频。这能提高可靠性,并更早返回第一个分段。

对每个分段应用相同的响应检查:

  • 遇到非成功的 HTTP 状态码时停止。
  • 确认 Content-Type 与请求的格式匹配。
  • 拒绝空响应。
  • 记录 X-Generation-Id,同时记录模型、语音、格式和应用请求 ID。
  • 在重试前对响应进行分类,这样永久性的请求失败就不会进入退避循环。

重试 429、502、503、524 和 529 响应,因为速率限制、提供商错误、临时不可用、超时和提供商过载可能会在后续尝试中消除。当响应包含 Retry-After 头时,遵循该头。否则,使用有上限的指数退避,并在少量尝试后停止。在修正请求、凭据或可用额度之前,不要重试 400、401 或 402 响应。

大多数 TTS 模型按输入文本的字符数计费,而 Gemini TTS 模型按输入和输出 token 计费。某些模型(例如 deepgram/flux-tts:free)标价为零成本。在估算生产成本之前,请查看当前模型页面或 Models API。

这些控制措施涵盖了可靠性、可追溯性和成本。其余的失败通常来自将错误响应体保存为音频,或将模型与不支持的语音或格式组合使用。

排查常见的 OpenRouter TTS 错误

为什么 MP3 里包含 JSON?

API 返回了错误,而程序在未检查状态的情况下保存了其响应体。在写入响应之前,调用 raise_for_status() 或检查状态码。

为什么音频文件为空或损坏?

空文件或无法读取的文件通常意味着请求未返回音频数据,或者响应以错误的格式保存。在保存之前,检查响应大小和 Content-Type。将 audio/mpeg 保存为 MP3,并将 audio/pcm 作为原始 PCM 处理,同时使用正确的播放器设置,因为将扩展名改为 .mp3 并不会转换音频。

为什么 OpenRouter 拒绝该语音?

语音标识符因模型而异。查看所选模型页面,并发送其支持的语音之一。每当更换模型时,都要重新检查语音。

为什么提供商选项没有效果?

提供商控制项只会到达匹配的提供商,以提供商 slug 为键。将 MAI-Voice-2 风格的控制项放在 provider.options.azure 下。某些提供商会静默忽略不支持的 speed 值。

在涵盖了响应检查和提供商特定设置之后,剩下的问题集中在端点、OpenAI SDK 兼容性以及查找当前 TTS 模型上。

常见问题

OpenRouter 有文本转语音功能吗?

有。向 https://openrouter.ai/api/v1/audio/speech 发送 POST 请求,包含模型、文本输入以及该模型支持的语音。我们会以所选模型支持的格式返回原始音频字节。

OpenRouter TTS 与 OpenAI SDK 兼容吗?

兼容。将 SDK 基础 URL 设置为 https://openrouter.ai/api/v1,并使用你的 OpenRouter API 密钥。模型 ID、语音 ID 和提供商特定控制项仍必须与你选择的模型匹配。

如何使用文本转语音 API?

向 https://openrouter.ai/api/v1/audio/speech 发送经过身份验证的 POST 请求,包含 model、input 和 voice。设置受支持的 response_format,检查 HTTP 状态和内容类型,然后将返回的音频字节写入文件或传递给兼容的播放器。

OpenAI API 中的 TTS 是什么?

文本转语音通过 Audio Speech API 将文本输入转换为生成的音频。我们使用相同的请求结构,因此 OpenAI SDK 客户端在更改基础 URL 并提供 OpenRouter API 密钥后,即可调用受支持的 OpenRouter TTS 模型。

如何查找当前的 OpenRouter TTS 模型?

请求 GET /api/v1/models?output_modalities=speech 或浏览 文本转语音合集。使用模型页面确认支持的语音和当前定价。

在这些工作流中,端点、身份验证和响应检查保持一致。模型特定的语音、格式和控制项是你在每次集成或比较之前需要确认的值。

使用 OpenRouter 生成语音

在端点、模型、语音和响应检查都就绪后,你可以通过 cURL、Python、JavaScript 或 OpenAI SDK 生成可播放的音频文件。请求结构在 TTS 模型之间保持一致,而每个模型决定可用的语音、格式和提供商控制项。

当你准备好生成第一个文件时,创建 API 密钥。在比较模型或为生产环境准备集成时,浏览我们的 文本转语音模型合集 和 TTS 参考文档。

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