Skip to Content
模型 API 文档按量API调用指南音频生成文生语音 API

文生语音 API

文生语音 API 基于 IndexTTS 2.5,提供异步语音生成、任务管理、参考音频上传、自定义音色管理和积分查询能力。支持中文、英文、日文、西班牙语和阿拉伯语,可调整语速、情绪和指定词语的读音。

创建任务后,使用任务 ID 轮询生成状态,成功后通过结果 URL 下载 WAV 音频。

接口总览

共包含 12 个接口,其中积分套餐查询与 MiniMax H3 共用:

功能方法路径
创建文生语音任务POST/audio/v1/speech/jobs
查询单个任务GET/audio/v1/speech/jobs/{task_id}
查询任务列表GET/audio/v1/speech/jobs
取消任务POST/audio/v1/speech/jobs/{task_id}/cancel
删除任务DELETE/audio/v1/speech/jobs/{task_id}
查询音色列表GET/audio/v1/voices
获取参考音频上传地址POST/audio/v1/upload_urls
登记参考音频素材POST/audio/v1/assets
创建自定义音色POST/audio/v1/voices
删除自定义音色DELETE/audio/v1/voices/{voice_id}
查询语音计价与积分余额GET/audio/v1/pricing
查询积分套餐包GET/minimax/v2/query/point_packages

接入信息

请求地址

https://cp.compshare.cn

身份认证

使用与 MiniMax H3 相同的模型 API Key,以 sk-ml- 开头:

  1. 进入优云智算视频工作台 
  2. 点击左侧工具栏中的 API 按钮,打开 API 密钥窗口。
  3. 创建或复制模型 API Key,并在调用时携带以下请求头:
Authorization: Bearer <YOUR_API_KEY>

音频任务、参考素材和自定义音色归属于 API Key 对应的顶级组织。同组织的工作台用户和模型 API Key 共享这些资源及积分余额。组织归属由平台鉴权确定,请求中无需填写账号或组织 ID。

公共请求约定

名称必填描述
AuthorizationBearer <YOUR_API_KEY>
Content-Type条件必填携带 JSON 请求体时必须为 application/json
Accept建议设置为 application/json
Idempotency-Key条件必填创建语音任务、创建自定义音色时必填,去除首尾空白后为 1~128 个字符
  • 请求和成功响应使用本文定义的 snake_case 字段;不支持的请求体字段会报错。
  • 时间戳均为 Unix 秒级时间戳;duration_ms 单位为毫秒;文件大小单位为字节。
  • 同一组织的模型 API 调用,在同一创建接口重复使用相同幂等键时会复用已有资源,不会按新的参数重新创建。请求超时后应使用原键重试;创建新任务或新音色时使用新的键,建议使用 UUID。
  • 音频生成采用轮询查询模式。任务创建成功响应为 JSON,生成结果为 WAV 文件。

推荐调用流程

  1. 查询语音计价与积分余额,确认 enabled=truebalance.available_points 足够。
  2. 查询音色列表,取得平台预设音色或自定义音色的 voice_id
  3. 创建语音任务,保存返回的 task_id
  4. 每隔 3 秒查询一次任务,直到状态为 succeededfailedcancelled
  5. 成功后从 task.output_url 下载音频。

需要使用自己的参考音频时,先完成「获取上传地址 → PUT 上传文件 → 登记素材」,取得 asset_id 后即可用于生成,也可将其保存为自定义音色。

创建文生语音任务

POST https://cp.compshare.cn/audio/v1/speech/jobs

请求参数

名称类型必填描述示例值
textString正文,最多 2000 个 Unicode 字符;至少包含一个汉字、字母或数字,不能只有空白、标点或符号你好,欢迎使用优云智算。
languageString语言:ZH 中文、EN 英文、JA 日文、ES 西班牙语、AR 阿拉伯语;默认 ZH,区分大小写ZH
voiceObject音色引用,结构见下表{"source":"preset","voice_id":"<VOICE_ID>"}
speedNumber语速,范围 0.5~2.0;省略或传 0 时按 1.0 处理1.0
auto_emotionBoolean自动推断情绪,默认 truetrue
emotion_descriptionString情绪描述,最多 200 个字符;非空时使用描述引导情绪温柔、平静,适合睡前故事
emotion_strengthNumber情绪强度,范围 0~1,默认 0.8;显式传 0 时保留零值0.8
emotion_vectorArray of Number8 维手动情绪向量,约束见下文[0.4,0,0,0,0,0,0,0]
emotion_vector_modeStringsinglemixed;必须与 emotion_vector 一起使用single
pronunciationsArray of Object读音规则,最多 100 条,结构见下文[{"word":"重庆","kind":"pinyin","value":"chong2 qing4"}]
save_voiceBoolean默认 false;仅 voice.source=asset 时可设为 true,同时保存一个自定义音色false
voice_nameString条件必填save_voice=true 时必填,去除首尾空白后为 1~64 个字符我的旁白音色

音色引用

名称类型必填描述
voice.sourceStringpreset 平台预设音色、custom 自定义音色、asset 临时参考素材
voice.voice_idString条件必填source=preset/custom 时必填,通过音色列表或创建音色接口获取
voice.asset_idString条件必填source=asset 时必填,通过登记参考音频素材接口获取

使用 preset/custom 时只需传 voice_id;使用 asset 时只需传 asset_id。示例中的 ID 均为占位值,应替换为接口实际返回的 ID。

预设音色示例

curl -X POST 'https://cp.compshare.cn/audio/v1/speech/jobs' \ -H 'Authorization: Bearer <YOUR_API_KEY>' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: speech-preset-001' \ -d '{ "text": "你好,欢迎使用优云智算文生语音服务。", "language": "ZH", "voice": {"source": "preset", "voice_id": "<PRESET_VOICE_ID>"}, "speed": 1.0, "auto_emotion": true }'

自定义音色与读音示例

curl -X POST 'https://cp.compshare.cn/audio/v1/speech/jobs' \ -H 'Authorization: Bearer <YOUR_API_KEY>' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: speech-custom-001' \ -d '{ "text": "欢迎来到重庆,这是一段温柔的城市介绍。", "language": "ZH", "voice": {"source": "custom", "voice_id": "<CUSTOM_VOICE_ID>"}, "speed": 0.9, "auto_emotion": false, "emotion_description": "温柔、自然,像朋友在介绍自己的家乡", "emotion_strength": 0.8, "pronunciations": [ {"word": "重庆", "kind": "pinyin", "value": "chong2 qing4"} ] }'

手动情绪向量

情绪向量固定为 8 维,顺序为:高兴、愤怒、悲伤、恐惧、厌恶、低落、惊讶、平静

  • 每个元素必须是 0~0.8 的数值,不能为 null
  • 元素之和必须大于 0 且不超过 0.8
  • 必须显式传入 auto_emotion=false,并省略 emotion_description 或传空字符串。
  • single 模式必须恰好有一个非零元素;mixed 支持组合情绪。
  • 省略 emotion_vector_mode 时,一个非零元素自动按 single 处理,否则按 mixed 处理。
  • emotion_strength 单独控制强度,传向量时无需先将强度乘进向量。

例如,在创建请求中加入:

{ "auto_emotion": false, "emotion_vector": [0.4, 0, 0, 0, 0, 0, 0, 0.2], "emotion_vector_mode": "mixed", "emotion_strength": 0.8 }

auto_emotion=false 且没有情绪描述、情绪向量时,使用参考音色本身的表现进行生成。

读音规则

名称类型必填描述
pronunciations[].wordString正文中的目标词语,去除首尾空白后为 1~64 个字符;同一请求中不能重复
pronunciations[].kindStringpinyinaliascmukana
pronunciations[].valueString指定读音,去除首尾空白后为 1~512 个字符
kind用途示例
pinyin中文拼音;目标词须为汉字,拼音音节数量与汉字数量一致,每个音节需带声调,音节间用空格分隔{"word":"重庆","kind":"pinyin","value":"chong2 qing4"}
alias用另一段文字引导目标词的读音{"word":"API","kind":"alias","value":"诶屁爱"}
cmu英文 CMU/ARPAbet 音素,音素间用空格分隔{"word":"read","kind":"cmu","value":"R IY1 D"}
kana日文假名,平台统一规范为片假名{"word":"今日","kind":"kana","value":"キョウ"}

词语和读音不能包含控制字符或 <>|。读音规则不改变积分计费所依据的原始正文。

响应参数

名称类型描述
task_idString任务 ID,用于查询、取消和删除任务
{"task_id": "019xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}

查询单个任务

GET https://cp.compshare.cn/audio/v1/speech/jobs/{task_id}

路径参数 task_id 为创建接口返回的任务 ID,无请求体。

curl 'https://cp.compshare.cn/audio/v1/speech/jobs/<TASK_ID>' \ -H 'Authorization: Bearer <YOUR_API_KEY>'

响应参数

名称类型描述
taskObject任务详情
task.task_idString任务 ID
task.typeString固定为 text_to_speech
task.inputObject规范化后的生成参数,字段与创建请求相同,包含生效的默认值
task.statusStringqueuedgeneratingsucceededfailedcancelled
task.attemptInteger已尝试的执行次数,尚未执行时为 0
task.max_attemptsInteger最大执行尝试次数,当前为 3
task.point_costInteger本任务的积分费用
task.point_statusStringreserved 已预占、consumed 已扣除、released 已释放;历史未计费记录可为空
task.error_messageString失败原因,非失败任务为空字符串
task.output_urlString生成音频的下载 URL,成功前为空字符串
task.output_sizeInteger生成音频大小,单位为字节;未生成时为 0
task.created_atInteger创建时间
task.started_atInteger开始执行时间,尚未开始时为 0
task.finished_atInteger结束时间,尚未结束时为 0

响应示例

{ "task": { "task_id": "019xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "type": "text_to_speech", "input": { "text": "你好,欢迎使用优云智算。", "language": "ZH", "voice": {"source": "preset", "voice_id": "<PRESET_VOICE_ID>"}, "auto_emotion": true, "emotion_strength": 0.8, "speed": 1 }, "status": "succeeded", "attempt": 1, "max_attempts": 3, "point_cost": 2, "point_status": "consumed", "error_message": "", "output_url": "https://example.com/generated/output.wav", "output_size": 240000, "created_at": 1789459200, "started_at": 1789459203, "finished_at": 1789459215 } }

示例中的积分费用仅用于说明响应结构,实际以任务返回值为准。生成结果默认在任务结束后保留 7 天,请及时下载保存;主动删除任务后,结果文件会被删除。

查询任务列表

GET https://cp.compshare.cn/audio/v1/speech/jobs

查询参数

名称类型必填描述示例值
offsetInteger0 开始的偏移量,默认 00
limitInteger每页数量,范围 1~100,默认 2020
task_idString精确筛选任务 ID<TASK_ID>
statusesString(可重复)按任务状态筛选,多次传入表示匹配任一状态queued
start_timeInteger创建时间下界,包含边界;0 或省略表示不限制1789459200
end_timeInteger创建时间上界,包含边界;0 或省略表示不限制;同时指定时须不小于 start_time1789545600

按创建时间从新到旧返回;已删除的任务不出现在列表中。

curl 'https://cp.compshare.cn/audio/v1/speech/jobs?offset=0&limit=20&statuses=queued&statuses=generating' \ -H 'Authorization: Bearer <YOUR_API_KEY>'

响应参数

名称类型描述
itemsArray of Object当前页任务,元素字段与单任务查询的 task 相同
totalInteger符合全部筛选条件的任务总数
status_countsObject各状态任务数;应用组织、任务 ID 和时间筛选,但不受 statuses 和分页影响;没有任务的状态可能不返回

例如,当前筛选没有排队或生成中的任务,但有 3 个已成功任务时:

{"items": [], "total": 0, "status_counts": {"succeeded": 3}}

取消任务

POST https://cp.compshare.cn/audio/v1/speech/jobs/{task_id}/cancel

路径参数 task_id 为待取消任务 ID,无请求体。queued 状态可取消,取消后释放预占积分。已经开始生成或已经结束的任务会返回业务错误。

curl -X POST 'https://cp.compshare.cn/audio/v1/speech/jobs/<TASK_ID>/cancel' \ -H 'Authorization: Bearer <YOUR_API_KEY>'

成功响应中的 task_id 为任务 ID,statuscancelled

{"task_id": "019xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "status": "cancelled"}

删除任务

DELETE https://cp.compshare.cn/audio/v1/speech/jobs/{task_id}

路径参数 task_id 为待删除任务 ID,无请求体。任务必须已经处于 succeededfailedcancelled,且积分已经结算。删除后任务不再出现在查询结果中,生成文件会被删除,已消费积分不会因删除而退回。

curl -X DELETE 'https://cp.compshare.cn/audio/v1/speech/jobs/<TASK_ID>' \ -H 'Authorization: Bearer <YOUR_API_KEY>'

成功响应中的 deleted=true 表示删除成功:

{"task_id": "019xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "deleted": true}

查询音色列表

GET https://cp.compshare.cn/audio/v1/voices

查询参数 kind 可取 presetcustom,默认 preset。预设音色仅返回平台已上线的音色;自定义音色返回当前组织共享的音色。

curl 'https://cp.compshare.cn/audio/v1/voices?kind=preset' \ -H 'Authorization: Bearer <YOUR_API_KEY>' curl 'https://cp.compshare.cn/audio/v1/voices?kind=custom' \ -H 'Authorization: Bearer <YOUR_API_KEY>'

响应参数

名称类型描述
itemsArray of Object音色列表,无音色时为 []
items[].voice_idString音色 ID,创建语音任务时作为 voice.voice_id 使用
items[].kindStringpresetcustom
items[].nameString音色名称
items[].descriptionString音色描述,未设置时不返回
items[].languageString音色语言信息,未设置时不返回
items[].voice_typeString音色类型信息,未设置时不返回
items[].style_tagsArray of String风格标签,无标签时为 []
items[].sample_textString示例文本,未设置时不返回
items[].audio_urlString音色试听音频 URL
items[].created_atInteger创建时间
totalInteger音色总数
{ "items": [{ "voice_id": "<PRESET_VOICE_ID>", "kind": "preset", "name": "示例旁白", "style_tags": ["自然"], "audio_url": "https://example.com/voice-sample.wav", "created_at": 1789459200 }], "total": 1 }

获取参考音频上传地址

POST https://cp.compshare.cn/audio/v1/upload_urls

文件要求

  • 支持 WAV、MP3、FLAC、OGG、M4A,文件扩展名和 content_type 必须匹配。
  • 单个文件默认上限为 15 MiB(15728640 字节)
  • 用于登记的参考音频时长必须为 500~15000 毫秒
  • file_name 为文件名,最多 255 个字符,不能包含目录分隔符或控制字符。
文件扩展名content_type
.wavaudio/wav,也支持 audio/x-wavaudio/waveaudio/vnd.wave
.mp3audio/mpeg
.flacaudio/flacaudio/x-flac
.oggaudio/ogg
.m4aaudio/mp4audio/x-m4a

请求参数

名称类型必填描述示例值
file_nameString参考音频文件名reference.wav
content_typeString文件 MIME 类型audio/wav
file_sizeInteger实际文件大小,必须大于 0240000
curl -X POST 'https://cp.compshare.cn/audio/v1/upload_urls' \ -H 'Authorization: Bearer <YOUR_API_KEY>' \ -H 'Content-Type: application/json' \ -d '{"file_name":"reference.wav","content_type":"audio/wav","file_size":240000}'

响应参数

名称类型描述
object_keyString上传对象标识,登记素材时原样传入
upload_urlString用于 PUT 上传的完整地址,包含临时签名参数
public_urlString上传暂存文件的地址;生成任务使用登记后返回的 asset_id
authorizationString兼容上传凭证字段,当前签名在 URL 中,该字段为空字符串
bucketString存储桶名称
regionString存储地域
expires_atInteger上传地址失效时间,默认有效期为 15 分钟,以返回值为准
{ "object_key": "ai-audio/production/uploads/<OWNER>/<UPLOAD_ID>/staging/reference.wav", "upload_url": "https://example.com/upload/reference.wav?UCloudPublicKey=...&Signature=...&Expires=1789460100", "public_url": "https://example.com/upload/reference.wav", "authorization": "", "bucket": "<BUCKET>", "region": "<REGION>", "expires_at": 1789460100 }

上传文件

使用返回的完整 upload_url 执行 PUT,Content-Type 必须与申请时一致:

curl --fail-with-body -X PUT '<UPLOAD_URL>' \ -H 'Content-Type: audio/wav' \ --data-binary '@reference.wav'

上传使用 URL 自带的临时签名,无需携带模型 API Key。应保留 URL 的完整查询参数,上传成功后再登记素材。

登记参考音频素材

POST https://cp.compshare.cn/audio/v1/assets

在 PUT 上传成功后调用,平台校验上传记录、实际文件大小和 MIME 类型,再生成用于语音任务的 asset_id

请求参数

名称类型必填描述示例值
object_keyString获取上传地址接口返回的对象标识<OBJECT_KEY>
file_nameString与申请上传时相同的文件名reference.wav
content_typeString与申请上传时相同的 MIME 类型audio/wav
file_sizeInteger与申请上传时相同的实际文件大小240000
duration_msInteger参考音频实际时长,范围 500~15000 毫秒5000
curl -X POST 'https://cp.compshare.cn/audio/v1/assets' \ -H 'Authorization: Bearer <YOUR_API_KEY>' \ -H 'Content-Type: application/json' \ -d '{ "object_key": "<OBJECT_KEY>", "file_name": "reference.wav", "content_type": "audio/wav", "file_size": 240000, "duration_ms": 5000 }'

响应参数

名称类型描述
assetObject素材信息
asset.asset_idString素材 ID
asset.purposeString固定为 speech_reference
asset.file_nameString文件名
asset.content_typeStringMIME 类型
asset.file_sizeInteger文件大小,单位为字节
asset.duration_msInteger参考音频时长,单位为毫秒
asset.public_urlString登记后素材的访问地址
asset.created_atInteger登记时间
{ "asset": { "asset_id": "<ASSET_ID>", "purpose": "speech_reference", "file_name": "reference.wav", "content_type": "audio/wav", "file_size": 240000, "duration_ms": 5000, "public_url": "https://example.com/reference/reference.wav", "created_at": 1789459200 } }

同一上传记录只能成功登记一次。登记后尚未使用的素材默认保留 7 天;需要长期复用音色时,可调用创建自定义音色接口保存。

直接使用素材生成并保存音色

curl -X POST 'https://cp.compshare.cn/audio/v1/speech/jobs' \ -H 'Authorization: Bearer <YOUR_API_KEY>' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: speech-reference-001' \ -d '{ "text": "这是使用参考音频生成的语音。", "voice": {"source": "asset", "asset_id": "<ASSET_ID>"}, "save_voice": true, "voice_name": "我的旁白音色" }'

创建任务响应只返回 task_id。同时保存的音色可通过 GET /audio/v1/voices?kind=custom 查询。若需要立即获得 voice_id,先调用下方的创建自定义音色接口,再以 voice.source=custom 创建任务。

创建自定义音色

POST https://cp.compshare.cn/audio/v1/voices

将已登记的参考音频保存为当前组织可复用的自定义音色。请求头必须包含 Idempotency-Key

请求参数

名称类型必填描述示例值
asset_idString已登记且可用的参考音频素材 ID<ASSET_ID>
nameString音色名称,去除首尾空白后为 1~64 个字符我的旁白音色
curl -X POST 'https://cp.compshare.cn/audio/v1/voices' \ -H 'Authorization: Bearer <YOUR_API_KEY>' \ -H 'Content-Type: application/json' \ -H 'Idempotency-Key: custom-voice-001' \ -d '{"asset_id":"<ASSET_ID>","name":"我的旁白音色"}'

响应中的 voice 与音色列表中的元素使用相同结构:

{ "voice": { "voice_id": "<CUSTOM_VOICE_ID>", "kind": "custom", "name": "我的旁白音色", "style_tags": [], "audio_url": "https://example.com/custom-voice/reference.wav", "created_at": 1789459200 } }

平台保存独立的音色副本,自定义音色不按临时参考素材的 7 天未使用规则清理。后续创建任务时传入 {"source":"custom","voice_id":"<CUSTOM_VOICE_ID>"} 即可。

删除自定义音色

DELETE https://cp.compshare.cn/audio/v1/voices/{voice_id}

路径参数 voice_id 为要删除的自定义音色 ID,无请求体。仅可删除当前组织的自定义音色;平台预设音色由平台管理。音色被排队中或生成中的任务引用时,删除会返回业务错误。

curl -X DELETE 'https://cp.compshare.cn/audio/v1/voices/<CUSTOM_VOICE_ID>' \ -H 'Authorization: Bearer <YOUR_API_KEY>'

成功响应中的 voice_id 为音色 ID,deleted=true 表示删除成功:

{"voice_id": "<CUSTOM_VOICE_ID>", "deleted": true}

查询语音计价与积分余额

GET https://cp.compshare.cn/audio/v1/pricing

无查询参数和请求体。返回当前语音计价规则,以及 API Key 所属组织的积分余额。

curl 'https://cp.compshare.cn/audio/v1/pricing' \ -H 'Authorization: Bearer <YOUR_API_KEY>'

响应参数

名称类型描述
enabledBoolean是否开启语音积分计费;为 false 时无法创建语音任务
pricing_versionInteger当前价格版本
unit_charactersInteger单价对应的计费字符数量,固定为 10
costs.text_to_speechInteger每 10 个正文计费字符的积分单价
balance.total_pointsInteger有效套餐中的剩余总积分,包含预占积分
balance.reserved_pointsInteger已被进行中任务预占的积分
balance.available_pointsInteger可用于创建新任务的积分
{ "enabled": true, "pricing_version": 3, "unit_characters": 10, "costs": {"text_to_speech": 2}, "balance": {"total_points": 100, "reserved_points": 20, "available_points": 80} }

计费规则

积分费用按下式计算,整次请求只向上取整一次:

积分费用 = ceil(正文计费字符数 × costs.text_to_speech / 10)
  • Unicode 字母(含汉字)和十进制数字计费。
  • 空白、标点、其他符号不计费,但仍占用 2000 字符输入长度。
  • 情绪描述、读音规则不计入正文计费字符数。
  • 创建任务时预占积分,成功后扣除,失败或取消后释放。
  • 音频与 MiniMax H3 共用组织积分余额,创建前以 available_points 判断是否足够。

例如,上述响应的单价为每 10 字符 2 积分,正文有 11 个计费字符时,费用为 ceil(11 × 2 / 10) = 3 积分。该价格仅为示例,实际单价以接口返回值为准。

查询积分套餐包

GET https://cp.compshare.cn/minimax/v2/query/point_packages

复用 MiniMax H3 的积分套餐查询接口,查询当前组织已经领取或购买的积分套餐;无查询参数和请求体。

curl 'https://cp.compshare.cn/minimax/v2/query/point_packages' \ -H 'Authorization: Bearer <YOUR_API_KEY>'

响应参数

名称类型描述
itemsArray of Object积分套餐列表
items[].idString套餐包 ID
items[].codeString套餐规格编码
items[].nameString套餐名称
items[].statusStringpending 待生效、active 可用、exhausted 已用完、expired 已过期
items[].total_pointsInteger套餐初始积分
items[].remaining_pointsInteger尚未扣除的积分,包含预占积分
items[].reserved_pointsInteger预占积分
items[].available_pointsInteger可用积分;不可用状态下为 0
items[].purchased_atInteger购买或激活时间,尚未激活时可能不返回
items[].expires_atInteger过期时间,尚未激活时可能不返回
items[].created_atInteger记录创建时间
items[].order_noString订单号,无订单时不返回
items[].total_priceInteger实付金额,单位为分;无付费金额时不返回
totalInteger套餐总数
{ "items": [{ "id": "<PACKAGE_ID>", "code": "<PACKAGE_CODE>", "name": "示例积分包", "status": "active", "total_points": 100, "remaining_points": 80, "reserved_points": 10, "available_points": 70, "created_at": 1789459200 }], "total": 1 }

更多说明参见 MiniMax H3 视频任务 API — 查询积分套餐包

任务状态与错误处理

任务状态

状态含义调用方处理
queued排队中继续轮询,或调用取消接口
generating生成或上传结果中继续轮询
succeeded生成成功output_url 下载音频
failed生成失败查看 error_message;需重新生成时使用新的幂等键
cancelled已取消停止轮询

请求错误

鉴权失败返回 HTTP 401;OpenAPI 参数格式错误返回 HTTP 400;下游服务连接或响应解析失败返回 HTTP 502。参数格式错误示例:

{ "type": "error", "error": { "type": "bad_request_error", "message": "Idempotency-Key is required and must contain 1 to 128 characters", "http_code": "400" }, "request_id": "<REQUEST_ID>" }

业务后端的错误会保留原 HTTP 状态和响应体,常见字段为 RetCodeMessagerequest_uuid即使 HTTP 状态为 200,只要 RetCode 非零,也表示请求失败。下游 HTTP 错误也可能返回非 JSON 内容。

情况处理建议
文本、语言、语速、情绪或读音参数不符合要求根据 Message 修正请求
积分不足查询可用积分并补充积分
组织存储空间已满清理不需要的任务和文件后重试
任务、素材或音色不存在检查 ID、所属组织及资源是否已删除或清理
上传信息不匹配确认文件名、MIME 类型、文件大小与申请上传时一致
取消时任务已经开始执行查询最新任务状态
删除音色时仍有活动任务引用等待相关任务结束后再删除
创建请求超时或连接中断保留并复用原 Idempotency-Key 重试

完整调用示例

以下 Python 示例使用标准库完成「查价格和余额 → 选择预设音色 → 创建任务 → 轮询 → 下载」。先设置环境变量 COMPSHARE_API_KEY;可选设置 COMPSHARE_VOICE_ID 指定一个预设音色,否则选择列表中的第一个。

import json import os import time import uuid from pathlib import Path from urllib.request import Request, urlopen BASE_URL = "https://cp.compshare.cn" API_KEY = os.environ["COMPSHARE_API_KEY"] def api(method, path, body=None, idempotency_key=None): headers = {"Authorization": f"Bearer {API_KEY}", "Accept": "application/json"} data = None if body is not None: headers["Content-Type"] = "application/json" data = json.dumps(body, ensure_ascii=False).encode("utf-8") if idempotency_key: headers["Idempotency-Key"] = idempotency_key request = Request(BASE_URL + path, data=data, headers=headers, method=method) # 非 2xx 响应由 urlopen 抛出 HTTPError;2xx 响应仍需检查业务错误。 with urlopen(request, timeout=60) as response: result = json.load(response) if result.get("RetCode", 0) != 0 or "error" in result: raise RuntimeError(result) return result text = "你好,欢迎使用优云智算文生语音服务。" pricing = api("GET", "/audio/v1/pricing") if not pricing["enabled"]: raise RuntimeError("语音生成当前不可用") characters = sum(character.isalpha() or character.isdecimal() for character in text) unit = pricing["unit_characters"] cost = (characters * pricing["costs"]["text_to_speech"] + unit - 1) // unit if pricing["balance"]["available_points"] < cost: raise RuntimeError("可用积分不足") voice_id = os.environ.get("COMPSHARE_VOICE_ID") if not voice_id: voices = api("GET", "/audio/v1/voices?kind=preset")["items"] if not voices: raise RuntimeError("当前没有可用的预设音色") voice_id = voices[0]["voice_id"] # 保存此键;若创建请求超时,应使用同一键和相同请求重试。 idempotency_key = str(uuid.uuid4()) print("Idempotency-Key:", idempotency_key) result = api("POST", "/audio/v1/speech/jobs", { "text": text, "language": "ZH", "voice": {"source": "preset", "voice_id": voice_id}, "speed": 1.0, "auto_emotion": True, }, idempotency_key=idempotency_key) task_id = result["task_id"] print("task_id:", task_id) deadline = time.monotonic() + 1200 while time.monotonic() < deadline: task = api("GET", f"/audio/v1/speech/jobs/{task_id}")["task"] if task["status"] == "succeeded": # 下载公共结果地址时无需携带模型 API Key。 with urlopen(task["output_url"], timeout=60) as audio: Path("speech.wav").write_bytes(audio.read()) print("已保存 speech.wav,消耗积分:", task["point_cost"]) break if task["status"] in {"failed", "cancelled"}: raise RuntimeError(task["error_message"] or task["status"]) time.sleep(3) else: raise TimeoutError(f"轮询超时,可继续查询任务 {task_id}")
Last updated on