音频处理
Suno 音乐生成
统一任务接口下的 32 个音乐动作:出歌、续写、翻唱、分轨、编辑、导出
POST
/
v1
/
tasks
Suno 音乐生成
curl --request POST \
--url https://api.qingbo.ai/v1/tasks \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"action": "<string>",
"prompt": "<string>",
"audio_urls": [
"<string>"
],
"callback_url": "<string>",
"ref_task_id": "<string>",
"audio_index": 123
}
'import requests
url = "https://api.qingbo.ai/v1/tasks"
payload = {
"model": "<string>",
"action": "<string>",
"prompt": "<string>",
"audio_urls": ["<string>"],
"callback_url": "<string>",
"ref_task_id": "<string>",
"audio_index": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
action: '<string>',
prompt: '<string>',
audio_urls: ['<string>'],
callback_url: '<string>',
ref_task_id: '<string>',
audio_index: 123
})
};
fetch('https://api.qingbo.ai/v1/tasks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.qingbo.ai/v1/tasks"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"action\": \"<string>\",\n \"prompt\": \"<string>\",\n \"audio_urls\": [\n \"<string>\"\n ],\n \"callback_url\": \"<string>\",\n \"ref_task_id\": \"<string>\",\n \"audio_index\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.qingbo.ai/v1/tasks")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"action\": \"<string>\",\n \"prompt\": \"<string>\",\n \"audio_urls\": [\n \"<string>\"\n ],\n \"callback_url\": \"<string>\",\n \"ref_task_id\": \"<string>\",\n \"audio_index\": 123\n}")
.asString();suno 是一个动作型模型:模型 ID 固定,action 字段决定这次做什么。从零出歌用 generate,拿到 task_id 之后可以在同一首歌上继续续写、翻唱、分轨、编辑和导出,一共 32 个动作。所有动作都通过统一任务接口 POST /v1/tasks 提交。
快速开始
curl -X POST https://api.qingbo.ai/v1/tasks \
-H "Authorization: Bearer $WAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno",
"action": "generate",
"prompt": "一首温柔的城市民谣,雨夜,女声,吉他与钢琴",
"version": "v5.5"
}'
curl -X POST https://api.qingbo.ai/v1/tasks \
-H "Authorization: Bearer $WAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno",
"action": "generate",
"custom": true,
"prompt": "[Verse]\n路灯把雨丝照成金线\n我把伞留给了昨天",
"title": "雨夜城南",
"style": "indie folk, female vocal, acoustic guitar",
"vocal_gender": "Female",
"version": "v5.5"
}'
curl -X POST https://api.qingbo.ai/v1/tasks \
-H "Authorization: Bearer $WAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno",
"action": "generate",
"prompt": "轻快的 lo-fi 学习背景音乐",
"instrumental": true
}'
curl -X POST https://api.qingbo.ai/v1/tasks \
-H "Authorization: Bearer $WAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno",
"action": "lyrics",
"prompt": "一首关于灯塔与耐心的歌"
}'
task_id。用 GET /v1/tasks/{task_id} 查询结果,也可以用 Prefer: wait 在一次调用里等待,或配置 Webhook。
请求参数
动作
从零创作——不引用已有音轨。| 动作 | 说明 |
|---|---|
generate | 生成一首完整歌曲:灵感模式给一句描述,自定义模式给歌词 |
inspo | 以参考音频为灵感生成新歌,用 audio_urls 传 1–4 条参考音频 |
lyrics | 只生成歌词文本,不出曲 |
sounds | 生成音效,可指定类型、BPM 与调性 |
upsample_tags | 把粗略的风格描述扩写成更完整的风格标签 |
upload | 导入一段自有音频,完成后可作为源音轨被后续动作引用 |
ref_task_id 指定源音轨。
| 动作 | 说明 |
|---|---|
extend | 从源音轨第 continue_at 秒开始续写 |
cover | 换一种风格重新演绎 |
remaster | 母带优化,提升音质与整体质感 |
sample | 取 start_s–end_s 一段作样本,发展成新曲 |
replace_section | 替换 start_s–end_s 这一段,可用 infill_lyrics 指定新词 |
mashup | 把歌曲混搭再创作 |
concat | 把片段合成为完整曲目 |
midi | 从歌曲生成 MIDI |
| 动作 | 说明 |
|---|---|
stems | 分离出指定的一条音轨,用 stem_type 选择 |
stems_all | 一次分离出全部音轨 |
add_vocals | 给伴奏叠加人声;源音轨需为 upload 导入的音频 |
add_instrumental | 给人声叠加伴奏;源音轨需为 upload 导入的音频 |
add_stem | 在源音轨上叠加一条新音轨 |
vox | 提取 vocal_start_s–vocal_end_s 之间的人声片段 |
create_voice | 用 audio_url 指向的音频创建可复用音色 |
persona | 创建歌手 Persona,之后用 persona_id 复用同一把嗓音 |
| 动作 | 说明 |
|---|---|
crop | 裁剪并保留 start_s–end_s |
remove_section | 删除 start_s–end_s |
fade_in / fade_out | 开头淡入 / 结尾淡出,时长 duration_s 秒 |
adjust_speed | 按 speed 变速,keep_pitch 可保持音高 |
| 动作 | 说明 |
|---|---|
wav | 把源音轨导出为 WAV 文件 |
download | 把源音轨导出为音频文件,用 formats 指定格式 |
generate_video | 为歌曲生成 MV 视频 |
aligned_lyrics | 输出逐句对齐的歌词时间轴 |
bpm | 分析歌曲 BPM |
通用参数
string
必填
固定为
suno。string
默认值:"generate"
这次要做什么,取值见「动作」。
string
灵感模式下是内容描述;
custom: true 时是歌词正文;lyrics 与 sounds 动作下是主题描述。string[]
参考音频 URL 数组,需公网可访问。只有
inspo 动作接受,且必填,可传 1–4 条。创作参数
下列参数适用于创作类动作:generate、inspo、extend、cover、remaster、mashup、sample、replace_section、add_vocals、add_instrumental、add_stem、sounds。适用范围更窄的参数写在说明里。
| 参数 | 类型 | 说明 |
|---|---|---|
version | string | v3.5、v4、v4.5、v4.5+、v4.5-all、v5、v5.5,默认 v5.5。影响音质 |
custom | boolean | 默认 false,prompt 当描述;true 时 prompt 当歌词 |
title | string | 歌曲标题。另可用于 fade_in、fade_out、adjust_speed |
style | string | 风格标签,仅 generate |
tags | string | 风格标签,用于 extend、cover、inspo、mashup、sample、add_vocals、add_instrumental、add_stem、replace_section、upsample_tags |
negative_tags | string | 需要避开的风格 |
instrumental | boolean | 纯音乐,无人声。仅 generate、mashup、sample,默认 false |
gpt_description | string | 灵感提示词,custom: false 时必填。用于 extend、cover、mashup、sample、add_vocals、add_instrumental、add_stem |
auto_lyrics | boolean | 自动写词。用于 generate、extend、cover、inspo、mashup、sample |
persona_id | string | 复用 persona 动作创建的嗓音。用于 generate、extend、cover、mashup |
vocal_gender | string | Male 或 Female |
style_weight | number | 0–1,风格权重 |
weirdness_constraint | number | 0–1,创意度 |
audio_weight | number | 0–1,音频权重 |
style 与 tags 是同一个概念的两个字段名:generate 用 style,其余动作用 tags。引用源音轨
string
产出源音轨的那次任务的
task_id。integer
默认值:"1"
取源任务结果里的第几首,从
1 开始。create_voice 用 audio_url 指向一段公网音频,upload 用 audioFilePath 指定要导入的音频文件。
动作专属参数
| 参数 | 类型 | 适用动作 | 说明 |
|---|---|---|---|
continue_at | integer | extend | 从源音轨第几秒开始续写。必填 |
start_s / end_s | number | crop、remove_section、replace_section、sample | 区间起止秒。必填 |
duration_s | integer | fade_in、fade_out | 淡入 / 淡出时长,最小 1 秒。必填 |
speed | number | adjust_speed | 变速倍率。必填 |
keep_pitch | boolean | adjust_speed | 变速时保持音高 |
stem_type | string | stems | 提取哪一条音轨,默认 lead_vocal |
infill_lyrics | string | replace_section | 替换段落填入的歌词 |
variation_category | string | remaster | 母带优化的变体方向 |
type | string | sounds | 音效类型 |
bpm | integer | sounds | 目标 BPM |
key | string | sounds | 调性 |
lyrics_model | string | lyrics | 写词用的模型 |
formats | array | download | 下载格式数组,例如 ["mp3","wav"];可选值 mp3 / m4a / wav,至少一项。必填 |
audio_url | string | create_voice | 用来创建音色的音频 URL。必填 |
audioFilePath | string | upload | 要导入的音频文件路径。必填 |
name | string | persona | Persona 名称。必填 |
describe | string | persona | Persona 描述 |
styles | string | persona | Persona 风格 |
vox_audio_id | string | persona | 取哪段人声创建 Persona |
vocal_start_s / vocal_end_s | integer | vox、persona | 人声片段起止秒 |
400,不计费。
限制
本模型一次任务只产出一个结果,不支持用n 批量生成。
inspo 动作需要 1 至 4 条参考音频 URL。
| 动作 | 必填参数 |
|---|---|
inspo | audio_urls |
extend | continue_at |
crop、remove_section、replace_section、sample | start_s 与 end_s |
fade_in、fade_out | duration_s |
adjust_speed | speed |
create_voice | audio_url |
upload | audioFilePath |
persona | name |
download | formats |
计费
按次计费,不同动作价格不同:每个动作有自己的固定单价,同一动作不因version、时长或提示词长度改变价格。完整生成类动作(generate、extend、cover、remaster 等)和多轨分离(stems_all)单价较高,lyrics、bpm、wav 这类轻量动作低得多。
单价见 GET /v1/models 返回的 price_config.audio_prices(按动作分键),或控制台「模型市场」。单次调用的实际花费见任务响应里的 cost——整数 quota,500,000 quota = 1 USD,不是美元。
只有成功产出结果才计费。任务失败、取消,或没有返回可交付结果时,全额退款。
响应
{
"task_id": "task-wave1789004688b950049238",
"model": "suno",
"action": "generate",
"status": "completed",
"progress": "100%",
"created_at": 1788768570,
"completed_at": 1788768689,
"result": {
"audios": [
{
"expires_at": 1789089508,
"url": ["https://cdn.example.com/result.mp3"]
},
{
"expires_at": 1789089508,
"url": ["https://cdn.example.com/result.mp3"]
}
]
},
"urls": {
"get": "https://api.qingbo.ai/v1/tasks/task-wave1789004688b950049238",
"cancel": "https://api.qingbo.ai/v1/tasks/task-wave1789004688b950049238/cancel"
},
"billing_status": "settled",
"cost": 28125
}
{
"task_id": "task-wave1789004688b950049238",
"model": "suno",
"action": "lyrics",
"status": "completed",
"progress": "100%",
"created_at": 1788769423,
"completed_at": 1788769434,
"result": {
"audios": {
"lyrics": [
{
"prompt": "[Verse]\nStone tower stands so tall\n...",
"tags": "[\"acoustic, melancholic, male vocals\"]",
"title": "The Beacon's Call"
}
]
}
},
"urls": {
"get": "https://api.qingbo.ai/v1/tasks/task-wave1789004688b950049238",
"cancel": "https://api.qingbo.ai/v1/tasks/task-wave1789004688b950049238/cancel"
},
"billing_status": "settled",
"cost": 4500
}
result.audios[]:url 是音频地址数组,expires_at 是链接过期时间。generate 一次返回两首候选,后续动作用 audio_index 选 1 或 2。
lyrics 动作不产出音频:歌词文本在 result.audios.lyrics[] 的 prompt 字段里,同一元素还带 title 与 tags。
使用示例
在同一首歌上接着往下做:先generate 拿到 task_id,再把它作为 ref_task_id 传给后续动作;后续动作各自又会产出新的 task_id,可以继续往下接。
curl -X POST https://api.qingbo.ai/v1/tasks \
-H "Authorization: Bearer $WAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno",
"action": "extend",
"ref_task_id": "task-wave1789004688b950049238",
"audio_index": 1,
"continue_at": 118
}'
curl -X POST https://api.qingbo.ai/v1/tasks \
-H "Authorization: Bearer $WAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno",
"action": "cover",
"ref_task_id": "task-wave1789004688b950049238",
"audio_index": 1,
"tags": "city pop, 80s synth, male vocal"
}'
curl -X POST https://api.qingbo.ai/v1/tasks \
-H "Authorization: Bearer $WAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno",
"action": "stems",
"ref_task_id": "task-wave1789004688b950049238",
"audio_index": 1,
"stem_type": "lead_vocal"
}'
curl -X POST https://api.qingbo.ai/v1/tasks \
-H "Authorization: Bearer $WAVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno",
"action": "wav",
"ref_task_id": "task-wave1789004688b950049238",
"audio_index": 1
}'
相关文档
⌘I
Suno 音乐生成
curl --request POST \
--url https://api.qingbo.ai/v1/tasks \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"action": "<string>",
"prompt": "<string>",
"audio_urls": [
"<string>"
],
"callback_url": "<string>",
"ref_task_id": "<string>",
"audio_index": 123
}
'import requests
url = "https://api.qingbo.ai/v1/tasks"
payload = {
"model": "<string>",
"action": "<string>",
"prompt": "<string>",
"audio_urls": ["<string>"],
"callback_url": "<string>",
"ref_task_id": "<string>",
"audio_index": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
action: '<string>',
prompt: '<string>',
audio_urls: ['<string>'],
callback_url: '<string>',
ref_task_id: '<string>',
audio_index: 123
})
};
fetch('https://api.qingbo.ai/v1/tasks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.qingbo.ai/v1/tasks"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"action\": \"<string>\",\n \"prompt\": \"<string>\",\n \"audio_urls\": [\n \"<string>\"\n ],\n \"callback_url\": \"<string>\",\n \"ref_task_id\": \"<string>\",\n \"audio_index\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.qingbo.ai/v1/tasks")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"action\": \"<string>\",\n \"prompt\": \"<string>\",\n \"audio_urls\": [\n \"<string>\"\n ],\n \"callback_url\": \"<string>\",\n \"ref_task_id\": \"<string>\",\n \"audio_index\": 123\n}")
.asString();