音乐生成
用 Mureka 或 Suno 生成歌曲、纯音乐与配乐,并分析已有音频——歌词识别、音频描述与音轨分离。
Music API 将文本、歌词、图片或参考音频转化为音乐,并分析已有曲目。生成能力由 Mureka 与 Suno 两个 provider 提供,在同时支持两者的端点上通过 provider 字段逐请求选择。所有端点位于 https://api.marswave.ai/openapi/v1/music 下,使用 Authorization: Bearer $LISTENHUB_API_KEY 鉴权。
接口分为两种响应模式:
| 模式 | 端点 | 结果如何返回 |
|---|---|---|
| 异步生成 | /generate、/cover、/instrumental、/soundtrack、/track、/remix、/extend | 返回 202 与 taskId,轮询 GET /v1/music/tasks/{taskId} 直到 status 为 success。 |
| 同步分析 | /recognize、/describe、/stem | 返回 200,结果直接在同一响应中。无需轮询。 |
每个响应都包裹在 { "code": 0, "message": "", "data": { ... } } 中。code 非 0 表示错误——见错误处理。下文示例均从 data 读取字段。
Provider
provider 接受 mureka、suno 或 default,default 解析为 Mureka。只有两个端点读取该字段,其余端点固定由单一 provider 承载并忽略它。
| 端点 | Mureka | Suno | provider 选择 |
|---|---|---|---|
/generate | ✓ | ✓ | 由 provider 决定,默认 Mureka |
/extend | ✓ | ✓ | 由 provider 决定,默认 Mureka |
/cover | — | ✓ | 固定 Suno |
/instrumental | ✓ | — | 固定 Mureka |
/soundtrack | ✓ | — | 固定 Mureka |
/track | ✓ | — | 固定 Mureka |
/remix | ✓ | — | 固定 Mureka |
/recognize | ✓ | — | 固定 Mureka |
/describe | ✓ | — | 固定 Mureka |
/stem | ✓ | — | 固定 Mureka |
/remix 与 /cover 都是重新演绎已有录音,但不可互换:/remix 用新歌词重唱 Mureka 歌曲,/cover 通过 Suno 把上传的音频用新风格重录。
GET /v1/music/tasks 与 GET /v1/music/tasks/{taskId} 返回两个 provider 的任务,每个任务在 provider 字段中标明实际执行它的 provider。
模型
model 的取值范围由承载该请求的 provider 决定:Mureka 端点用 Mureka 模型名,Suno 端点用 Suno 档位。积分列适用于按档位计价的 /generate、/instrumental 与 /cover;/extend 走另一张表——mureka-7.6 与 auto(计价前先解析为 mureka-7.6)10 积分,其余模型(含全部 Suno 档位)15 积分——其余端点为固定价,列在积分。
Mureka 模型:
| 模型 | 积分 | 说明 |
|---|---|---|
auto | 10 | Mureka 默认值。由服务自动选择模型。 |
mureka-7.6 | 5 | |
mureka-8 | 10 | |
mureka-9 | 10 | /instrumental 不支持。 |
mureka-o2 | 10 |
Suno 模型:
| 模型 | 积分 | 说明 |
|---|---|---|
V4 | 15 | |
V4_5 | 15 | |
V4_5PLUS | 15 | |
V4_5ALL | 15 | |
V5 | 15 | |
V5_5 | 20 | |
V6 | 20 | Suno 默认值。最新档位。 |
全部档位都可显式指定。Suno 请求不传 model 时运行在 V6。
音轨分离 /stem 使用另一套模型:audio-separation-1(默认)或 audio-separation-2(额外产出 MIDI)。
Suno 专有参数
Suno 有七个 Mureka 没有对应项的参数。在 /generate 与 /cover 上它们放在 providerParams 内;在 /extend 上是顶层表单字段。
| 字段 | 类型 | 适用端点 | 说明 |
|---|---|---|---|
negativeTags | string | /generate、/cover、/extend | 需要规避的风格标签,逗号分隔 |
vocalGender | string | /generate、/cover、/extend | m 或 f。注意与 /track 不同,后者取 male / female |
styleWeight | number | /generate、/cover、/extend | 0–1。结果贴合 style 的程度 |
weirdnessConstraint | number | /generate、/cover、/extend | 0–1。结果允许偏离常规的程度 |
audioWeight | number | /generate、/cover、/extend | 0–1。源录音的权重,仅在请求带源音频时有意义 |
personaId | string | /generate、/cover | 演唱该曲目的 Suno persona。在 /cover 上仅 custom mode 生效 |
personaModel | string | /generate、/cover | 创建该 persona 时所用的档位,与 personaId 一起传 |
不在上表中的键会在请求到达 Suno 前从 providerParams 中丢弃。
异步任务生命周期
- 提交生成请求,响应携带
taskId,初始status为pending。 - 轮询
GET /v1/music/tasks/{taskId},status依次经过pending→generating→uploading→success。 - 成功后读取
tracks数组(标题、标签、时长、签名audioUrl);失败则读取errorMessage。params.model给出该任务实际运行的档位,也是creditCost的计价依据。
推荐轮询节奏:提交后约 30 秒再开始轮询,每 10 秒一次。音乐任务通常 1–3 分钟完成。
{
"code": 0,
"message": "",
"data": {
"id": "68e780390fc5c9a54f695a7e",
"provider": "mureka",
"taskType": "GENERATE",
"status": "success",
"params": {
"model": "auto",
"prompt": "r&b, slow, passionate, male vocal",
"instrumental": false
},
"tracks": [
{
"title": "Night Walk",
"tags": "r&b, slow",
"duration": 142.5,
"audioUrl": "https://assets.listenhub.app/.../track-1.mp3"
}
],
"creditCost": 10,
"createdAt": 1730000000000,
"updatedAt": 1730000180000
}
}音轨的 audioUrl 是签名 URL,在任务被获取后约 1 小时失效。请在过期前下载音频,或重新获取任务以刷新 URL。
从文本或歌词生成
POST /v1/music/generate
根据风格提示词和/或歌词生成歌曲。发送 JSON。不传 provider=suno 时由 Mureka 承载。Mureka 会拒绝不带 lyrics 的非纯器乐请求;Suno 则接受只带 lyrics 或只带 prompt 的请求。
curl -X POST "https://api.marswave.ai/openapi/v1/music/generate" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "r&b, slow, passionate, male vocal",
"lyrics": "[verse]\nWalking down the empty street at night\n[chorus]\nFeel the rhythm, feel the light",
"title": "Night Walk",
"model": "auto"
}'const response = await fetch('https://api.marswave.ai/openapi/v1/music/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
prompt: 'r&b, slow, passionate, male vocal',
lyrics: '[verse]\nWalking down the empty street at night\n[chorus]\nFeel the rhythm, feel the light',
title: 'Night Walk',
model: 'auto',
}),
});
const { data } = await response.json();
console.log('Task ID:', data.taskId);import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/generate',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'prompt': 'r&b, slow, passionate, male vocal',
'lyrics': '[verse]\nWalking down the empty street at night\n[chorus]\nFeel the rhythm, feel the light',
'title': 'Night Walk',
'model': 'auto',
},
)
data = response.json()['data']
print('Task ID:', data['taskId'])请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
prompt | string | 否 | Mureka 上是风格/描述提示词。Suno 把它当作歌词读取,因此建议改用 lyrics,风格走 style |
lyrics | string | 否 | 歌词。instrumental 不为 true 时 Mureka 必填。Suno 用它作为歌曲歌词 |
style | string | 否 | 风格标签。作为 prompt 的 fallback |
title | string | 否 | 歌曲标题 |
instrumental | boolean | 否 | 生成纯器乐(无人声) |
customMode | boolean | 否 | 仅 Suno。默认 true,此时 style 与 title 承载风格描述、歌词正文取自 lyrics;设为 false 则整首歌只由 prompt 驱动 |
model | string | 否 | 见模型。Mureka 默认 auto,Suno 默认 V6 |
vocalId | string | 否 | 复用的 Mureka vocal id,仅 Mureka 支持 |
provider | string | 否 | default(Mureka)、mureka 或 suno。默认 default |
providerParams | object | 否 | Provider 特有参数。Suno 见 Suno 专有参数 |
返回 202 与 { "taskId": "...", "status": "pending" }。轮询该任务以获取结果。
生成纯音乐
POST /v1/music/instrumental
通过文本提示词或参考音频生成纯音乐。prompt 与 referenceAudio 二选一。发送 multipart/form-data。
curl -X POST "https://api.marswave.ai/openapi/v1/music/instrumental" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-F "prompt=lofi hip hop, mellow, rainy night" \
-F "model=auto"const form = new FormData();
form.append('prompt', 'lofi hip hop, mellow, rainy night');
form.append('model', 'auto');
const response = await fetch('https://api.marswave.ai/openapi/v1/music/instrumental', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log('Task ID:', data.taskId);import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/instrumental',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
data={'prompt': 'lofi hip hop, mellow, rainy night', 'model': 'auto'},
)
data = response.json()['data']
print('Task ID:', data['taskId'])请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
prompt | string | 二选一 | 风格/流派描述。与 referenceAudio 互斥 |
referenceAudio | file | 二选一 | 参考音频(mp3/m4a,最大 10MB)。与 prompt 互斥 |
model | string | 否 | auto、mureka-7.6、mureka-8 或 mureka-o2。默认 auto |
由图片或视频生成配乐
POST /v1/music/soundtrack
生成与图片或视频匹配的音乐。image 与 video 二选一。发送 multipart/form-data。
curl -X POST "https://api.marswave.ai/openapi/v1/music/soundtrack" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-F "image=@scene.jpg" \
-F "prompt=cinematic, hopeful, orchestral" \
-F "model=auto"import { readFile } from 'node:fs/promises';
const form = new FormData();
form.append('image', new Blob([await readFile('scene.jpg')]), 'scene.jpg');
form.append('prompt', 'cinematic, hopeful, orchestral');
form.append('model', 'auto');
const response = await fetch('https://api.marswave.ai/openapi/v1/music/soundtrack', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log('Task ID:', data.taskId);import os
import requests
with open('scene.jpg', 'rb') as f:
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/soundtrack',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
files={'image': f},
data={'prompt': 'cinematic, hopeful, orchestral', 'model': 'auto'},
)
data = response.json()['data']
print('Task ID:', data['taskId'])请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
image | file | 二选一 | 图片(jpg/jpeg/png/webp)。与 video 互斥 |
video | file | 二选一 | 视频(mp4/mov/avi/mkv/webm)。与 image 互斥 |
prompt | string | 否 | 风格/描述提示词 |
model | string | 否 | auto、mureka-7.6、mureka-8、mureka-9 或 mureka-o2。默认 auto |
生成单条音轨
POST /v1/music/track
基于参考音频文件或已有的 Mureka providerSongId 生成单条乐器/人声音轨。audio 与 providerSongId 二选一。发送 multipart/form-data。
curl -X POST "https://api.marswave.ai/openapi/v1/music/track" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-F "audio=@reference.mp3" \
-F "generateType=Drums" \
-F "prompt=funk, tight groove, 110 bpm"import { readFile } from 'node:fs/promises';
const form = new FormData();
form.append('audio', new Blob([await readFile('reference.mp3')]), 'reference.mp3');
form.append('generateType', 'Drums');
form.append('prompt', 'funk, tight groove, 110 bpm');
const response = await fetch('https://api.marswave.ai/openapi/v1/music/track', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log('Task ID:', data.taskId);import os
import requests
with open('reference.mp3', 'rb') as f:
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/track',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
files={'audio': f},
data={'generateType': 'Drums', 'prompt': 'funk, tight groove, 110 bpm'},
)
data = response.json()['data']
print('Task ID:', data['taskId'])请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
generateType | string | 是 | 目标音轨类型,取值之一:Vocals、Instrumental、Drums、Bass、Guitar、Keyboard、Percussion、Strings、Synth、FX、Brass、Woodwinds |
prompt | string | 是 | 风格/流派描述 |
audio | file | 二选一 | 参考音频(mp3/m4a/wav,最大 10MB)。与 providerSongId 互斥 |
providerSongId | string | 二选一 | 来自之前结果的 Mureka song id。与 audio 互斥 |
lyrics | string | 为 Vocals 时 | 歌词。generateType 为 Vocals 时必填 |
vocalGender | string | 否 | male 或 female。仅 generateType=Vocals |
generateStart | number | 否 | 起始时间(秒) |
generateEnd | number | 否 | 结束时间(秒) |
Remix 已有歌曲
POST /v1/music/remix
用新歌词重新演绎已有歌曲。源音频三选一:上传的 audio 文件、内部 ListenHub audioUrl,或 Mureka providerSongId。发送 multipart/form-data。
curl -X POST "https://api.marswave.ai/openapi/v1/music/remix" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-F "audio=@original.mp3" \
-F "lyrics=[verse]\nA brand new story to tell" \
-F "prompt=upbeat pop, bright synths"import { readFile } from 'node:fs/promises';
const form = new FormData();
form.append('audio', new Blob([await readFile('original.mp3')]), 'original.mp3');
form.append('lyrics', '[verse]\nA brand new story to tell');
form.append('prompt', 'upbeat pop, bright synths');
const response = await fetch('https://api.marswave.ai/openapi/v1/music/remix', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log('Task ID:', data.taskId);import os
import requests
with open('original.mp3', 'rb') as f:
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/remix',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
files={'audio': f},
data={
'lyrics': '[verse]\nA brand new story to tell',
'prompt': 'upbeat pop, bright synths',
},
)
data = response.json()['data']
print('Task ID:', data['taskId'])请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
lyrics | string | 是 | 新歌词 |
prompt | string | 是 | 风格/流派描述 |
audio | file | 三选一 | 音频文件(mp3/m4a,最大 10MB) |
audioUrl | string | 三选一 | 内部 ListenHub 音频 URL(须归属当前用户或公开) |
providerSongId | string | 三选一 | 来自之前结果的 Mureka song id |
翻唱已有录音
POST /v1/music/cover
把上传的曲目用新风格重录,保留原旋律。仅 Suno 支持。发送 JSON。
curl -X POST "https://api.marswave.ai/openapi/v1/music/cover" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"uploadUrl": "https://example.com/original.mp3",
"style": "acoustic folk, fingerpicked guitar",
"title": "Night Walk (Acoustic)",
"prompt": "[verse]\nWalking down the empty street at night",
"model": "V6"
}'const response = await fetch('https://api.marswave.ai/openapi/v1/music/cover', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
uploadUrl: 'https://example.com/original.mp3',
style: 'acoustic folk, fingerpicked guitar',
title: 'Night Walk (Acoustic)',
prompt: '[verse]\nWalking down the empty street at night',
model: 'V6',
}),
});
const { data } = await response.json();
console.log('Task ID:', data.taskId);import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/cover',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'uploadUrl': 'https://example.com/original.mp3',
'style': 'acoustic folk, fingerpicked guitar',
'title': 'Night Walk (Acoustic)',
'prompt': '[verse]\nWalking down the empty street at night',
'model': 'V6',
},
)
data = response.json()['data']
print('Task ID:', data['taskId'])请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
uploadUrl | string | 是 | 源录音:公网可访问的 URL,或你自己的 ListenHub 资源 URL——后者会校验归属并签发短时下载链接 |
model | string | 否 | Suno 模型,见模型。默认 V6 |
customMode | boolean | 否 | 默认 true。设为 false 时仅用 prompt 驱动翻唱 |
prompt | string | custom mode 必填 | 新人声的歌词,customMode 为 true 且 instrumental 为 false 时必填。非 custom mode 下它是自由描述 |
style | string | custom mode 必填 | 音乐风格 |
title | string | custom mode 必填 | 歌曲标题 |
instrumental | boolean | 否 | 生成无人声的翻唱。默认 false |
providerParams | object | 否 | Suno 专有参数,见 Suno 专有参数 |
返回 202 与 { "taskId": "...", "status": "pending" }。按 Suno 模型档位计价,与 /generate 一致。
延伸歌曲
POST /v1/music/extend
从指定时间点继续延伸已有歌曲。发送 multipart/form-data。源音频通过 audio、uploadUrl 或 providerSongId 提供。
curl -X POST "https://api.marswave.ai/openapi/v1/music/extend" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-F "audio=@original.mp3" \
-F "model=mureka-8" \
-F "extendAt=30" \
-F "extendType=tail"import { readFile } from 'node:fs/promises';
const form = new FormData();
form.append('audio', new Blob([await readFile('original.mp3')]), 'original.mp3');
form.append('model', 'mureka-8');
form.append('extendAt', '30');
form.append('extendType', 'tail');
const response = await fetch('https://api.marswave.ai/openapi/v1/music/extend', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log('Task ID:', data.taskId);import os
import requests
with open('original.mp3', 'rb') as f:
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/extend',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
files={'audio': f},
data={'model': 'mureka-8', 'extendAt': '30', 'extendType': 'tail'},
)
data = response.json()['data']
print('Task ID:', data['taskId'])请求参数(Mureka 路径):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
audio | file | 三选一 | 音频文件(mp3/m4a,最大 10MB)。与 uploadUrl / providerSongId 互斥 |
uploadUrl | string | 三选一 | 音频 URL(任意可访问外链或内部 GCS URL) |
providerSongId | string | 三选一 | 来自之前结果的 Mureka song id |
model | string | 否 | Mureka 模型名,见模型。默认 auto,本端点会把它解析为 mureka-7.6 |
extendAt | number | 是 | 延伸的起始时间偏移,必须在 8–420 秒之间 |
extendType | string | 否 | tail(向后,默认)或 head(向前,仅 mureka-8) |
lyrics | string | 是 | 新增段落的歌词 |
prompt | string | 否 | 风格/描述 |
style | string | 否 | 音乐风格 |
title | string | 否 | 歌曲标题 |
instrumental | boolean | 否 | 新增段落生成纯器乐(无人声) |
请求参数(Suno 路径):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
provider | string | 是 | suno。不传则走 Mureka 路径 |
uploadUrl | string | 是 | 源录音:公网可访问的 URL,或你自己的 ListenHub 资源 URL |
continueAt | number | 是 | 从第几秒继续,必须大于 0 |
model | string | 否 | Suno 模型,见模型。默认 V6 |
prompt | string | 否 | 续写段落的歌词。instrumental 为 true 时忽略 |
style | string | 否 | 音乐风格 |
title | string | 否 | 歌曲标题 |
instrumental | boolean | 否 | 续写无人声段落 |
negativeTags | string | 否 | 见 Suno 专有参数 |
vocalGender | string | 否 | 见 Suno 专有参数 |
styleWeight | number | 否 | 见 Suno 专有参数 |
weirdnessConstraint | number | 否 | 见 Suno 专有参数 |
audioWeight | number | 否 | 见 Suno 专有参数 |
model 在预占积分之前先校验:不在模型两张表里的取值直接拒绝。显式传 provider 会把校验范围收窄到该 provider 的档位。
两条路径只共用 uploadUrl、prompt、style、title 与 instrumental。audio、providerSongId、extendAt、extendType、lyrics 仅 Mureka 可用;continueAt 仅 Suno 可用。
识别歌词
POST /v1/music/recognize
从音频文件转写带时间戳分段的歌词。同步——结果直接在响应中。发送 multipart/form-data。这是从录音里读出歌词;要用提示词写新歌词,见歌词生成。
curl -X POST "https://api.marswave.ai/openapi/v1/music/recognize" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-F "audio=@song.mp3"import { readFile } from 'node:fs/promises';
const form = new FormData();
form.append('audio', new Blob([await readFile('song.mp3')]), 'song.mp3');
const response = await fetch('https://api.marswave.ai/openapi/v1/music/recognize', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log('Sections:', data.result.lyricsSections.length);import os
import requests
with open('song.mp3', 'rb') as f:
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/recognize',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
files={'audio': f},
)
data = response.json()['data']
print('Sections:', len(data['result']['lyricsSections']))请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
audio | file | 是 | 音频文件(mp3/m4a,最大 10MB) |
data.result 对象包含 duration 与 lyricsSections 数组。
分析音频
POST /v1/music/describe
分析音频文件,返回描述以及标签、流派与乐器。同步。 发送 multipart/form-data。
curl -X POST "https://api.marswave.ai/openapi/v1/music/describe" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-F "audio=@song.mp3"import { readFile } from 'node:fs/promises';
const form = new FormData();
form.append('audio', new Blob([await readFile('song.mp3')]), 'song.mp3');
const response = await fetch('https://api.marswave.ai/openapi/v1/music/describe', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log(data.result.description, data.result.genres);import os
import requests
with open('song.mp3', 'rb') as f:
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/describe',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
files={'audio': f},
)
data = response.json()['data']
print(data['result']['description'], data['result']['genres'])请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
audio | file | 是 | 待分析音频文件(mp3/m4a,最大 10MB) |
data.result 对象包含 description、tags、genres 与 instruments。
分离音轨(stem)
POST /v1/music/stem
将音频文件分离为音轨(人声、贝斯、鼓、其他),返回下载 URL。同步。 发送 multipart/form-data。
curl -X POST "https://api.marswave.ai/openapi/v1/music/stem" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-F "audio=@song.mp3" \
-F "model=audio-separation-1"import { readFile } from 'node:fs/promises';
const form = new FormData();
form.append('audio', new Blob([await readFile('song.mp3')]), 'song.mp3');
form.append('model', 'audio-separation-1');
const response = await fetch('https://api.marswave.ai/openapi/v1/music/stem', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
body: form,
});
const { data } = await response.json();
console.log('Stems ZIP:', data.result.zipUrl);import os
import requests
with open('song.mp3', 'rb') as f:
response = requests.post(
'https://api.marswave.ai/openapi/v1/music/stem',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
files={'audio': f},
data={'model': 'audio-separation-1'},
)
data = response.json()['data']
print('Stems ZIP:', data['result']['zipUrl'])请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
audio | file | 是 | 待分离音频文件(mp3/m4a,最大 10MB) |
model | string | 否 | audio-separation-1(默认)或 audio-separation-2(额外产出 MIDI) |
data.result 对象包含 zipUrl、midiZipUrl(使用 audio-separation-2 时)与 expiresAt。下载链接在生成后约 24 小时失效。
查询任务列表
GET /v1/music/tasks
列出你的音乐任务,按创建时间倒序。
curl -X GET "https://api.marswave.ai/openapi/v1/music/tasks?page=1&pageSize=20&status=success" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
'https://api.marswave.ai/openapi/v1/music/tasks?page=1&pageSize=20',
{ headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` } }
);
const { data } = await response.json();
console.log(`${data.items.length} of ${data.total} tasks`);import os
import requests
response = requests.get(
'https://api.marswave.ai/openapi/v1/music/tasks',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
params={'page': 1, 'pageSize': 20},
)
data = response.json()['data']
print(len(data['items']), 'of', data['total'], 'tasks')查询参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
page | integer | 否 | 页码,最小 1。默认 1 |
pageSize | integer | 否 | 每页数量,1–100。默认 20 |
status | string | 否 | 按 pending、generating、uploading、success 或 failed 过滤 |
data 是一页而不是数组:items 是本页任务,total 是总数,page 与 pageSize 回显本次生效的取值。
查询单个任务
GET /v1/music/tasks/{taskId}
获取单个任务。这是提交异步生成请求后用于轮询的端点。
curl -X GET "https://api.marswave.ai/openapi/v1/music/tasks/{taskId}" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
`https://api.marswave.ai/openapi/v1/music/tasks/${taskId}`,
{ headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` } }
);
const { data } = await response.json();
console.log('Status:', data.status);
if (data.status === 'success') console.log('Audio:', data.tracks[0].audioUrl);import os
import requests
response = requests.get(
f'https://api.marswave.ai/openapi/v1/music/tasks/{task_id}',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
)
data = response.json()['data']
print('Status:', data['status'])
if data['status'] == 'success':
print('Audio:', data['tracks'][0]['audioUrl'])任务响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 任务 ID |
provider | string | mureka 或 suno。建单时已解析——任务不会存成 default |
taskType | string | GENERATE、INSTRUMENTAL、REMIX、EXTEND、COVER、SOUNDTRACK、TRACK、RECOGNIZE、DESCRIBE、STEM、REGION_EDIT |
status | string | pending、generating、uploading、success、failed |
params | object | 生成请求参数的回显,含 model——任务实际运行的档位 |
tracks | array | 完成的音轨:title、tags、duration(秒)、签名 audioUrl |
creditCost | number | 消耗积分 |
errorMessage | string | 失败原因(仅 status 为 failed 时返回) |
createdAt | number | 创建时间(毫秒时间戳) |
updatedAt | number | 更新时间(毫秒时间戳) |
积分
/generate、/instrumental 与 /cover 按模型档位计价,档位价见模型。其余端点为固定价:/remix 10,/extend 在 mureka-7.6 与 auto(解析为 mureka-7.6)上 10、其余模型 15,/soundtrack 15,/track 15,/describe 15,/recognize 3,/stem 在 audio-separation-1 上 10、audio-separation-2 上 100。
异步生成在提交时预占积分,成功时确认扣除,失败自动退回。每个任务的实际消耗通过 creditCost 返回(分析类调用在结果中同样返回 creditCost)。用 GET /v1/user/subscription 查询实时余额,并参见定价了解积分与功能的对应关系。
SDK 与 CLI
官方 SDK 与 CLI 封装了下列端点,包含异步轮询。两者目前都还不支持选择 provider 和传 Suno 专有参数——这两项请直接用 HTTP 调用。
JavaScript SDK
OpenAPIClient.createMusicGenerate / createMusicCover / createMusicInstrumental / createMusicSoundtrack / createMusicTrack / createMusicRemix,以及 recognizeMusic / describeMusic / stemMusic 和 getMusicTask / listMusicTasks。
CLI
listenhub openapi music generate | instrumental | soundtrack | track | remix | recognize | describe | stem | list | get——用 --no-wait 与 --timeout 控制轮询。