Puter TTSVoice 对象详解:AI 文本转语音音色元数据与实战调用指南
【免费下载链接】puter🌐 The Internet Computer! Free, Open-Source, and Self-Hostable.项目地址: https://gitcode.com/GitHub_Trending/pu/puter
TTSVoice是 Puter AI 平台中描述"某个文本转语音(TTS)供应商可用音色"的数据对象。本文以 TTSVoice 对象文档 为骨架,完整讲解其id、name、provider、language、category、labels、supported_models、supported_engines等全部字段的语义与可选性,并对照 txt2speech.listVoices()、txt2speech() 两个接口文档及仓库后端源码给出可运行的调用示例。读完本文,你将掌握如何在浏览器、Node.js、App 或 Worker 中枚举、过滤并挑选语音,把正确的 voice id 传入语音合成调用。
背景:TTSVoice 在 Puter AI 语音能力中的位置
Puter 将多家第三方 TTS 供应商(AWS Polly、OpenAI、ElevenLabs、Gemini、xAI、Speechify)抽象成统一接口puter.ai.txt2speech。当你想让应用"开口说话"时,通常需要先回答两个问题:
- 该供应商当前提供哪些音色(voice)?
- 某个音色支持哪些引擎/模型、语言与附加元数据?
TTSVoice对象就是第 1 个问题的标准答案格式:它是 listVoices 接口返回数组的元素类型。根据 后端类型定义,ITTSVoice在源码中的结构为:
export interface ITTSVoice { id: string; name: string; language?: { name: string; code: string; }; description?: string; category?: string; provider: string; labels?: Record<string, string>; supported_models?: string[]; supported_engines?: string[]; }该接口由统一的puter-ttsdriver 的list_voices()方法调用各供应商listVoices(args)后归一化返回(见 TTSDriver.ts);当传入provider: 'all'时,driver 会遍历所有已注册 provider 并拼接结果。对象文档中带May be absent(可缺失)字样的字段在 TS 类型中恰好对应?可选标记——这说明同一数组内的对象字段并不完全同构,不同供应商返回的元数据详略差异很大,消费端代码应做空值防御。
属性详解
下文逐字段说明 TTSVoice 文档 定义的 9 个属性。
id(String,必有)
传给puter.ai.txt2speech()的音色标识符。它是整个对象最关键的字段:枚举音色的最终目的,就是拿到一个能在合成调用中被识别的 id。典型取值如 OpenAI 的'alloy'、AWS Polly 的'Joanna'、ElevenLabs 的'21m00Tcm4TlvDq8ikWAM'(Rachel 示例音色)、Gemini 的'Puck'、xAI 的'eve'等。
注意 id 通常是供应商侧定义的原始值(大小写、连字符、下划线都可能保留原样),不要臆测规范化规则,直接回传即可。
name(String,必有)
人类可读的音色名称,例如"Alloy"、"Joanna"。它用于展示层(下拉菜单、设置面板、列表 UI),而真正传给合成接口的是id。在 listVoices 示例 中两者的配合非常典型:console.log(voice.id, voice.name)就是"面向机器取 id、面向用户显示 name"的用法。
provider(String,必有)
该音色所属的供应商,例如'aws-polly'、'openai'、'elevenlabs'、'gemini'、'xai'。当调用listVoices({ provider: 'all' })一次性拉取所有供应商时,这个字段是你按来源分组/过滤结果的唯一依据。供应商的"官方 id + 常见别名"全部定义在后端 providerAliases.ts 中:除六个规范名外,'eleven'、'google'、'grok'、'polly'、'simba'、'aws'等别名也会被normalizeTTSProvider()归一化到对应规范名;传入无法识别的供应商名时,接口会以bad_request错误拒绝。
language(Object,可选,可缺失)
描述音色语言的嵌套对象,包含两个 String 属性:
name:人类可读语言名,如"English (US)";code:语言代码,如"en-US"。
文档强调May be absent——例如 OpenAI 等偏向"中性音色"的供应商通常不提供语言字段。因此当你想用语言代码展示音色时,应先判断voice.language是否存在,官方示例即采用这种防御式写法:
const lang = voice.language ? ` (${voice.language.code})` : ''; console.log(`${voice.id} - ${voice.name}${lang}`);典型含此字段的返回项如下(来自 listVoices 文档 的示例响应):
{ "id": "Joanna", "name": "Joanna", "provider": "aws-polly", "language": { "name": "English (US)", "code": "en-US" }, "supported_engines": ["standard", "neural"] }注意:AWS Polly 对同一音色的语言归属非常明确,因此在与语言相关的合成参数上,Polly 还有独立的language参数(默认'en-US'),二者语义要区分开。
description(String,可选,可缺失)
音色的简短文字说明。例如 OpenAI 示例返回项中的"description": "A balanced, neutral voice"。适合做 UI 中的悬停提示或辅助选择文案,缺失时应做降级处理。
category(String,可选,可缺失)
音色类别,文档给出的示例值是'premade'(预置音色)。该字段常用于筛选"预置/自定义"音色。
labels(Object,可选,可缺失)
供应商自定义标签的键值对象。不同供应商会携带不同粒度的信息,后端类型将其建模为Record<string, string>(见 types.ts)。由于内容是 provider 专属的,跨供应商代码不应假设其中存在某个固定键。
supported_models(Array,可选,可缺失)
该音色可配合使用的模型 id 数组,元素为 String。例如某个音色可能仅支持['eleven_multilingual_v2']。若该字段存在,可用于在 UI 中禁用不兼容当前模型的音色;缺失时通常表示不限制。
supported_engines(Array,可选,可缺失)
该音色支持的引擎类型数组,元素为 String。在 AWS Polly 场景下取值如["standard", "neural"],恰好对应 txt2speech 文档 中 Polly 的engine参数可取值'standard'(默认)、'neural'、'long-form'、'generative'。这个字段非常适合做"选好音色后列出可用引擎供用户切换"的动态联动 UI。
如何获取 TTSVoice 数组:listVoices() 接口
TTSVoice对象只能通过puter.ai.txt2speech.listVoices()获得。该接口支持两种调用形态:
puter.ai.txt2speech.listVoices() puter.ai.txt2speech.listVoices(options)参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
options | Object(可选) | 支持provider、engine两个键,详见下表 |
options内可用项:
| Option | 类型 | 说明 |
|---|---|---|
provider | String | 要查询的 TTS 供应商。默认'aws-polly'。接受'aws-polly'、'openai'、'elevenlabs'、'gemini'、'xai',以及'all'(一次性列出所有供应商);常见别名如'eleven'、'google'、'grok'同样有效。无法识别的 provider 会被bad_request拒绝 |
engine | String | 引擎/模型过滤条件(供应商相关,部分供应商忽略) |
一个便捷规则:当options以普通字符串传入时,会被当作默认(AWS Polly)供应商的engine过滤器。
返回值
Promise,resolve 为TTSVoice对象数组。provider: 'all'时的示例响应(含可选字段缺失的情形):
[ { "id": "alloy", "name": "Alloy", "provider": "openai", "description": "A balanced, neutral voice" }, { "id": "Joanna", "name": "Joanna", "provider": "aws-polly", "language": { "name": "English (US)", "code": "en-US" }, "supported_engines": ["standard", "neural"] } ]可以看到第一条 OpenAI 音色没有language与supported_engines,第二条 Polly 音色没有description——这正是"可选字段可缺失"字段语义在真实数据中的体现。
完整可运行示例
浏览器(HTML)中列出某个供应商的音色:
<html> <body> <script src="https://js.puter.com/v2/"></script> <script> (async () => { const voices = await puter.ai.txt2speech.listVoices({ provider: 'openai' }); puter.print('OpenAI voices:'); for (const voice of voices) { puter.print(` ${voice.id} - ${voice.name}`); } })(); </script> </body> </html>Node.js 中列出默认(AWS Polly)全部音色并带语言代码:
const voices = await puter.ai.txt2speech.listVoices(); for (const voice of voices) { const lang = voice.language ? ` (${voice.language.code})` : ''; console.log(`${voice.id} - ${voice.name}${lang}`); }Node.js 中列出 Gemini 音色:
const voices = await puter.ai.txt2speech.listVoices({ provider: 'gemini' }); for (const voice of voices) { console.log(voice.id, voice.name); }在自托管场景下,该接口在服务端对应 TTSDriver.ts 的list_voices()实现:单供应商模式直接转发给目标 provider,'all'模式则遍历聚合。若需要进一步了解每个供应商侧的listVoices归一化逻辑,可查阅 src/backend/drivers/ai-tts/providers 下各 provider 目录(awsPolly、openai、elevenlabs、gemini、xai、speechify)及其同名测试文件。
实战:从 TTSVoice 到实际发声
拿到 TTSVoice 数组只是第一步,最终要用其中某个voice.id发起合成。下表将 txt2speech() 支持的主流供应商与音色/模型默认值汇总,帮助你理解不同 provider 的 TTSVoice 对象"语言与引擎字段为何呈现差异":
| Provider | 典型 voice 值 | 默认 model / engine | 语音风格相关参数 |
|---|---|---|---|
aws-polly | Joanna(默认)等,Polly 官方音色表 | engine:standard(默认)、neural、long-form、generative;language 默认en-US | ssml布尔开关 |
openai | alloy(默认)、ash、ballad、coral、echo、fable、nova、onyx、sage、shimmer | model:gpt-4o-mini-tts(默认)、tts-1、tts-1-hd;输出mp3/wav/opus/aac/flac/pcm | instructions风格引导 |
elevenlabs | 21m00Tcm4TlvDq8ikWAM(默认,Rachel) | model:eleven_multilingual_v2(默认)、eleven_flash_v2_5、eleven_turbo_v2_5、eleven_v3;输出默认mp3_44100_128 | voice_settings(stability、similarity boost、speed) |
gemini | Kore(默认),另有Zephyr、Puck、Charon、Fenrir、Leda等 30 个音色 | model:gemini-2.5-flash-preview-tts(默认)、gemini-2.5-pro-preview-tts、gemini-3.1-flash-tts-preview | instructions自然语言风格指令 |
xai | eve(默认、充满活力)、ara(温暖)、rex(自信)、sal(流畅)、leo(权威) | language 默认'en',支持'auto'自动检测与 20+ 语言;输出mp3/wav/pcm/mulaw/alaw | 内联标签[pause]、[laugh]、<whisper>text</whisper> |
speechify | geffen_32(默认)、dominic_32、harper_32、hugh_32、imogen_32 | model:simba-3.2(默认)、simba-english、simba-multilingual;输出mp3/wav/ogg/aac | — |
调用返回一个Promise<HTMLAudioElement>,其src指向包含合成音频的 blob 或远程 URL。下面是一个综合场景:先在页面上枚举某个 provider 的音色,再让用户选中并播放。核心是把voice.id塞回options.voice:
<html> <body> <script src="https://js.puter.com/v2/"></script> <button id="play">播放所选音色</button> <select id="voiceSelect"></select> <script> const text = '你好,欢迎体验 Puter 的文本转语音能力!'; (async () => { // 1) 拉取 TTSVoice 数组 const voices = await puter.ai.txt2speech.listVoices({ provider: 'gemini' }); const select = document.getElementById('voiceSelect'); // 2) 用 name 做展示,用 id 做回传 for (const voice of voices) { const opt = document.createElement('option'); opt.value = voice.id; opt.textContent = `${voice.name}${voice.language ? ' (' + voice.language.code + ')' : ''}`; select.appendChild(opt); } })(); document.getElementById('play').addEventListener('click', async () => { const voiceId = document.getElementById('voiceSelect').value; const audio = await puter.ai.txt2speech(text, { provider: 'gemini', voice: voiceId, model: 'gemini-2.5-flash-preview-tts', instructions: 'Speak in a friendly, upbeat tone.' }); audio.play(); }); </script> </body> </html>值得注意:txt2speech()中provider 列表比 listVoices 多出'speechify',因此使用 Speechify 音色前不妨先listVoices({ provider: 'speechify' })确认最新 voice id。另外合成文本长度须小于 3000 字符;test_mode/testMode置为true时接口返回示例音频而不消耗配额,适合先试听某个voice.id再决定正式使用。
与相关对象的联系
- TTSEngine:与 TTSVoice 并列的另一个对象类型,描述"可用引擎/模型"及可选价格元数据
pricing_per_million_chars,由puter.ai.txt2speech.listEngines()返回。后端 types.ts 中ITTSEngine与ITTSVoice同为puter-ttsdriver 的公共结构。TTSVoice 的supported_engines/supported_models字段正是"该音色 ↔ 引擎/模型"的关联线索。 - 同一对象族:语音合成链路中还涉及
Speech2TxtResult(语音转文字结果对象,见 Objects 目录 下的 speech2txtresult.md),以及配套的 speech2txt()、speech2speech() 接口。
最佳实践小结
- 以
id为准、name为辅:展示层用name,请求层回传id,不要把两者混用。 - 可选字段一律判空:
language、description、category、labels、supported_models、supported_engines都可能缺失,跨 provider 迭代时务必先判断再访问(如voice.language ? voice.language.code : null)。 - 多供应商场景用
provider分组:provider: 'all'返回混合数组,按voice.provider归组可避免同名音色混淆。 - 用
supported_engines做联动过滤:展示 Polly 音色时,仅当数组含"neural"才允许用户选 neural 引擎,减少运行时bad_request。 - 先试听再合成:用
test_mode获取样本音频验证 voice/engine 组合,正式调用时不带该参数。 - 供应商别名统一由后端解析:即使 SDK 版本较旧,
'eleven'、'google'、'grok'等别名也能在后端被正确归一化(见 providerAliases.ts 的normalizeTTSProvider()),因此客户端不必重复维护别名映射。
通过本文介绍的对象字段与调用链路,你已经可以把"枚举音色 → 展示选择 → 语音合成 → 播放"整条 TTS 流程接入 Puter 应用;如需在自托管环境中进一步调试,可从 src/backend/drivers/ai-tts 的驱动与 provider 实现入手追踪完整数据流。
【免费下载链接】puter🌐 The Internet Computer! Free, Open-Source, and Self-Hostable.项目地址: https://gitcode.com/GitHub_Trending/pu/puter
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考