ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

9Router 文本转语音(TTS)API 完整实战指南:从 /v1/audio/speech 到多提供商语音合成

9Router 文本转语音(TTS)API 完整实战指南:从 /v1/audio/speech 到多提供商语音合成 9Router 文本转语音TTSAPI 完整实战指南从 /v1/audio/speech 到多提供商语音合成【免费下载链接】9routerUnlimited FREE AI coding. Connect Claude Code, Codex, Cursor, Cline, Copilot, Antigravity to FREE Claude/GPT/Gemini via 40 providers. Auto-fallback, RTK -40% tokens, never hit limits.项目地址: https://gitcode.com/GitHub_Trending/9r/9router本篇技术指南以 9Router 技能文档 skills/9router-tts/SKILL.md 为核心骨架系统讲解如何通过 OpenAI 兼容的/v1/audio/speech接口把文字转换为语音。文中覆盖模型与音色发现、请求格式、响应格式、以及 OpenAI、ElevenLabs、Edge TTS、Google TTS、Deepgram 等十余家提供商的model参数格式差异并结合仓库源码speech 路由、TTS 处理器、核心合成器深入剖析其内部实现。读完本文你将能够在任意语言环境中curl、Node.js、Python 等一键调用 9Router 完成语音合成并理解其统一接口、多提供商、自动回退的底层机制。一、环境准备两个环境变量9Router 的 TTS 能力通过统一的 OpenAI 兼容 HTTP 接口暴露调用前需要配置两个环境变量变量必填说明NINEROUTER_URL是9Router 服务的根地址例如自建部署的http://localhost:3000NINEROUTER_KEY视配置而定API 密钥仅当服务端开启了鉴权requireApiKey时需要从源码看密钥校验逻辑位于 src/sse/handlers/tts.js处理器在收到请求后会读取本地设置若settings.requireApiKey为真则从请求中提取 API Key 并校验缺失或非法时分别返回401 Missing API key与401 Invalid API key。若你的部署未开启鉴权则NINEROUTER_KEY可以省略。服务的整体初始化与技能接入方式见 skills/9router/SKILL.mdTTS 只是 9Router 众多多模态能力之一同一套鉴权与模型路由机制同样适用于聊天、图像、语音识别等接口。二、发现能力列出 TTS 模型、元数据与音色在正式合成之前建议先通过三个只读接口侦察可用的模型与音色。这三个接口在仓库中均有对应实现且全部返回 OpenAI 风格的{ object: list, data: [...] }结构。1列出所有 TTS 模型curl $NINEROUTER_URL/v1/models/tts | jq .data[].id该接口实现位于 src/app/api/v1/models/[kind]/route.jstts是支持的 kind 之一其余为image、stt、embedding、image-to-text、web。它按能力类型过滤模型列表返回形如el/eleven_multilingual_v2、openai/tts-1、edge-tts/vi-VN-HoaiMyNeural的完整模型 ID。2查询单个模型的元数据curl $NINEROUTER_URL/v1/models/info?idel/eleven_multilingual_v2实现见 src/app/api/v1/models/info/route.js。返回的元数据包括id、name、kind、owned_by、endpoint对应/v1/audio/speech并附带params、capabilities、options等扩展字段。关键点对于支持按 ID 选音色的提供商elevenlabs、edge-tts、deepgram、inworld、local-device返回结果中还包含voicesUrl字段指向对应的音色列表接口源码。3列出具体提供商的音色# 列出 edge-tts 的全部音色可用 ?langvi 按语言过滤 curl $NINEROUTER_URL/v1/audio/voices?provideredge-ttslangvi | jq .data[].model音色接口实现位于 src/app/api/v1/audio/voices/route.js目前支持的提供商为elevenlabs、deepgram、inworld、edge-tts、local-device源码。不传lang时返回该提供商全部音色按语言分组后展平传lang时仅返回该语言下的音色。每个音色条目包含id、name、lang、gender以及可直接用于/v1/audio/speech的完整model字符串由提供商别名前缀 音色 ID 拼成见 源码。重要约定/v1/audio/speech请求体里的model字段本质上是音色 ID 或模型音色组合串而非传统的 LLM 模型名。例如edge-tts/vi-VN-HoaiMyNeural、el/voice_id或直接写openai/tts-1此时使用该模型的默认音色。三、合成端点POST /v1/audio/speechPOST $NINEROUTER_URL/v1/audio/speech该端点的实现入口是 src/app/api/v1/audio/speech/route.js它把请求直接转交给handleTts处理。请求体字段如下字段必填说明model是音色 ID 或模型/音色取自/v1/models/tts或/v1/audio/voicesinput是要朗读的文本请求体校验同样在 src/sse/handlers/tts.js缺model返回400 Missing model缺input返回400 Missing required field: input。查询参数response_format通过 URL 查询参数控制返回格式?response_formatmp3默认直接返回原始音频字节流Content-Type为audio/mp3?response_formatjson返回 JSON包含 base64 编码的音频与格式信息{ audio: SUQzBAAAA..., format: mp3 }响应格式的拼接逻辑见 open-sse/handlers/ttsCore.jsjson模式返回{audio: base64, format}的 JSON二进制模式则按audio/${format}设置 Content-Type 并附带Content-Length两种模式均带 CORS 头。可选字段language请求体还可携带可选的language字段作为语言提示目前用于 Gemini 提供商源码。例如{model:gemini/...,input:你好,language:zh-CN}。四、实战示例curl 与 Node.jscurl 保存 MP3curl -X POST $NINEROUTER_URL/v1/audio/speech \ -H Authorization: Bearer $NINEROUTER_KEY \ -H Content-Type: application/json \ -d {model:openai/tts-1,input:Hello world} \ --output speech.mp3Node.js 保存文件import { writeFile } from node:fs/promises; const r await fetch(${process.env.NINEROUTER_URL}/v1/audio/speech, { method: POST, headers: { Authorization: Bearer ${process.env.NINEROUTER_KEY}, Content-Type: application/json, }, body: JSON.stringify({ model: el/eleven_multilingual_v2, input: Xin chào }), }); await writeFile(speech.mp3, Buffer.from(await r.arrayBuffer()));Python 示例requestsimport requests resp requests.post( f{NINEROUTER_URL}/v1/audio/speech, headers{Authorization: fBearer {NINEROUTER_KEY}}, json{model: edge-tts/vi-VN-HoaiMyNeural, input: Xin chào}, ) open(speech.mp3, wb).write(resp.content)若需要 JSON 格式只需追加查询参数POST $NINEROUTER_URL/v1/audio/speech?response_formatjson然后对返回的audio字段做 base64 解码即可。五、提供商差异model 格式速查表不同提供商对model字段的格式约定差异较大这是使用 TTS 接口时最容易踩坑的地方。以下完整继承自技能文档并补充说明Providermodel格式说明openaitts-1/alloy模型/音色或仅音色默认模型gpt-4o-mini-ttselevenlabsmodel_id/voice_id或voice_id默认模型eleven_flash_v2_5音色可在 Dashboard 查看openrouteropenai/gpt-4o-mini-tts/alloy通过 chat-completions 的 audio 模态流式输出edge-tts音色 ID如vi-VN-HoaiMyNeural无需鉴权默认vi-VN-HoaiMyNeuralgoogle-tts语言代码如en、vi无需鉴权local-device操作系统语音名say -v ?/ SAPI无需鉴权需要本机安装ffmpegdeepgramaura-asteria-en等Token 鉴权nvidia、inworld、cartesia、playhtmodel/voice提供商专属鉴权头coqui、tortoisespeaker / voice ID本地 localhost无需鉴权hyperbolic模型 ID请求体只有{text}源码层面的解析规则无论采用哪种格式最终都要经过统一的model/voice拆解。核心实现在 open-sse/handlers/ttsProviders/_base.js 的parseModelVoice函数优先与已知模型 ID 列表做最长前缀匹配若model恰好等于某模型 ID则使用该模型 默认音色若以模型ID/开头则后半段作为音色匹配不到时取最后一个/分割模型/音色兜底模型ID/音色整体作为默认模型音色用默认值。以 OpenAI 适配器为例open-sse/handlers/ttsProviders/openai.jsopenai/tts-1/alloy会被拆成模型tts-1与音色alloy再转发到上游POST /v1/audio/speech若只传alloy则使用默认模型gpt-4o-mini-tts。六、架构与内部原理一次 TTS 请求的完整旅程理解内部调用链有助于排查问题和发挥接口的全部能力。一次合成请求会依次经过以下层级POST /v1/audio/speech └─ src/app/api/v1/audio/speech/route.js ← 路由入口 └─ src/sse/handlers/tts.js handleTts ← 校验 路由分发 ├─ 鉴权校验requireApiKey ├─ 参数校验model / input ├─ Combo 展开可选→ open-sse/services/combo.js └─ handleSingleModelTts ├─ 无凭据提供商 → 直接合成 └─ 有凭据提供商 → 凭据轮询 失败回退 └─ open-sse/handlers/ttsCore.js handleTtsCore ├─ 专用适配器SPECIAL_ADAPTERS └─ 通用配置驱动synthesizeViaConfig └─ ttsProviders/{provider}.js1Combo 多模型聚合handleTts在正式合成前会检查model是否为已配置的 Combo 名称源码。若命中 Combo会按其策略fallback回退 / 轮询等在多个 TTS 模型间自动切换实现一个 Combo 名 一组可用音色自动兜底。Combo 的建模与路由逻辑在 open-sse/services/combo.js与聊天接口共用同一套机制。2凭据管理与失败回退对于需要凭据的提供商elevenlabs、openai、deepgram、inworld 等处理器维护了一个CREDENTIALED_PROVIDERS集合源码凡声明了serviceKinds含tts、且noAuth不为真、且ttsConfig.authType ! none的提供商都算在内。对这类提供商请求进入凭据轮询 失败回退循环源码每次取一组可用凭据合成若上游报错则通过markAccountUnavailable标记该账号暂不可用并尝试下一个账号直到成功或全部账号耗尽。这意味着即使某个账号额度耗尽也能自动切到备用账号继续合成。3适配器与通用调度核心合成器 open-sse/handlers/ttsCore.js 采用专用适配器 通用配置驱动双轨制专用适配器google-tts、edge-tts、local-device、elevenlabs、openai、openrouter、gemini七个提供商有自定义的synthesize()逻辑注册表见 open-sse/handlers/ttsProviders/index.js通用配置驱动其余提供商hyperbolic、deepgram、nvidia、huggingface、inworld、cartesia、playht、coqui、tortoise、qwen 等通过ttsConfig.format映射到 genericFormats.js 中的格式处理器按统一的{baseUrl, apiKey, text, modelId, voiceId}参数调用源码。上游返回的音频统一转成{base64, format}内部结构见 _base.js会根据 Content-Type 识别wav/mp3/ogg最终由createTtsResponse按response_format打包返回给调用方。七、实践建议与常见问题优先走发现三步曲写死音色 ID 容易在提供商调整音色后失效建议在应用启动时调用/v1/models/tts或/v1/audio/voices动态获取可用的model值。无需鉴权的提供商edge-tts、google-tts、local-device、coqui、tortoise免费可用适合快速验证链路或做低成本批量合成local-device依赖本机语音库与ffmpeg运行环境需提前准备。超长文本input为单次请求的文本超长文本建议先分段再逐段合成最后按序拼接音频。调试技巧返回400 Invalid model format时检查model是否带上了合法前缀如el/、openai/、edge-tts/返回503且提示All accounts unavailable时通常是该提供商所有已存凭据均被标记为限流可稍后重试或在仪表盘中补充凭据。Combo 兜底把多个提供商/音色组织成 Combo可显著提升合成的可用性——单一上游抖动时自动回退不影响最终用户体验。八、延伸阅读技能定义文件skills/9router-tts/SKILL.md本文骨架来源9Router 主技能环境初始化skills/9router/SKILL.md路由与处理器src/app/api/v1/audio/speech/route.js、src/app/api/v1/audio/voices/route.js、src/sse/handlers/tts.js核心合成与提供商适配open-sse/handlers/ttsCore.js、open-sse/handlers/ttsProviders/index.js、open-sse/handlers/ttsProviders/openai.js、open-sse/handlers/ttsProviders/_base.js模型发现接口src/app/api/v1/models/[kind]/route.js、src/app/api/v1/models/info/route.js单元测试示例tests/unit/gemini-tts.test.js、tests/unit/minimax-tts.test.js含response_format与音色列表的断言可作为接口行为的可执行文档【免费下载链接】9routerUnlimited FREE AI coding. Connect Claude Code, Codex, Cursor, Cline, Copilot, Antigravity to FREE Claude/GPT/Gemini via 40 providers. Auto-fallback, RTK -40% tokens, never hit limits.项目地址: https://gitcode.com/GitHub_Trending/9r/9router创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表