文档
音乐生成
使用 Suno V5 / V5.5 将文本生成音乐,支持人声、歌词和风格控制。提供两种 API 形式:一种是单次调用的同步端点,会一直等待直至曲目就绪;另一种是适用于生产环境的提交并轮询式异步 API(支持签名 webhook)。
端点:POST /v1/audio/music(同步,首先介绍),以及 POST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id}(异步,推荐用于生产环境)。每个请求生成两首曲目;生成约需 1–3 分钟。价格:在 suno-v5 上每个生成请求 $0.09,在 suno-v5-5 上为 $0.09 ——两首曲目只收取一次费用,从预付余额中扣除;生成失败不收费。
快速开始(同步)
传入一个 prompt 和一个 Suno 模型。请求会保持打开状态,直到两首曲目就绪,然后返回它们的永久 URL。
import requests
# Synchronous: one request blocks until the tracks are ready (1-3 min).
resp = requests.post(
"https://api.kunavo.com/v1/audio/music",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "suno-v5",
"prompt": "upbeat lofi hip hop for late-night coding, mellow piano",
"instrumental": True,
},
timeout=600, # generation can take a few minutes
)
# Suno returns ~2 tracks per request.
for track in resp.json()["data"]:
print(track["url"], track.get("image_url"))参数
| 参数 | 类型 | 备注 |
|---|---|---|
model | 字符串(必填) | 音乐模型 slug —— suno-v5 或 suno-v5-5。 |
prompt | 字符串(必填) | 音乐描述(自定义模式下为歌词)。 |
instrumental | bool | true = 无人声。默认值为 false。 |
customMode | bool | Suno 高级模式 ——明确设置曲目结构 / 歌词 / 风格。 |
style | string | 风格 / 流派提示,例如“lofi, jazz, chill”。 |
title | string | 曲目标题。 |
webhook_url | string(https) | 仅限异步 ——在此推送签名的终态事件。请参阅 Webhooks。 |
音乐模型
| 标识符(slug) | 提供商 | 备注 |
|---|---|---|
suno-v5 | Suno | Suno V5 ——支持人声、歌词和风格融合。 |
suno-v5-5 | Suno | Suno V5.5 ——最新版本,保真度更高,生成时长更长。 |
请查看 /models,获取当前模型列表和每次调用的定价。
异步 API(提交 + 轮询)
端点:POST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id}。结构与异步视频 API 相同,因此相同的轮询 / webhook 代码可用于不同模态。
同步端点会将 HTTP 连接保持数分钟 ——适合脚本,但在移动网络上不可靠。异步端点组合会立即返回一个 msc_* ID;你可以轮询 GET /v1/audio/music/jobs/{id},直到 status 变为 completed 或 failed。模型、定价和永久 CDN URL 均相同。
import requests, time
# 1. Submit — returns immediately with a msc_ task id. No long-lived connection.
submit = requests.post(
"https://api.kunavo.com/v1/audio/music/jobs",
headers={
"Authorization": f"Bearer {API_KEY}",
# Optional: retrying with the same key inside ~24h returns the
# original task rather than submitting again.
"Idempotency-Key": "my-song-uuid",
},
json={
"model": "suno-v5",
"prompt": "dreamy synthwave with a driving bassline",
"title": "Midnight Drive",
},
timeout=60,
).json()
task_id = submit["id"] # "msc_abc..."
status = submit["status"] # "queued"
# 2. Poll until terminal. Recommended cadence: 5s, backing off to 30s.
while status not in ("completed", "failed"):
time.sleep(5)
r = requests.get(
f"https://api.kunavo.com/v1/audio/music/jobs/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=30,
).json()
status = r["status"]
if status == "failed":
raise RuntimeError(r["error"]["message"])
for track in r["output"]["tracks"]:
print(track["url"])响应格式
| 字段 | 类型 | 备注 |
|---|---|---|
id | string | 以 msc_ 为前缀的任务 ID。 |
object | string | "music". |
status | string | queued | in_progress | completed | failed。 |
model | string | 提交时指定的模型 slug。 |
created_at | int | 我们接受提交请求时的 Unix 秒数。 |
completed_at | int | null | 进入终态时的 Unix 秒数 ——任务待处理时为 null。 |
expires_at | int | 提交后满 30 天时的 Unix 秒数:至少在此之前都可以轮询该任务。其结果 URL 不会过期。 |
progress | int | 进入终态前为 0,之后为 100。 |
output | object | null | 完成时返回 {tracks[], archived}。 |
output. | array | 每条记录包含:{url, stream_url, image_ |
error | object | null | 失败时返回 {code, message}。 |
请求头与约定
Idempotency-Key(可选,≤128 个字符)——在同一账户中使用相同密钥重复提交时,会返回原任务,而不会创建重复任务。- 新提交时,
POST /v1/audio/music/jobs返回 202 Accepted;幂等密钥重放结果时,则返回 200 OK。 GET的作用范围限定于所属账户:查询属于其他账户的任务会返回 404。- 建议的轮询间隔:5 s,随后逐渐延长至 30 s。
Webhook 回调
提交时传入 webhook_url(https),任务进入终态时,Kunavo 会立即向该地址 POST 一个带签名的 music.completed / music.failed 事件,并通过重试和退避机制进行投递。事件的 data 字段与上面的 GET 响应负载完全一致。
# Pass webhook_url on submit to be pushed a signed event on terminal —
# instead of (or alongside) polling:
# {"model": "suno-v5", "prompt": "...", "webhook_url": "https://you.com/hook"}
#
# Verify the HMAC signature on your receiver (Flask shown):
import hmac, hashlib
from flask import request, abort
def verify(secret: str) -> dict:
ts = request.headers["X-Kunavo-Webhook-Timestamp"]
sig = request.headers["X-Kunavo-Webhook-Signature"] # "sha256=<hex>"
raw = request.get_data(as_text=True)
expected = "sha256=" + hmac.new(
secret.encode(), f"{ts}.{raw}".encode(), hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, sig):
abort(401)
return request.get_json()
# Event body:
# { "id": "evt_...", "object": "event",
# "type": "music.completed" | "music.failed",
# "created_at": 1700000000,
# "data": { ...the GET /v1/audio/music/jobs/{id} payload... } }{timestamp}.{rawBody} 的 HMAC-SHA256,通过 X-Kunavo-Webhook-Signature: sha256=<hex> 发送。生成签名的方式与视频 webhook 相同,因此一个验证器即可处理两者。何时使用哪种方式
| 同步 /v1/ | 异步 /v1/ | |
|---|---|---|
| 适用场景 | 一次性脚本、笔记本 | 生产环境、移动端、webhook |
| 网络 | 连接保持 1-3 分钟 | 几秒内提交;轮询或接收推送 |
| 故障恢复 | 丢失响应 = 丢失结果 | expires_at 到期前随时重新查询该 ID |
| Webhook 回调 | — | 已签名的 music. |
响应与存储
每首曲目的 url(音频)和 image_url(封面图)都是永久的 files.kunavo.com 链接 ——Kunavo 会将每个结果存档至自己的 CDN,因此这些链接与 Suno 原始 URL 不同,永不过期。stream_url 是 Suno 的原始流媒体链接(便于即时播放)。每首曲目也会显示在 /app/assets 中。
output.archived 会显示 false,URL 将回退为 Suno 的临时链接(约 24 小时后过期)——此时请自行重新托管。