Skip to content

音乐生成 ​

音乐生成 API 可以根据文字描述创作带人声的完整歌曲或纯音乐。接口采用异步生成方式:先提交一次生成请求并保存返回的 clip ID,再通过查询接口获取生成进度和最终音频地址。

快速了解 ​

一次完整调用包含以下步骤:

  1. 使用公开模型 ID 提交生成请求。
  2. 从 HTTP 202 响应中保存所有 clips[].id。
  3. 每隔一段时间批量查询这些 ID。
  4. 当状态变为 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-v6V6(旗舰核心模型)
suno-v6-wildV6 Wild(实验性探索)
suno-v6-miniV6 Mini(轻量快速)

不同模型分别按次定价。实际可用模型和当前价格以工作台的模型列表为准。

提交音乐生成 ​

POST https://oneapi.zaiwenai.com/v1/music/generations

请求体使用 JSON 格式,并设置 Content-Type: application/json。

请求参数 ​

参数类型必填默认值说明
modelstring是-使用上方列出的公开模型 ID
modestring否simplesimple 或 custom
promptstring视模式而定""简单模式中的歌曲描述,或自定义模式中的歌词
instrumentalboolean否falsetrue 生成纯音乐,false 生成带人声歌曲
stylestring自定义模式必填-曲风、乐器、速度、情绪等风格说明
titlestring自定义模式必填-歌曲标题
negative_stylestring否-希望避免的风格或声音元素
vocal_genderstring否-人声倾向,可选 male 或 female
style_weightnumber否-风格约束强度,范围为 0 到 1
weirdnessnumber否-创意和意外程度,范围为 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 数组。

片段字段 ​

字段类型说明
idstring片段唯一 ID
objectstring固定为 music.clip
modelstring结果记录携带的模型标识
statusstring当前生成状态
titlestring歌曲标题,尚未生成时可能为空
lyricsstring歌词;纯音乐或处理中可能为空
stylestring结果使用的风格描述
audio_urlstring最终音频地址;成功前可能为空
video_urlstring音乐视频地址;没有视频时可能为空
image_urlstring封面图片地址;生成完成前可能为空
durationnumber音频时长,单位为秒
created_atstring 或 integer创建时间
errorobject失败原因,正常情况下为空或不返回

响应会省略当前没有值的可选字段。客户端应按字段是否存在来读取,不要假定所有字段始终返回。

状态说明 ​

状态是否终态说明
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 和必填字段
401API Key 缺失或无效检查 Authorization 请求头
402账户余额不足充值后重新提交
404查询的片段不存在检查 clip_id 是否完整、正确
422字段类型、取值范围或请求格式错误根据响应中的字段提示修正 JSON
502本次生成或查询结果暂时不可用稍后重试查询;提交失败时谨慎重试
503服务暂时不可用或连接超时稍后重试,并使用退避策略限制频率

接入建议 ​

  • 将每次提交返回的全部 clip ID 与你自己的业务记录关联。
  • 使用批量查询减少请求次数,并把轮询间隔设置为 10 至 20 秒。
  • 以 status 判断任务是否完成,不要以 audio_url 是否出现作为唯一依据。
  • 对 failed 状态记录 error.message,不要继续轮询失败片段。
  • 播放或下载前确认 audio_url 非空。
  • 用户主动取消页面等待时,仍可保留片段 ID,稍后继续查询。
  • 设置合理的提交超时和查询超时,但不要因一次客户端超时无限重复提交。

常见问题 ​

为什么提交接口没有直接返回完整歌曲? ​

歌曲生成需要一定时间,因此提交接口先返回可查询的片段 ID。客户端可以继续处理其他工作,并通过查询接口获取进度。

一次请求为什么返回多个片段? ​

一次创作可能提供多个候选结果。每个候选片段都有独立 ID、状态和音频地址,应分别处理。

可以只查询其中一个片段吗? ​

可以。使用单个片段查询接口即可;需要同时跟踪多个候选结果时,推荐使用批量查询。

查询状态会重复扣费吗? ​

不会。音乐生成只在提交请求被接受时按次计费,后续状态查询不额外收费。

可以直接使用返回的音频地址吗? ​

可以。任务成功并返回非空 audio_url 后,可以用该地址播放或下载音频。是否需要另外保存副本,可根据你的业务归档需求决定,调用接口本身不要求配置对象存储。