BREEZE TTS / DEVELOPER GUIDE流式语音 API

让你的 Agent
开口说话。

发送文字与音色描述,持续接收语音数据。面向服务端、桌面客户端与 Agent 的中文 / 英文语音合成接口。

POSThttps://tts.heang.top/v1/audio/speech
24 kHz单声道 PCM
流式返回边生成 · 边播放
Token 认证Cloudflare Access
01 / START

快速接入

先向服务提供方领取 Client ID 和 Client Secret,将它们放入运行环境变量,再执行以下请求。文档公开不代表 API 可匿名使用。

下面是 Bash / zsh 语法;Windows 可使用 WSL,或直接运行下方 Python 示例并配置环境变量。

export TTS_CLIENT_ID="由服务提供方单独提供"
export TTS_CLIENT_SECRET="由服务提供方单独提供"

curl --fail-with-body --no-buffer https://tts.heang.top/v1/audio/speech \
  -H "CF-Access-Client-Id: $TTS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $TTS_CLIENT_SECRET" \
  -H "User-Agent: BreezeAgent/1.0" \
  -H "Content-Type: application/json" \
  -d '{"input":"你好,欢迎来到我的直播间。","instructions":"温柔自然的成年女性,用普通话亲切地说话。","response_format":"pcm","cfg_scale":1,"max_new_tokens":500}' \
  --output speech.pcm

# 可选:使用 ffplay 边接收边播放时,将 --output speech.pcm 替换为:
# --output - | ffplay -nodisp -autoexit -f s16le -ar 24000 -ac 1 -i -

下载 Python 示例 ↗下载 Node.js 示例 ↗给 Agent 的纯文本说明 ↗

02 / AUTH

每次请求都携带认证头

请求头填写内容
CF-Access-Client-Id服务提供方分配的 Client ID
CF-Access-Client-Secret对应的 Client Secret
User-AgentBreezeAgent/1.0;避免默认 Python 标识被站点检查拒绝
Content-Type合成请求使用 application/json
密钥只放在服务端或可信客户端。不要放进公开网页 JavaScript、Git 仓库或分享链接。浏览器产品应由自己的后端转发;当前接口不提供跨域浏览器直连。

检查可用性

curl --fail-with-body https://tts.heang.top/health \
  -H "User-Agent: BreezeAgent/1.0" \
  -H "CF-Access-Client-Id: $TTS_CLIENT_ID" \
  -H "CF-Access-Client-Secret: $TTS_CLIENT_SECRET"

# 正常响应包含:{"status":"ok","sample_rate":24000}
03 / REQUEST

用文字描述声音

请求体使用 UTF-8 JSON。input 是必填字段。当前没有预注册的音色 ID;请省略 voice,通过 instructions 设计声音。

字段类型说明
inputstring · 必填要朗读的文字;建议从短句开始。
instructionsstring音色和表达描述,例如“成年女性,中低音,温柔自然,用普通话聊天”。描述语言尽量与正文一致。
response_formatstring实时建议显式指定 pcm;也支持 wav、mp3。
cfg_scalenumber建议 1,音质和速度较均衡;提高可强化指令,但可能更刺耳。
seedinteger随机种子;相同文本与配置下便于复现,不保证跨文本保持完全相同的音色。
max_new_tokensinteger生成帧数上限,示例为 500;每帧约 80 ms,上限不是固定输出时长。
temperaturenumber可选采样温度,模型默认约 0.9,先保持默认。
split_charsinteger可选长文本分段预算,当前默认 200;中文按加权预算计数。
modelstring兼容字段,当前忽略;不用填写。

接口兼容 OpenAI Speech 风格的部分字段,并非所有 OpenAI 参数或内置声音均可用;不要传入 alloy、nova 等默认音色名称。

04 / STREAM

收到一块,播放一块

文字→语音合成→PCM 数据块→播放队列
一次公网测试:6.48 秒语音约 5.63 秒生成,首个音频块约 1.88 秒。数据包含当时的网络链路,仅供参考,不是延迟承诺。
05 / EXAMPLES

复制代码,接进你的项目

Python · 流式接收并保存 WAV

# Python 3.10+,仅使用标准库。密钥先设置到环境变量。
import json, os, urllib.request, wave

request = urllib.request.Request(
    "https://tts.heang.top/v1/audio/speech",
    data=json.dumps({
        "input": "你好,这是流式语音合成测试。",
        "instructions": "自然、清晰、温暖的成年女声。",
        "response_format": "pcm",
        "cfg_scale": 1,
        "max_new_tokens": 500,
    }).encode("utf-8"),
    headers={
        "Content-Type": "application/json",
        "User-Agent": "BreezeAgent/1.0",
        "CF-Access-Client-Id": os.environ["TTS_CLIENT_ID"],
        "CF-Access-Client-Secret": os.environ["TTS_CLIENT_SECRET"],
    },
)
with urllib.request.urlopen(request, timeout=180) as response:
    if "audio" not in response.headers.get("Content-Type", ""):
        raise RuntimeError("服务未返回音频,请检查认证和响应内容")
    with wave.open("speech.wav", "wb") as audio:
        audio.setnchannels(1)
        audio.setsampwidth(2)
        audio.setframerate(24000)
        while chunk := response.read1(4096):
            # 实时播放:将 chunk 交给 PCM 播放队列,勿等待整个请求结束。
            audio.writeframesraw(chunk)
# wave 自动写入正确的文件长度;不要把 .pcm 直接改名为 .wav。

Node.js · 流式保存 PCM

// Node.js 22+;保存为 speech.mjs 后执行 node speech.mjs。
import { createWriteStream } from "node:fs";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";

const response = await fetch("https://tts.heang.top/v1/audio/speech", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "User-Agent": "BreezeAgent/1.0",
    "CF-Access-Client-Id": process.env.TTS_CLIENT_ID,
    "CF-Access-Client-Secret": process.env.TTS_CLIENT_SECRET,
  },
  body: JSON.stringify({
    input: "你好,我正在实时生成语音。",
    instructions: "温暖、自然的成年男声。",
    response_format: "pcm", cfg_scale: 1, max_new_tokens: 500,
  }),
  signal: AbortSignal.timeout(180000),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
if (!response.headers.get("content-type")?.includes("audio")) {
  throw new Error("Expected audio response");
}
await pipeline(Readable.fromWeb(response.body), createWriteStream("speech.pcm"));
// 实时应用可逐块读取 response.body,并交给播放器。
06 / ERRORS

错误与重试

状态处理方式
400检查字段、JSON 格式和文本内容;不要对同一错误请求盲目重试。
403 / 登录页面检查两项认证头、Token 有效期、User-Agent。认证响应可能是 HTML 或纯文本。
404仅开放 /health 和 /v1/audio/speech;根目录不提供网页。
413请求体超过 1 MiB;拆小请求。
429合成忙碌。等待约 5 秒,并加入随机抖动后重试;不要同时提交多个任务。
5xx / 超时检查健康接口,退避重试;持续失败请联系服务提供方。

读取音频前先验证 HTTP 状态和 Content-Type。流中断后应停止或清空对应播放任务;重新请求可能再次生成整段音频。

07 / NOTES

接入前需要知道

查看上游模型许可证 ↗