Appearance
音乐生成
音乐生成 API 可以根据文字描述创作带人声的完整歌曲或纯音乐。接口采用异步生成方式:先提交一次生成请求并保存返回的 clip ID,再通过查询接口获取生成进度和最终音频地址。
快速了解
一次完整调用包含以下步骤:
- 使用公开模型 ID 提交生成请求。
- 从 HTTP
202响应中保存所有clips[].id。 - 每隔一段时间批量查询这些 ID。
- 当状态变为
succeeded时,使用audio_url播放或下载音频。
TIP
一次生成请求通常会返回多个候选片段。请保存并查询响应中的全部 clip ID,不要只处理第一项。
接口一览
| 用途 | 方法与路径 | 是否计费 |
|---|---|---|
| 提交音乐生成 | POST /v1/music/generations | 按所选模型计费一次 |
| 批量查询片段 | GET /v1/music/clips?ids=... | 不额外计费 |
| 查询单个片段 | GET /v1/music/clips/{clip_id} | 不额外计费 |
所有接口均使用相同的 API Key:
http
Authorization: Bearer YOUR_API_KEY支持的模型
请求中的 model 必须填写下列公开模型 ID 之一:
| 模型 ID | 版本 |
|---|---|
suno-v6 | V6(旗舰核心模型) |
suno-v6-wild | V6 Wild(实验性探索) |
suno-v6-mini | V6 Mini(轻量快速) |
不同模型分别按次定价。实际可用模型和当前价格以工作台的模型列表为准。
提交音乐生成
POST https://oneapi.zaiwenai.com/v1/music/generations
请求体使用 JSON 格式,并设置 Content-Type: application/json。
请求参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
model | string | 是 | - | 使用上方列出的公开模型 ID |
mode | string | 否 | simple | simple 或 custom |
prompt | string | 视模式而定 | "" | 简单模式中的歌曲描述,或自定义模式中的歌词 |
instrumental | boolean | 否 | false | true 生成纯音乐,false 生成带人声歌曲 |
style | string | 自定义模式必填 | - | 曲风、乐器、速度、情绪等风格说明 |
title | string | 自定义模式必填 | - | 歌曲标题 |
negative_style | string | 否 | - | 希望避免的风格或声音元素 |
vocal_gender | string | 否 | - | 人声倾向,可选 male 或 female |
style_weight | number | 否 | - | 风格约束强度,范围为 0 到 1 |
weirdness | number | 否 | - | 创意和意外程度,范围为 0 到 1 |
不支持的字段会被拒绝。建议仅发送当前场景实际需要的参数。
简单模式
简单模式适合快速创作。你只需要用自然语言描述想要的歌曲,系统会自动组织标题、歌词、风格和编曲。
简单模式规则:
mode省略时默认为simple。prompt必填且不能为空。instrumental=false时生成带人声歌曲。instrumental=true时生成纯音乐。
生成带人声歌曲
bash
curl https://oneapi.zaiwenai.com/v1/music/generations \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6",
"mode": "simple",
"prompt": "一首温暖的中文流行歌曲,主题是雨后重新出发,女声演唱,副歌明亮而有记忆点",
"instrumental": false
}'生成纯音乐
bash
curl https://oneapi.zaiwenai.com/v1/music/generations \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6-mini",
"prompt": "轻快的电子氛围音乐,清晰的鼓点和明亮的合成器,适合作为科技产品演示背景音乐",
"instrumental": true
}'自定义模式
自定义模式适合需要明确控制标题、歌词和曲风的场景。
自定义模式规则:
mode必须设置为custom。style和title必填且不能为空。- 生成带人声歌曲时,
prompt必填,并作为歌词使用。 - 生成纯音乐时,将
instrumental设为true,此时prompt可以留空。
使用自定义歌词
bash
curl https://oneapi.zaiwenai.com/v1/music/generations \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6",
"mode": "custom",
"title": "雨后的站台",
"style": "中文流行,温暖女声,中速,钢琴与弦乐,副歌逐渐增强",
"prompt": "[Verse]\n雨停在清晨的站台\n风把昨天轻轻吹开\n\n[Chorus]\n我向着亮起来的天\n把新的故事写一遍",
"instrumental": false,
"vocal_gender": "female",
"style_weight": 0.7,
"weirdness": 0.25
}'自定义纯音乐
bash
curl https://oneapi.zaiwenai.com/v1/music/generations \
-H "Authorization: Bearer $YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6-wild",
"mode": "custom",
"title": "Neon Morning",
"style": "synthwave, cinematic, mid-tempo, bright arpeggios, punchy drums",
"prompt": "",
"instrumental": true,
"negative_style": "distorted vocals, harsh noise",
"style_weight": 0.8,
"weirdness": 0.2
}'如何编写提示词
简单模式的 prompt 建议包含以下信息:
- 音乐类型:流行、摇滚、电子、民谣、爵士、古典等。
- 情绪氛围:温暖、忧郁、振奋、梦幻、紧张、平静等。
- 节奏速度:慢速、中速、快节奏,或者描述鼓点特征。
- 主要乐器:钢琴、吉他、弦乐、合成器、鼓组等。
- 人声要求:语言、男声或女声、演唱质感。
- 使用场景:短视频背景、游戏场景、播客片头、品牌展示等。
比起堆叠大量互相冲突的形容词,清晰表达音乐类型、情绪和核心乐器通常更容易得到稳定结果。
自定义歌词可以使用 [Verse]、[Chorus]、[Bridge] 等段落标记帮助表达歌曲结构。段落标记属于歌词内容的一部分,不需要额外字段。
提交成功响应
请求被接受后返回 HTTP 202:
json
{
"object": "music.generation",
"model": "suno-v6",
"clips": [
{
"id": "87d7be70-6fb7-494b-a465-436332eadf02",
"object": "music.clip",
"model": "chirp-hawk",
"status": "pending"
},
{
"id": "7218e443-c702-46c1-903a-183f48db5f73",
"object": "music.clip",
"model": "chirp-hawk",
"status": "pending"
}
]
}| 字段 | 说明 |
|---|---|
object | 固定为 music.generation |
model | 本次请求使用的公开模型 ID |
clips | 本次生成产生的候选片段列表 |
clips[].id | 后续查询使用的片段 ID,必须保存 |
clips[].status | 当前片段状态,提交时通常为 pending 或 partial |
clips[].model 是结果记录携带的模型标识,具体值以实际响应为准。选择模型、统计费用或重新发起请求时,应使用提交请求时的公开模型 ID,而不是依赖该字段。
查询生成结果
批量查询
推荐优先使用批量查询,一次可以查询最多 20 个片段 ID。
GET https://oneapi.zaiwenai.com/v1/music/clips?ids={id1},{id2}
bash
curl "https://oneapi.zaiwenai.com/v1/music/clips?ids=87d7be70-6fb7-494b-a465-436332eadf02,7218e443-c702-46c1-903a-183f48db5f73" \
-H "Authorization: Bearer $YOUR_API_KEY"响应格式:
json
{
"object": "list",
"data": [
{
"id": "87d7be70-6fb7-494b-a465-436332eadf02",
"object": "music.clip",
"model": "chirp-hawk",
"status": "succeeded",
"title": "雨后的站台",
"lyrics": "雨停在清晨的站台……",
"style": "中文流行,钢琴,弦乐",
"audio_url": "https://example.com/generated-song.mp3",
"video_url": "https://example.com/generated-song.mp4",
"image_url": "https://example.com/generated-cover.jpeg",
"duration": 188.84,
"created_at": "2026-08-04T07:50:59.078Z"
}
]
}查询单个片段
GET https://oneapi.zaiwenai.com/v1/music/clips/{clip_id}
bash
curl https://oneapi.zaiwenai.com/v1/music/clips/87d7be70-6fb7-494b-a465-436332eadf02 \
-H "Authorization: Bearer $YOUR_API_KEY"成功时直接返回一个 music.clip 对象,不再包含外层的 data 数组。
片段字段
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 片段唯一 ID |
object | string | 固定为 music.clip |
model | string | 结果记录携带的模型标识 |
status | string | 当前生成状态 |
title | string | 歌曲标题,尚未生成时可能为空 |
lyrics | string | 歌词;纯音乐或处理中可能为空 |
style | string | 结果使用的风格描述 |
audio_url | string | 最终音频地址;成功前可能为空 |
video_url | string | 音乐视频地址;没有视频时可能为空 |
image_url | string | 封面图片地址;生成完成前可能为空 |
duration | number | 音频时长,单位为秒 |
created_at | string 或 integer | 创建时间 |
error | object | 失败原因,正常情况下为空或不返回 |
响应会省略当前没有值的可选字段。客户端应按字段是否存在来读取,不要假定所有字段始终返回。
状态说明
| 状态 | 是否终态 | 说明 |
|---|---|---|
pending | 否 | 已进入队列,等待开始生成 |
partial | 否 | 已产生部分结果,仍需继续查询 |
running | 否 | 正在生成或处理 |
succeeded | 是 | 已完成;确认 audio_url 后即可使用 |
failed | 是 | 生成失败;查看 error.message |
建议每隔 10 至 20 秒查询一次。到达 succeeded 或 failed 后停止轮询。不要以固定等待时长代替状态判断,因为不同歌曲的生成时间可能不同。
WARNING
收到 partial 时不要将任务视为完成。即使响应中已经出现部分可用字段,也应继续查询到终态。
完整 Python 示例
下面的示例会提交请求、批量轮询全部片段,并在完成后打印音频地址:
python
import time
import requests
BASE_URL = "https://oneapi.zaiwenai.com/v1"
API_KEY = "YOUR_API_KEY"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
generation_response = requests.post(
f"{BASE_URL}/music/generations",
headers=HEADERS,
json={
"model": "suno-v6",
"mode": "simple",
"prompt": "温暖的中文流行歌曲,女声,中速,钢琴与弦乐",
"instrumental": False,
},
timeout=180,
)
generation_response.raise_for_status()
generation = generation_response.json()
clip_ids = [clip["id"] for clip in generation["clips"]]
print("已提交:", clip_ids)
while True:
query_response = requests.get(
f"{BASE_URL}/music/clips",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"ids": ",".join(clip_ids)},
timeout=30,
)
query_response.raise_for_status()
clips = query_response.json()["data"]
print({clip["id"]: clip["status"] for clip in clips})
if all(clip["status"] in {"succeeded", "failed"} for clip in clips):
break
time.sleep(15)
for clip in clips:
if clip["status"] == "succeeded":
print(clip.get("title"), clip.get("audio_url"))
else:
print(clip["id"], "生成失败:", clip.get("error"))完整 JavaScript 示例
以下示例适用于支持原生 fetch 的 Node.js 环境:
javascript
const baseUrl = "https://oneapi.zaiwenai.com/v1";
const apiKey = "YOUR_API_KEY";
const headers = {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
};
const generationResponse = await fetch(`${baseUrl}/music/generations`, {
method: "POST",
headers,
body: JSON.stringify({
model: "suno-v6",
mode: "simple",
prompt: "温暖的中文流行歌曲,女声,中速,钢琴与弦乐",
instrumental: false,
}),
});
if (!generationResponse.ok) {
throw new Error(await generationResponse.text());
}
const generation = await generationResponse.json();
const clipIds = generation.clips.map((clip) => clip.id);
let clips = [];
while (true) {
await new Promise((resolve) => setTimeout(resolve, 15000));
const ids = encodeURIComponent(clipIds.join(","));
const queryResponse = await fetch(`${baseUrl}/music/clips?ids=${ids}`, {
headers: { Authorization: `Bearer ${apiKey}` },
});
if (!queryResponse.ok) {
throw new Error(await queryResponse.text());
}
clips = (await queryResponse.json()).data;
if (clips.every((clip) => ["succeeded", "failed"].includes(clip.status))) {
break;
}
}
for (const clip of clips) {
console.log(clip.status, clip.title, clip.audio_url, clip.error);
}不要把 API Key 放入公开网页或浏览器前端代码。生产环境应由你自己的服务端安全保存并使用 API Key。
计费说明
音乐生成按照所选模型的请求次数计费:
- 一次被接受的
POST /v1/music/generations按所选模型计费一次。 - 同一次请求返回多个候选片段时,仍按这一次请求计费。
- 查询单个或批量片段不会产生额外音乐生成费用。
- 对同一提示词重复提交
POST会被视为新的生成请求,并再次计费。 - 任务后续状态变化不会产生第二次费用。
提交前会检查账户余额。余额不足时返回 HTTP 402,不会接受生成请求。具体单价和消费记录可在工作台中查看。
避免重复提交
如果客户端因网络问题没有收到提交响应,不要立即无限重试。先检查调用记录,并为自动重试设置明确的次数上限,避免创建和计费多次生成请求。
常见错误
错误响应使用统一结构:
json
{
"error": {
"message": "错误说明",
"type": "错误类型",
"param": "相关参数",
"code": "错误代码"
}
}| HTTP 状态码 | 常见原因 | 处理建议 |
|---|---|---|
400 | 模型不支持或模式参数组合无效 | 检查模型 ID、mode 和必填字段 |
401 | API Key 缺失或无效 | 检查 Authorization 请求头 |
402 | 账户余额不足 | 充值后重新提交 |
404 | 查询的片段不存在 | 检查 clip_id 是否完整、正确 |
422 | 字段类型、取值范围或请求格式错误 | 根据响应中的字段提示修正 JSON |
502 | 本次生成或查询结果暂时不可用 | 稍后重试查询;提交失败时谨慎重试 |
503 | 服务暂时不可用或连接超时 | 稍后重试,并使用退避策略限制频率 |
接入建议
- 将每次提交返回的全部
clipID 与你自己的业务记录关联。 - 使用批量查询减少请求次数,并把轮询间隔设置为
10至20秒。 - 以
status判断任务是否完成,不要以audio_url是否出现作为唯一依据。 - 对
failed状态记录error.message,不要继续轮询失败片段。 - 播放或下载前确认
audio_url非空。 - 用户主动取消页面等待时,仍可保留片段 ID,稍后继续查询。
- 设置合理的提交超时和查询超时,但不要因一次客户端超时无限重复提交。
常见问题
为什么提交接口没有直接返回完整歌曲?
歌曲生成需要一定时间,因此提交接口先返回可查询的片段 ID。客户端可以继续处理其他工作,并通过查询接口获取进度。
一次请求为什么返回多个片段?
一次创作可能提供多个候选结果。每个候选片段都有独立 ID、状态和音频地址,应分别处理。
可以只查询其中一个片段吗?
可以。使用单个片段查询接口即可;需要同时跟踪多个候选结果时,推荐使用批量查询。
查询状态会重复扣费吗?
不会。音乐生成只在提交请求被接受时按次计费,后续状态查询不额外收费。
可以直接使用返回的音频地址吗?
可以。任务成功并返回非空 audio_url 后,可以用该地址播放或下载音频。是否需要另外保存副本,可根据你的业务归档需求决定,调用接口本身不要求配置对象存储。