音乐生成
用 Mureka 生成歌曲、纯音乐与配乐,并分析已有音频——歌词识别、音频描述与音轨分离。
Music API 将文本、歌词、图片或参考音频转化为音乐,并分析已有曲目。生成能力由 Mureka 提供。所有端点位于 https://api.marswave.ai/openapi/v1/music 下,使用 Authorization: Bearer $LISTENHUB_API_KEY 鉴权。
接口分为两种响应模式:
| 模式 | 端点 | 结果如何返回 |
|---|---|---|
| 异步生成 | /generate、/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 读取字段。
模型
生成端点接受 model 参数,采用 provider-neutral 合同。Mureka 模型:
| 模型 | 说明 |
|---|---|
auto | 默认。由服务自动选择模型。 |
mureka-7.6 | |
mureka-8 | |
mureka-9 | /instrumental 不支持。 |
mureka-o2 |
音轨分离 /stem 使用另一套模型:audio-separation-1(默认)或 audio-separation-2(额外产出 MIDI)。
异步任务生命周期
- 提交生成请求,响应携带
taskId,初始status为pending。 - 轮询
GET /v1/music/tasks/{taskId},status依次经过pending→generating→uploading→success。 - 成功后读取
tracks数组(标题、标签、时长、签名audioUrl);失败则读取errorMessage。
推荐轮询节奏:提交后约 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.ai/.../track-1.mp3"
}
],
"creditCost": 20,
"createdAt": 1730000000000,
"updatedAt": 1730000180000
}
}音轨的 audioUrl 是签名 URL,在任务被获取后约 1 小时失效。请在过期前下载音频,或重新获取任务以刷新 URL。
从文本或歌词生成
POST /v1/music/generate
根据风格提示词和/或歌词生成歌曲。发送 JSON。对 Mureka,非纯器乐请求应包含 lyrics。
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 | 否 | 风格/描述提示词 |
lyrics | string | 否 | 歌词。Mureka 非纯器乐时必填 |
style | string | 否 | 风格标签。作为 prompt 的 fallback |
title | string | 否 | 歌曲标题 |
instrumental | boolean | 否 | 生成纯器乐(无人声) |
model | string | 否 | 见模型。默认 auto |
vocalId | string | 否 | 复用的 Mureka vocal id |
provider | string | 否 | default(Mureka)、mureka 或 suno。默认 default |
providerParams | object | 否 | Provider 特有参数 |
返回 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/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 | 否 | 见模型 |
extendAt | number | 否 | 延伸的起始时间偏移(秒,8–420) |
extendType | string | 否 | tail(向后,默认)或 head(向前,仅 mureka-8) |
lyrics | string | 否 | 新增段落的歌词 |
prompt | string | 否 | 风格/描述 |
style | string | 否 | 音乐风格 |
title | string | 否 | 歌曲标题 |
instrumental | boolean | 否 | 新增段落生成纯器乐(无人声) |
/extend 也支持 Suno 路径,使用 continueAt、uploadUrl 与 Suno 模型版本。传入 provider=suno 与 Suno 专属字段即可。默认 provider 为 Mureka。
识别歌词
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.length} 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},
)
print(len(response.json()['data']), 'tasks')查询参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
page | integer | 否 | 页码,最小 1。默认 1 |
pageSize | integer | 否 | 每页数量,1–100。默认 20 |
status | string | 否 | 按 pending、generating、uploading、success 或 failed 过滤 |
查询单个任务
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 | default、mureka 或 suno |
taskType | string | GENERATE、INSTRUMENTAL、REMIX、EXTEND、COVER |
status | string | pending、generating、uploading、success、failed |
params | object | 生成请求参数的回显 |
tracks | array | 完成的音轨:title、tags、duration(秒)、签名 audioUrl |
creditCost | number | 消耗积分 |
errorMessage | string | 失败原因(仅 status 为 failed 时返回) |
createdAt | number | 创建时间(毫秒时间戳) |
updatedAt | number | 更新时间(毫秒时间戳) |
积分
各端点按模型档位扣费。异步生成在提交时预占积分,成功时确认扣除,失败自动退回。每个任务的实际消耗通过 creditCost 返回(分析类调用在结果中同样返回 creditCost)。用 GET /v1/user/subscription 查询实时余额,并参见定价了解积分与功能的对应关系。
SDK 与 CLI
官方 SDK 与 CLI 封装了本页所有端点,包含异步轮询。
JavaScript SDK
OpenAPIClient.createMusicGenerate / 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 控制轮询。