剧本会告诉配音演员每句台词该怎么说,是压低声音耳语,还是带着哭腔。语音模型如果用同一种平稳的语气读完每一句,这些标注就只能留在纸面上,表演只能靠进录音棚来完成。
今天,我们发布 Paxa TTS Flash v2。在实验室内部,它叫 Pixie,控制台语音工具里的模型名旁边也标着这个昵称。Pixie 会演绎剧本里的这些标注。写在方括号里的指令可以用中文、英语或泰语书写,它决定后面的文字以什么方式说出,同一句话里,演绎方式还可以变换好几次。
Paxa TTS Flash v2 现已在 API 的所有语音路由和控制台中上线,价格为每百万字符 $10。这与 Paxa TTS Flash 的费率相同,发往 Paxa TTS Flash 的请求也会照常工作。
与 Paxa TTS Flash 相比有哪些变化#
| Paxa TTS Flash | Paxa TTS Flash v2 | |
|---|---|---|
| 语气演绎 | 2 个实验音色支持 [happy] 这类情感标签 | 所有音色都支持用任意文字书写的指令 |
| 笑声、叹气等声音 | 无 | [laughs] 等声音,写在哪里就在哪里发出 |
| 迟疑声 | 无 | [um] 和 [hmm],按词读出来 |
| 强调 | 无 | <emph> 和 <whisper> 标记的片段 |
| 语言 | 每个音色只为中文、英语、泰语中的一种语言打造 | 每个音色都能说这三种语言 |
| 音色数量 | 34 | 50 |
| mp3 | 24 kHz, 64 kbps | 44.1 kHz, 128 kbps |
| opus | 48 kHz, 48 kbps | 48 kHz, 64 kbps |
| 每 1,000 字符价格 | 10 积分 | 10 积分 |
同一句话,两个模型#
Foi Thong 把同一句话读了两遍。在 Paxa TTS Flash 上,请求里只有文本。在 Paxa TTS Flash v2 上,请求带有两条指令:前半句之前是 [whispering],后半句之前是 [ecstatic]。
-
Paxa TTS Flash0:02 - [whispering] [ecstatic] Paxa TTS Flash v20:03
用自然语言写指令#
指令就是写在方括号里的任意文字,例如 [sad]、[speaking slowly, close to the microphone] 或 [เสียงสดใส]。它可以是一个词,也可以是对整段朗读的描述,比如 [product advertisement, punchy and upbeat] 或 [ผู้ประกาศข่าว น้ำเสียงเป็นทางการ]。指令本身不会被读出来。
一条指令会一直生效,直到下一条出现。第一条指令之前的文本保持音色本身的演绎方式,[neutral] 可以回到这种方式。大小写、多余的空格和全角括号都不影响结果:[Sad]、[ sad ] 和 [sad] 是同一条指令。
下面第一行在一句话里变换了四次演绎方式。Foi Thong 先是耳语,接着以 2 的权重变得兴奋,然后哭了出来,最后以笑声收尾。
- [whispering] [excited:2] [crying] [laughs]Foi Thong0:07
- [whispering] Mocha0:02
- [shouting urgently] Mocha0:01
- [เสียงสั่น]
[กลั้นน้ำตา] Sanae Chan0:04
权重与混合#
冒号后面的权重决定一条指令或一个声音的作用强度,可以写成数字或百分比:[sad:0.5]、[sad:50%]、[laughs:0.3]。加号用来混合多条指令,每条都有自己的权重,例如 [happy:0.7+sad:0.3]。
声音、迟疑和强调#
声音会在写下的位置发出:[sighs]、[laughs]、[chuckles]、[exhales sharply]、[gasps]、[inhales deeply]、[giggles]、[sobs]、[yawns] 和 [clears throat],还有 [inhales] 和 [scoffs] 这样的写法。
[um] 和 [hmm] 表示迟疑。它们会按括号里的词读出来,[เอ่อ] 这样的泰语写法也一样。
<emph> 把句子的重音放在其中的词上,<whisper> 则把其中的词用耳语说出。结束标记会让这一行回到标记之前的演绎方式。强调也可以写成方括号形式:[emphasize] 或 [เน้นเสียง]。
- [firm] <emph>
</emph>Cookie0:01
它不会做的事#
模型无法演绎的标签会在扣费之前被拒绝,返回 400 tag_invalid。只有标签、没有可读文字的文本会返回 422 unspeakable_text,同样发生在扣费之前。
| 请求内容 | 示例 |
|---|---|
| 口音 | [北京口音]、[british accent]、[สำเนียงอีสาน] |
| 换一种声音 | [robotic]、[old man voice]、[เสียงเด็ก] |
| 唱歌 | [唱歌]、[singing]、[ร้องเพลง] |
| 音效 | [door slams]、[applause] |
| 指定语言 | [中文]、[in thai]、[english] |
| 列表之外的声音 | [sniffs]、[gulps]、[coughs] 和 [sneezes] |
指令指南列出了所有声音、写法和会被拒绝的标签。
50 个音色,每个都会三种语言#
Paxa TTS Flash v2 共有 50 个音色:其中 26 个沿用 Paxa TTS Flash 的音色,id 保持不变,另有 24 个是新音色。在 Paxa TTS Flash 上,每个音色只为一种语言打造。在 Paxa TTS Flash v2 上,每个音色都能说中文、英语和泰语,同一个音色就能在三个市场介绍同一款产品。
Pixie 能用同一个音色朗读混合多种语言的文本。每个词都按其文字所属的语言来读。一句提到英文产品名的泰语,或一条带航班号的中文通知,都可以用一个请求发出。可选的 language 字段决定代码、数字和符号的读法,例如设为 "th" 时,AB2039 会用泰语的字母名称来读。
- [广告配音,热情洋溢]
Khanom Krok0:03 - [product advertisement, punchy and upbeat] Khanom Krok0:03
- [โฆษณาสินค้า น้ำเสียงกระฉับกระเฉง]
Khanom Krok0:03 - [apologetic, sincere] Cookie0:07
- [亲切的客服语气]
Cookie0:07
24 个新音色#
影片中的场景#
一通客服电话#
来电者因为等待太久而恼火,客服道歉并为他改签了航班,来电者又请客服用中文把消息告诉他的妻子。Cookie 先用英语回答,再用中文回答,始终是同一个音色。
- [frustrated, tense] Espresso0:04
- [apologetic, sincere] Cookie0:07
- [relieved] Espresso0:04
- [亲切的客服语气]
Cookie0:07
一部广播剧#
两个窃贼从压低声音的倒计时开始,接着陷入慌乱,大喊着逃跑,最后上气不接下气地松了口气。每句台词各带一条指令,最后一句以笑声收尾。
- [whispering] Mocha0:02
- [panicked, fast] Latte0:01
- [shouting urgently] Mocha0:01
- [out of breath, relieved] [laughs]Latte0:03
一部泰语有声小说#
一场重逢,用泰语说出,也用泰语写指令。台词带着颤抖,强忍泪水,最后含泪笑出来。
- [เสียงสั่น]
[กลั้นน้ำตา] Sanae Chan0:04 - [อบอุ่น]
Massaman0:02 - [หัวเราะทั้งน้ำตา]
Sanae Chan0:04
晚间新闻#
- [ผู้ประกาศข่าว น้ำเสียงเป็นทางการ]
Thong Ek0:04
词级时间戳#
把 timestamps 设为 "word",响应中的每个词都会带上以秒为单位的开始和结束时间,可用于字幕,也可以像这个页面一样,让词随着朗读逐个点亮。"sentence" 和 "utterance" 给出更长的时间区间。时间区间只覆盖读出来的文本,标签不占用时间区间。
非流式的带时间戳请求返回 JSON,其中音频以 base64 编码,与 timing.spans 并列。流式请求则每个音频块返回一行 JSON,每行带着该块的音频和其中完成的时间区间。带时间戳的请求按语音费率的 125%计费,两种返回格式详见时间戳指南。
速度与流式输出#
在我们从新加坡进行的实测中,请求的首段音频最快 90 毫秒就能到达。把 stream 设为 true 后,其余部分还在合成时,请求的音频就已经开始播放。
实时 WebSocket 在语言模型还在写文本时就开始朗读,指令在这里同样有效。WebSocket 开始合成时仍未闭合的标签,会等到括号闭合后再合成;每一段都以上一段结束时的指令开头。来电者插话时,cancel 帧会停止回复。“实时语音合成”页面逐帧演示了一次完整的会话。
价格不变#
Paxa TTS Flash v2 每 1,000 字符收费 10 积分,相当于每百万字符 $10,与 Paxa TTS Flash 的费率相同。标签按书写它所用的字符计费,括号也计算在内。在两个模型上,带时间戳的请求,以及请求了时间戳的实时连接,都按该费率的 125%计费。
| 发送的台词 | 字符数 | 积分 |
|---|---|---|
| I can't believe it. We actually did it! | 39 | 0.39 |
| [whispering] I can't believe it. [ecstatic] We actually did it! | 63 | 0.63 |
| [whispering] I was not going to tell anyone, [excited:2] but we got the house, [crying] after three years of saving. [laughs] | 125 | 1.25 |
| [โฆษณาสินค้า น้ำเสียงกระฉับกระเฉง] ซีซันใหม่ สีใหม่ วางขายวันศุกร์นี้ | 69 | 0.69 |
| [广告配音,热情洋溢] 新一季,新色彩,本周五上市。 | 26 | 0.26 |
新账户的 100 免费积分可以合成 10,000 个字符,约合 16 分钟的泰语语音。
开始使用#
POST /v1/tts可返回完整音频或流式音频。把model设为paxa-tts-flash-v2。- 兼容 OpenAI 的
POST /v1/audio/speech按同样的规则读取input中的标签。指向 Paxa API 的 OpenAI SDK 会把指令按原样发送。 - 实时 WebSocket
/v1/tts/live在start帧中指定模型。 - 在控制台中,语音工具列出了 Paxa TTS Flash v2,名称旁标有 Pixie。
curl -X POST https://api.paxalabs.com/v1/tts \
-H "Authorization: Bearer $PAXA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "[warm, unhurried] ยินดีต้อนรับกลับมาครับ [chuckles] วันนี้มีข่าวดี [เอ่อ] <whisper>แต่ขอเก็บเป็นความลับไว้ก่อนนะครับ</whisper>",
"voice": "khanomkrok",
"model": "paxa-tts-flash-v2"
}' \
--output speech.mp3import { writeFile } from "node:fs/promises";
const response = await fetch("https://api.paxalabs.com/v1/tts", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAXA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
text: "[warm, unhurried] ยินดีต้อนรับกลับมาครับ [chuckles] วันนี้มีข่าวดี [เอ่อ] <whisper>แต่ขอเก็บเป็นความลับไว้ก่อนนะครับ</whisper>",
voice: "khanomkrok",
model: "paxa-tts-flash-v2",
}),
});
if (!response.ok) throw new Error(`TTS failed: ${response.status}`);
await writeFile("speech.mp3", Buffer.from(await response.arrayBuffer()));import os
import requests
response = requests.post(
"https://api.paxalabs.com/v1/tts",
headers={"Authorization": f"Bearer {os.environ['PAXA_API_KEY']}"},
json={"text": "[warm, unhurried] ยินดีต้อนรับกลับมาครับ [chuckles] วันนี้มีข่าวดี [เอ่อ] <whisper>แต่ขอเก็บเป็นความลับไว้ก่อนนะครับ</whisper>", "voice": "khanomkrok", "model": "paxa-tts-flash-v2"},
)
response.raise_for_status()
with open("speech.mp3", "wb") as f:
f.write(response.content)单个请求最多 5,000 个字符,返回 mp3、opus、wav 和 pcm 格式,其中 wav 和 pcm 为 24 kHz。speed 的取值范围是 0.5 到 1.5,不影响计费。
从 Paxa TTS Flash 迁移#
- Paxa TTS Flash 仍以
paxa-tts-flash-v1提供,原有请求照常工作。 - 迁移请求时,把
model改为paxa-tts-flash-v2。两个模型共有的 26 个音色保留原来的 id。 - Pad Thai、Yoyo、Som Tam、Larb、Khao Soi、Roti、Donut 和 Toast 继续留在 Paxa TTS Flash 上。
- 在 Paxa TTS Flash 上,只有实验音色能读
[happy]这类情感标签。在 Paxa TTS Flash v2 上,每个音色都能读标签,[happy]和其他指令没有区别。
常见问题#
Paxa TTS Flash v2 是预览版吗?#
不是。Paxa TTS Flash v2 已全面开放,API 和控制台均可使用。
Paxa TTS Flash v2 比 Paxa TTS Flash 更贵吗?#
不会。两者都是每 1,000 字符 10 积分。
请求里要用 Pixie 这个名字吗?#
不用。Pixie 是模型的昵称,请求中用它的 id paxa-tts-flash-v2 来指定。
指令可以写什么?#
任何演绎方式都可以,用中文、英语或泰语书写,例如 [tired, exhausted] 或 [ผู้ประกาศข่าว น้ำเสียงเป็นทางการ]。要求口音、换一种声音、唱歌、音效或指定语言的指令,会返回 tag_invalid。
可以克隆声音吗?#
不可以。Paxa TTS Flash v2 提供 50 个目录音色,不接受参考音频。新音色可以通过音色设计获得,根据一段文字描述生成。