# 语音合成
> 用预置或克隆音色，把文本合成为语音。

用预置或克隆音色，把文本合成为语音。

## Agent 主路径

通过 Universal Skill 使用 MCP 工具 `beatra.speech.synthesize`。该工具计费，
返回异步任务。

1. 先选音色：`beatra.voices.list` 返回预置与克隆音色的 `voice_id` 和试听链接。
2. 当模型、语言、格式或价格有影响时，用 `capability: "text_to_speech"` 调用
   `beatra.models.list`；否则使用 `model: "auto"` 或省略 `model`。
3. 创建一个不透明的 `client_request_id`，把最终参数提交一次。
4. 用 `beatra.tasks.get` 轮询返回的任务直到终态。

## AI 指南

AI integration guide: https://docs.beatra.ai/llms/audio-text-to-speech.md

## 工具参数

```json
{
  "voice": "voice_01JX...",
  "input": "Welcome to Beatra — make your first call in three minutes.",
  "language": "en-US",
  "format": "mp3",
  "speed": 1.0,
  "client_request_id": "tts-opaque-1"
}
```

`voice` 接受[音色管理](https://docs.beatra.ai/zh/docs/capabilities/speech/voices)返回的任何
`voice_id`，预置或[克隆音色](https://docs.beatra.ai/zh/docs/capabilities/speech/voice-clone)都可以。每个音色属于一个引擎（见它的 `compatible_models`）；
有的模型上，音色跟随哪些控制项因音色而异，音色的 `persona` 会写明。
本能力不含流式与实时对话。

## 规范标记

`input` 只能使用下面这一组标记。标记计入 50,000 字符上限，也计入加权字符计费。
词表与各模型生效值域在 `beatra.models.list` 模型卡的 `constraints.script_markup`。
同一套标记适用于每个语音模型；模型做不到的标记会被去掉或忽略，并返回警告，不会做近似替代。
下文的「模型特化参数」是 `model_options` 字段，不属于标记语言。

- `{pause <seconds>}` — 停顿，最多两位小数，取值在模型卡的 `script_markup.pause.range` 之内（有的模型最长 99.99 秒，有的最长 10 秒；超出会在扣费前被拒绝）。停顿位于整段开头或结尾，或两个停顿之间没有可朗读内容时，请求会被拒绝。
- 声音标签：`{laugh}` 笑声、`{chuckle}` 轻笑、`{sigh}` 叹气、`{breath}` 换气、`{cough}` 咳嗽、`{clear-throat}` 清嗓子、`{gasp}` 倒吸一口气、`{groan}` 痛苦或不满的哼声、`{inhale}` 吸气、`{exhale}` 呼气、`{pant}` 喘气、`{sniff}` 吸鼻子、`{hmm}` 嗯（迟疑、思考）。`script_markup.tags` 列出模型能发出的标签；不支持的模型会把标签去掉（不会读出来），并返回 `markup_degraded` 警告。
- `{pron <word> <reading>}` — 为标记的这一处固定读法：同一个字在别处仍按默认读法，同一请求里也可以给同一个字标不同读音。读法记法为拼音：音节直接相连、每音节以声调数字 1–5 结尾、v 代表 ü，中文词每个汉字对应一个音节；其他记法不支持。例：`孩子{pron 长 zhang3}大了，头发也很{pron 长 chang2}。`
- `{sub <word> <spoken text>}` — 把标记处的词按给定文字朗读（最多 100 个字符），字幕仍显示原词；适合品牌名、缩写、英文词和需要逐位读的数字。例：`{sub W3C 万维网联盟}`。
- `{{` — 字面左花括号：写成 `{{` 的位置会朗读一个 `{`，这对花括号本身不会被解析为标记；其后的文本仍按正常规则解析（只需转义左花括号，右花括号原样书写即可）。

每个模型卡的 `constraints.limitations` 用完整句子写明该模型的限制，调用哪个模型就读哪张卡。例如：

- 音量、语速、音高、情绪在一次请求内整段生效，不能只作用于某一句或某个词。如需局部变化，请拆分成多次调用（各自设置参数，会生成多个音频文件），或通过改写文本（省略号、短句、措辞）间接实现。
- 有的模型在长文本（超过 3000 字时走异步路径）上不支持高质量数字归一化，或会去掉 `{pause}`、`{pron}` 标记（返回警告）。需要这些效果时，按段落把文本拆成每次不超过 3000 字的请求。

## 表演指令与上文

下面两个可选字段描述这段语音该怎么读，执行它们的模型会在模型卡的 `controls` 里列出（相关数值见 `constraints.direction_max_characters` 和 `constraints.previous_text_tail_characters`）：

- `direction` — 整段的自然语言表演指令，例如 `像在耳边说悄悄话一样，轻声地说`、`read it like breaking news`。写成一两句话即可：超过 `direction_max_characters` 的指令会被忽略并返回警告。实际效果取决于模型、音色和文本；调音量请用 `volume`。
- `previous_text` — 紧挨在这段之前的文字（对话的上一句、上一段），让分开合成的片段语气连贯。长度不限，模型只用最后 `previous_text_tail_characters` 个字。它不会被读出来。

这两个字段都不计费，也不会让请求失败。不执行某个字段的模型、音色或路径会忽略它并返回 `option_ignored` 警告，音频照常生成。有的模型上这两项还取决于音色（例如角色类音色两项都不跟随），模型卡的 `constraints.limitations` 会写明。`emotion` 同理：模型或音色做不到所请求的情绪时，忽略并返回警告。想在计费前知道某个音色是否跟随这些控制项，把同样的请求发给下面的 validate 接口即可：它免费返回同样的警告。

计费提交前可调用 `beatra.speech.validate` 或 `POST /v1/audio/speech/validate`。
它执行同一套解析和警告检查，返回加权字符数与所需积分；不创建任务、不扣积分、不调用语音引擎，
也不需要 `Idempotency-Key`。

warnings 非空时出现在 202（含幂等重放）、`GET /v1/tasks/{task_id}`、
`beatra.tasks.get` 和客户回调的 `task.warnings`。任务列表、`expand`、账户详情
和 admin 不保证返回。字幕里的 `text_begin` / `text_end` 指向引擎实际朗读的文本
（标记已按该模型编译或去掉），不会映射回提交原文；字幕段与这段文本对得上时，`text` 中 `{pron}`、`{sub}` 的词显示原词，声音标签不出现。计费字数见下文“模型、控制项与成本”一节；
`output.characters` 是引擎实际朗读的字符数，两者可以不同。

## 模型、控制项与成本

通用控制项：`input`（必填，≤50,000 字符）、`voice`（必填）、
`language`、`format`（默认 `mp3`；模型卡的 `constraints.formats` 列出该模型支持的其他格式）、
`speed`（0.5–2.0）、`volume`（在模型卡的 `constraints.volume` 范围内，例如 >0–10 或 0.5–2；超出范围会在扣费前被拒绝）、`pitch`（−1–1，归一化：0 = 音色原始
音高，−1 为该模型允许的最低，1 为最高；微调请用小数如 0.25）、`emotion`、
`sample_rate`、`subtitle_enable`（默认 `false`；设为 `true` 随音频以
`output.subtitles` 返回逐句字幕——免费；模型对所选音色或语种做不了字幕时，
请求会在扣费前被拒绝，`constraints.limitations` 写明这些情况；若运行时字幕文件未能生成，
音频照常交付，只是不带 `output.subtitles`）。`language` 在有的模型上只部分生效，
`constraints.limitations` 写明所选模型怎样处理它。每个控制项只按
所选模型的元数据使用。并非每种格式都支持全部采样率（例如 `opus` 在有的模型上仅支持
8/16/24 kHz，在有的模型上固定输出 48 kHz、不接受 `sample_rate`）：请读模型卡上的 `constraints.sample_rates_by_format`，不要
假设平铺采样率列表对每种格式都成立。

`beatra.models.list` 是可选模型、支持语言、格式、采样率与价格的当前
事实来源。不要把模型目录或价格表复制进 agent 提示词。

语音按请求估价预扣，按加权字符**线性**计费（报价以每 1,000 加权字符为
单位）：每个汉字计 2，其他字符计 1。按提交原文（含标记）计字。引擎按收到的控制文本长度计费的模型上，发给引擎的文本更长时按它计：停顿、读法会变成控制标签，带标签（或正文以 `<speak` 开头）的请求整段按这种形式发送（`&`、`<`、`>` 会转义）。validate 返回准确字数。

## 模型特化参数

`model_options` 承载只有某一类模型执行的参数，按模型类别命名。模型卡的 `controls` 列出该模型执行的键（例如 `model_options.doubao.explicit_dialect`）；其他类别的键不生效，模型可能返回 `option_ignored` 警告说明。

### MiniMax：读音词典

生僻字与多音字可以直接指定读音，不必用同音字改写：

```json
{
  "model_options": {
    "minimax": {
      "pronunciation_dict": {
        "tone": ["湛/(zhan4)", "晞/(xi1)", "厌/(yan1)"]
      }
    }
  }
}
```

格式为 `字/(拼音+声调数字)`，声调数字为 1–4（四声）与 5（轻声）。词典条目对请求里
这个词的每一处都生效；只想改某一处时，用上文的 `{pron}` 标记。仅 MiniMax 系模型支持；
其他模型会忽略该字段。

### 豆包

- `model_options.doubao.explicit_dialect` — `beijing`、`dongbei`、`henan`、`shaanxi`、`shanghai`、`sichuan`、`tianjin`（粤语用 `language: "yue-HK"`）。只有 `languages_supported` 含 `yue` 的音色能说方言，其他音色会在扣费前被拒绝。
- `model_options.doubao.silence_duration` — 在最后一个字后追加的静音，0–30,000 毫秒。
- `model_options.doubao.explicit_language` — 强制朗读语种（`zh-cn`、`en`、`ja`、`es-mx`、`ko`、`de`、`fr` 等）。它是过滤，不是提示：其他语种的句子会被跳过，音色读不了的文本不会出声（任务失败并退款）。`nl`、`no`、`uk`、`fi`、`da`、`cs`、`hu`、`el`、`ro`、`hi`、`es-es` 只对中文（`zh_…`）预置音色有效。长文本只接受 `zh-cn`、`en`、`es-mx`、`id`、`pt-br`。
- `model_options.doubao.latex_parser` — 设为 `"v2"` 会朗读 LaTeX 公式（教育类脚本）。
- `model_options.doubao.pronunciation_dict` — `{"tone": ["北京/(bei3)(jing1)", "omg/oh my god"]}`：最多 5,000 条，对请求里这个词的每一处都生效（读法或替换文本）。只想改某一处时，用 `{pron}`。

文本里用了 `{pause}` 或 `{pron}` 时以标记为准：`latex_parser` 和 `pronunciation_dict` 会被忽略并返回警告，因为引擎不能把它们和标记编译成的形式同时使用。

## 语言

`language` 是可选的供应商中立 BCP-47 标签，如 `zh-CN`、`yue-HK`、`en-US`。
Beatra 用主语言子标签与所选模型匹配；省略该字段则由音色或供应商自行选择。
仅当你明确要求自动语种检测时才传固定值 `auto`（模型卡上的
`constraints.language_auto` 标明该模型是否支持）。不支持的语言会被拒绝，
而不是被悄悄替换。

各模型对 `language` 的用法不同。有的模型把它当作给音色的识别提示；有的模型默认读中文和英文，
`language` 用来为其他语种开启语种识别（例如中文音色读日语时，不传可能读不出来）以及选择方言（`yue`），
这类模型上每个音色只读它 `languages_supported` 里的语种，传入音色不会说的语种会返回 `option_ignored`
警告；结果只会失败的情况在扣费前就拒绝：给不会粤语的音色传粤语，或让音色读它读不了的语种的长文本。
以模型卡的 `constraints.limitations` 为准。

当前语音模型最多覆盖下列 40 种语言，每个模型覆盖其中一部分；`beatra.models.list` 的
`constraints.supported_languages` 是实时的、按模型的事实来源。

| 代码 | 语言 | 代码 | 语言 |
| --- | --- | --- | --- |
| `zh` | 中文 | `tr` | 土耳其语 |
| `yue` | 粤语 | `nl` | 荷兰语 |
| `en` | 英语 | `uk` | 乌克兰语 |
| `es` | 西班牙语 | `th` | 泰语 |
| `fr` | 法语 | `pl` | 波兰语 |
| `ru` | 俄语 | `ro` | 罗马尼亚语 |
| `de` | 德语 | `el` | 希腊语 |
| `pt` | 葡萄牙语 | `cs` | 捷克语 |
| `ar` | 阿拉伯语 | `fi` | 芬兰语 |
| `it` | 意大利语 | `hi` | 印地语 |
| `ja` | 日语 | `bg` | 保加利亚语 |
| `ko` | 韩语 | `da` | 丹麦语 |
| `id` | 印尼语 | `he` | 希伯来语 |
| `vi` | 越南语 | `ms` | 马来语 |
| `fa` | 波斯语 | `sk` | 斯洛伐克语 |
| `sv` | 瑞典语 | `hr` | 克罗地亚语 |
| `fil` | 菲律宾语 | `hu` | 匈牙利语 |
| `no` | 挪威语 | `sl` | 斯洛文尼亚语 |
| `ca` | 加泰罗尼亚语 | `nn` | 新挪威语 |
| `ta` | 泰米尔语 | `af` | 南非荷兰语 |

## 任务状态与恢复

`queued` 与 `running` 不是失败。持续轮询同一个 `task_id`；不要因为任务还在
运行就提交替代请求。创建响应丢失时，用同一个 `client_request_id` 原样重试；
任何输入变化都要换新 ID。失败任务自动退款。只从终态任务响应返回音频产物、
实际模型与扣费；产物 URL 是 CDN 地址——请尽快转存到自己的存储。

## 通过 REST 调用

直连协议集成可使用 `POST /v1/audio/speech` 与共享任务端点，参数见生成的
[接口定义](https://docs.beatra.ai/zh/docs/api-reference/operations/audio/text_to_speech_v1_audio_speech_post)。
推荐通过 Skill + MCP 接入；REST 适合自定义应用直连。
