跳转到文档正文
浏览文档

VOICE API · 中文开发文档

开始使用 Voice API

从创建密钥开始,添加声音、生成音频,再查看用量和费用。 这份指南带你完成一次完整调用。

1. 创建密钥

登录控制台并开通工作区,在“API 密钥”中点击“创建 API 密钥”。只需填写名称,默认永不过期;可选 7、30 或 90 天。完整密钥仅展示一次。

代码
export CASTREADER_API_BASE="https://voice.castreader.cn/v1"
export CASTREADER_API_KEY="YOUR_API_KEY"
# 仅在服务端保存密钥,不要提交到 Git 或放入浏览器前端。

身份验证与区域

在每次请求中发送 Authorization: Bearer YOUR_API_KEY。语音生成需要 speech:generate,声音读取需要 voices:read,账单用量查询需要 usage:read。把密钥放在服务端环境变量,不要放进公开仓库或移动端安装包。

页面语言不决定数据区域。任务、音色与密钥应始终使用所属区域的 API 地址;区域不可用时不得改用另一区域重试。

2. 添加声音

我的声音选择“自己录制”“邀请朋友”或“上传音频”。准备单人、无背景音乐的清晰录音,建议 20–30 秒,最大 4 MB。上传他人声音时提供明确授权;邀请朋友时,由对方在录音页面确认授权。

等待状态变为“可用”,试听后复制声音 ID。删除声音会阻止新的生成和旧结果下载。声音准备过程中出现失败时,请查看提示再添加新录音。

代码
curl "$CASTREADER_API_BASE/voices" \
  -H "Authorization: Bearer $CASTREADER_API_KEY" \
  -H 'Idempotency-Key: my-first-voice-001' \
  -F 'name=我的声音' -F 'language=zh' \
  -F 'reference_audio=@reference.wav;type=audio/wav' \
  -F 'consent_type=self' -F 'subject_name=Your name' \
  -F 'consent_confirmed=true' -F 'terms_version=voice-consent-v1' \
  --fail-with-body

声音授权与数据处理规则 →

3. 生成第一段音频

将下方的 voice_YOUR_ID 替换为自己的声音 ID。中国区示例直接生成中文音频,无需时间戳。当前可用的合成语言以 GET /v1/models 为准。

代码
curl "$CASTREADER_API_BASE/audio/speech" \
  -H "Authorization: Bearer $CASTREADER_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: my-first-speech-001' \
  --data '{
  "model": "clone-v1",
  "voice_id": "voice_YOUR_ID",
  "text": "欢迎使用 CastReader,让文字拥有熟悉的声音。",
  "language": "zh",
  "output_format": "mp3"
}' \
  --fail-with-body --dump-header speech.headers --output speech.mp3

成功响应为二进制音频。先检查 HTTP 200,再播放文件;失败响应是 JSON。响应头中可取得请求 ID 和可选时间戳地址。

资源繁忙时:使用排队任务

提交后保存任务 ID,按 Retry-After 建议间隔查询。关闭浏览器不会丢失任务。等待不收费;已开始执行的任务需确认停止后才能释放预留金额。

代码
curl "$CASTREADER_API_BASE/jobs" \
  -H "Authorization: Bearer $CASTREADER_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: my-first-job-001' \
  --fail-with-body --data '{
  "model": "clone-v1",
  "voice_id": "voice_YOUR_ID",
  "text": "欢迎使用 CastReader,让文字拥有熟悉的声音。",
  "language": "zh",
  "output_format": "mp3"
}'

# 保存返回的 id;后续请求始终使用相同区域的地址。
export JOB_ID="job_RETURNED_ID"
curl "$CASTREADER_API_BASE/jobs/$JOB_ID" \
  -H "Authorization: Bearer $CASTREADER_API_KEY" --fail-with-body

# 状态为 succeeded 后,从 chunks 中取得 requestId。
export REQUEST_ID="req_RETURNED_ID"
curl "$CASTREADER_API_BASE/requests/$REQUEST_ID/audio" \
  -H "Authorization: Bearer $CASTREADER_API_KEY" \
  --fail-with-body --output speech.mp3

状态包括 queuedblockedrunningsucceededfailedcancelledexpired。非成功的终态不能当作音频结果。取消使用 DELETE /v1/jobs/{job_id}

4. 核对计量与扣费

在控制台的「API 账单」中使用支付宝充值。最低支付 ¥7,获得 $1 API 额度;付款后自动确认到账。余额不设有效期,优先使用免费字符,随后按实际成功生成的字符扣费。

用量按请求 ID 对照字符数、免费字符抵扣、实际扣费和最终状态。金额以账本为准,界面四舍五入不改变实际扣费。

代码
curl "$CASTREADER_API_BASE/requests/$REQUEST_ID" \
  -H "Authorization: Bearer $CASTREADER_API_KEY" --fail-with-body

curl "$CASTREADER_API_BASE/usage" \
  -H "Authorization: Bearer $CASTREADER_API_KEY" --fail-with-body

价格为每百万规范化 Unicode 字符 12 美元。相同内容和相同幂等键只结算一次,下载保留结果不产生新费用。查看完整规则 →

错误与安全重试

状态码处理建议
401检查密钥是否有效、过期或已撤销。
403核对角色、权限、声音授权及区域归属。
402检查工作区额度和余额。
409查询原请求;不要在执行结果未知时创建新任务。
410结果或任务已过期,原请求不会自动重新生成。
422检查参数、语言、字符数或录音格式。
429 / 503按 Retry-After 等待,在同一区域重试同一请求或使用排队任务。

网络断开不代表生成失败。优先查询保存的任务 ID 或请求 ID。同一次提交使用同一个 Idempotency-Key;修改文字、声音、格式或时间戳选项时,才为新的任务生成新键。

HTTP 接口参考

接口用途
GET /v1/models模型和语言限制
GET /v1/voices列出声音
POST /v1/voices注册授权声音
DELETE /v1/voices/{voice_id}删除声音
POST /v1/audio/speech生成完整音频
POST /v1/jobs创建排队任务
GET /v1/jobs/{job_id}查询任务
DELETE /v1/jobs/{job_id}取消任务
GET /v1/requests/{request_id}读取请求与用量
GET /v1/requests/{request_id}/audio下载音频
GET /v1/requests/{request_id}/timestamps读取 v3 时间戳
GET /v1/usage查询工作区用量

下载 OpenAPI 3.1 规范 → · v3 时间戳 →

Node.js 与 Python

使用任意支持 HTTPS 的服务端客户端。初始化时显式设置本区基础地址,不使用另一区域作备用地址。对请求设置超时,保存任务 ID、幂等键及错误码,再查询结果。

代码
// Node.js:先提交,保存 id,再轮询。
const response = await fetch('https://voice.castreader.cn/v1/jobs', {
  method: 'POST',
  redirect: 'error',
  headers: {
    Authorization: 'Bearer ' + process.env.CASTREADER_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'node-first-job-001',
  },
  body: JSON.stringify({
  "model": "clone-v1",
  "voice_id": "voice_YOUR_ID",
  "text": "欢迎使用 CastReader,让文字拥有熟悉的声音。",
  "language": "zh",
  "output_format": "mp3"
}),
  signal: AbortSignal.timeout(30000),
});
if (!response.ok) throw new Error(await response.text());
const job = await response.json();
console.log(job.id);
代码
import json, os
from urllib.request import Request, urlopen

payload = {"model":"clone-v1","voice_id":"voice_YOUR_ID","text":"Hello from CastReader.","language":"en","output_format":"mp3"}
request = Request('https://voice.castreader.cn/v1/jobs',
    data=json.dumps(payload).encode(), headers={
        'Authorization': 'Bearer ' + os.environ['CASTREADER_API_KEY'],
        'Content-Type': 'application/json',
        'Idempotency-Key': 'python-first-job-001',
    })
with urlopen(request, timeout=30) as response:
    job = json.load(response)
print(job['id'])

当前未开放的能力

公开预览版不提供实时会话、流式输出、长篇生成、自动充值或延迟 SLA。控制台成员管理、密钥创建与付款需要登录会话,不通过公开 Bearer 接口管理。请以当前能力页及实际返回为准。