Tài liệu

Tài liệu

Tạo nhạc

Chuyển văn bản thành nhạc bằng Suno V5 / V5.5 — điều khiển giọng hát, lời bài hát và phong cách. Có hai dạng API: điểm cuối đồng bộ một lần chờ cho đến khi các bản nhạc sẵn sàng, và cặp API bất đồng bộ kiểu gửi yêu cầu rồi thăm dò (có webhook ký số) dành cho môi trường production.

Các điểm cuối: POST /v1/audio/music (đồng bộ, trình bày trước), và POST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id} (bất đồng bộ, khuyến nghị cho production). Mỗi yêu cầu tạo ra hai bản nhạc; quá trình tạo mất khoảng 1–3 phút. Giá: $0.09 cho mỗi yêu cầu tạo trên suno-v5, $0.09 trên suno-v5-5 — tính phí một lần cho cả hai bản nhạc, trừ từ số dư trả trước; lần tạo thất bại sẽ không bị tính phí.

Bắt đầu nhanh (đồng bộ)

Gửi một prompt và model Suno. Yêu cầu sẽ chờ cho đến khi cả hai bản nhạc sẵn sàng, sau đó trả về URL vĩnh viễn của chúng.

import os

import requests

API_KEY = os.environ["KUNAVO_API_KEY"]

# 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"))
Suno mất 1–3 phút để tạo nhạc. Điểm cuối đồng bộ giữ kết nối mở ở phía máy chủ cho đến khi các bản nhạc sẵn sàng, tối đa khoảng 9 phút thăm dò, vì vậy hãy đặt thời gian chờ tương ứng cho ứng dụng HTTP của bạn (≥600s). Với tác vụ lâu hơn, lưu lượng production hoặc mạng di động / không ổn định, hãy ưu tiên API bất đồng bộ — yêu cầu gửi tác vụ sẽ trả về trong vài giây.

Hàm fetch tích hợp sẵn của Node ngừng chờ header phản hồi sau 300 giây, bất kể bạn đặt thời gian chờ là bao nhiêu: khi gọi từ Node, hãy dùng API bất đồng bộ, hoặc gọi hàm fetch từ gói undici với tùy chọn dispatcher: new Agent({ headersTimeout: 600_000 }).

Tham số

Tham sốLoạiGhi chú
modelstring (bắt buộc)Slug model nhạc — suno-v5 hoặc suno-v5-5.
promptstring (bắt buộc)Mô tả nhạc (hoặc lời bài hát ở chế độ tùy chỉnh).
instrumentalbooltrue = không có giọng hát. Mặc định là false.
customModeboolChế độ Suno nâng cao — điều khiển rõ ràng cấu trúc / lời bài hát / phong cách.
stylestringGợi ý phong cách / thể loại, ví dụ "lofi, jazz, chill".
titlestringTiêu đề bản nhạc.
webhook_urlstring (https)Chỉ dành cho API bất đồng bộ — gửi sự kiện kết thúc có chữ ký đến đây. Xem Webhooks.

Model nhạc

SlugNhà cung cấpGhi chú
suno-v5SunoSuno V5 — giọng hát, lời bài hát, pha trộn phong cách.
suno-v5-5SunoSuno V5.5 — phiên bản mới nhất, độ trung thực cao hơn và thời lượng tạo dài hơn.

Kiểm tra /models để xem danh sách hiện hành và giá cho từng lệnh gọi.

API bất đồng bộ (gửi yêu cầu + thăm dò)

Các điểm cuối: POST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id}. Cách hoạt động tương tự API video bất đồng bộ, nên cùng một mã thăm dò / webhook dùng được cho cả hai loại nội dung.

Điểm cuối đồng bộ giữ kết nối HTTP mở trong nhiều phút — tiện cho tập lệnh nhưng không đáng tin cậy trên mạng di động. Cặp API bất đồng bộ trả về ngay một ID msc_*; bạn thăm dò GET /v1/audio/music/jobs/{id} cho đến khi status là completed hoặc failed. Cùng model, cùng mức giá, cùng URL CDN vĩnh viễn.

import os
import time

import requests

API_KEY = os.environ["KUNAVO_API_KEY"]

# 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: a repeat under the same key returns the original task
        # rather than submitting again. A new task needs a new key.
        "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"])

Cấu trúc phản hồi

TrườngLoạiGhi chú
idstringID tác vụ có tiền tố msc_.
objectstring"music".
statusstringđang chờ | đang xử lý | đã hoàn tất | thất bại.
modelstringSlug model bạn đã gửi.
created_atintThời điểm Unix tính bằng giây khi chúng tôi chấp nhận yêu cầu.
completed_atint | nullThời điểm Unix tính bằng giây khi tác vụ kết thúc — null khi đang chờ.
expires_atintGiây Unix, 30 ngày sau khi gửi: có thể truy vấn tác vụ ít nhất cho đến lúc đó. URL kết quả của tác vụ không hết hạn.
progressintBằng 0 cho đến khi tác vụ kết thúc, sau đó là 100.
outputobject | null{tracks[], archived} khi hoàn tất.
output.tracksarrayMỗi mục: {url, stream_url, image_url}. url / image_url là các liên kết CDN vĩnh viễn.
errorobject | null{code, message} khi thất bại.

Tiêu đề và quy ước

  • Idempotency-Key (không bắt buộc, ≤128 ký tự) — gửi hai lần cùng khóa trên một tài khoản sẽ trả về tác vụ ban đầu thay vì tạo tác vụ trùng lặp.
  • Một khóa idempotency ứng với một yêu cầu: khóa đã được dùng để bắt đầu một tác vụ trên endpoint khác, cho model khác, hoặc cho một yêu cầu có prompt khác hay tham số khác sẽ bị từ chối với lỗi 400. Khóa dài hơn 128 ký tự và khóa được gửi kèm một yêu cầu đồng bộ cũng vậy. URL hình ảnh không được so sánh: yêu cầu dùng URL được ký lại vẫn là cùng một yêu cầu.
  • POST /v1/audio/music/jobs trả về 202 Accepted khi gửi tác vụ mới và 200 OK khi khóa idempotency phát lại một kết quả.
  • GET được giới hạn theo chủ sở hữu: truy vấn tác vụ thuộc tài khoản khác sẽ trả về 404.
  • Nhịp thăm dò được khuyến nghị: 5 s, tăng dần đến 30 s.

Webhook

Gửi webhook_url (https) khi tạo tác vụ; ngay khi tác vụ kết thúc, Kunavo sẽ POST sự kiện music.completed / music.failed có chữ ký đến đó — gửi kèm cơ chế thử lại với thời gian chờ tăng dần. Trường data của sự kiện chính xác là nội dung phản hồi GET ở trên.

# 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

# secret: your account's webhook secret ("kwh_..."), from Settings → Webhooks
# in the dashboard. Keep it out of your code: read it from the environment.
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... } }

Nếu webhook_url không phải là URL https, hoặc có chứa tên người dùng hay mật khẩu, yêu cầu sẽ bị từ chối với lỗi 400, và không có gì được tạo ra hay bị tính phí.

Khóa bí mật webhook của bạn nằm trong bảng điều khiển, tại Cài đặt → Webhooks. Khóa này bắt đầu bằng kwh_, và cùng một khóa bí mật được dùng để ký mọi sự kiện hình ảnh, video và nhạc của tài khoản bạn. Bạn có thể thay khóa tại đó; mọi sự kiện được gửi sau khi thay khóa, kể cả các lần thử lại, đều được ký bằng khóa bí mật mới.

Chữ ký là HMAC-SHA256 trên {timestamp}.{rawBody}, được gửi dưới dạng X-Kunavo-Webhook-Signature: sha256=<hex>. Cách làm giống webhook video, nên một bộ xác minh xử lý được cả hai.

Khi nào nên dùng model nào

Đồng bộ /v1/audio/musicBất đồng bộ /v1/audio/music/jobs
Phù hợp nhất choTập lệnh dùng một lần, notebookProduction, ứng dụng di động, webhook
MạngGiữ kết nối mở trong 1-3 phútGửi trong vài giây; thăm dò hoặc nhận dữ liệu được đẩy về
Khôi phục sau sự cốMất phản hồi = mất kết quảTruy vấn lại ID bất kỳ lúc nào trước khi expires_at hết hạn
Webhook—Sự kiện music.completed / music.failed có chữ ký

Phản hồi và lưu trữ

url (âm thanh) và image_url (ảnh bìa) của mỗi bản nhạc là các liên kết vĩnh viễn files.kunavo.com — Kunavo lưu trữ mọi kết quả trên CDN riêng, nên khác với URL Suno gốc, chúng không bao giờ hết hạn. stream_url là liên kết phát trực tuyến gốc của Suno (tiện để phát ngay). Mỗi bản nhạc cũng xuất hiện trong /app/assets.

Nếu việc lưu trữ thất bại, output.archived sẽ là false và URL sẽ chuyển về các liên kết tạm thời của Suno (hết hạn sau khoảng 24h) — trong trường hợp đó, hãy tự lưu trữ lại.

Tiếp theo nên xem gì