歌词生成
用 Mureka 或 Suno 把一句提示词写成完整歌词,再从任务中读取生成结果。
Lyrics API 把一句提示词写成完整歌词。它与 Music API 使用同样两个 provider——Mureka 与 Suno——通过 provider 字段逐请求选择。所有端点位于 https://api.marswave.ai/openapi/v1/lyrics 下,使用 Authorization: Bearer $LISTENHUB_API_KEY 鉴权。
生成一律走任务。POST /v1/lyrics/generate 返回 taskId 和状态,不返回歌词本身;歌词从 GET /v1/lyrics/tasks/{taskId} 读取。
所有响应都包在 { "code": 0, "message": "", "data": { ... } } 里。code 非 0 即为错误——见错误处理。下面的示例都从 data 取字段。
Provider
provider 取 mureka、suno 或 default(解析为 Mureka)。选谁不改变请求结构,只影响任务多久进入终态,以及返回几条歌词版本。
| Provider | 运行方式 | 创建响应里的 status | 歌词版本数 |
|---|---|---|---|
mureka | 同步。创建请求会等上游出结果。 | success,已是终态 | 1 条 |
suno | 回调式。上游生成完成后回调通知。 | pending | 通常 2 条 |
default | 解析为服务默认 provider,即 Mureka。 | 同 mureka | 1 条 |
不传 provider 等同于传 default。任务始终记录实际执行它的 provider,所以用 default 创建的任务读回来是 mureka。
任务生命周期
status 依次为 pending → generating → success 或 failed。两个 provider 共用这套状态机,区别只在任务停留在非终态的时长。
POST /v1/lyrics/generate返回202,带taskId和初始status。- Mureka 的初始状态已是
success——取一次任务即可读到歌词。Suno 是pending——每隔几秒轮询GET /v1/lyrics/tasks/{taskId}。 success时读variants;failed时读errorMessage。
Suno 没有歌词查询端点,回调是任务走到 success 的唯一路径。Suno 任务若 30 分钟没有任何更新,会被置为 failed 并全额退还积分,此后不再恢复。
生成歌词
POST /v1/lyrics/generate
用提示词创建歌词任务。发送 JSON。
curl -X POST "https://api.marswave.ai/openapi/v1/lyrics/generate" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A hopeful anthem about leaving a small town at dawn",
"provider": "suno"
}'const response = await fetch(
'https://api.marswave.ai/openapi/v1/lyrics/generate',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
prompt: 'A hopeful anthem about leaving a small town at dawn',
provider: 'suno',
}),
}
);
const { data } = await response.json();
console.log('Task:', data.taskId, data.status);import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/lyrics/generate',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'prompt': 'A hopeful anthem about leaving a small town at dawn',
'provider': 'suno',
},
)
data = response.json()['data']
print('Task:', data['taskId'], data['status'])请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
prompt | string | 是 | 歌词要写什么。最多 200 字符——超长在参数校验阶段就被拒绝,不会预扣积分 |
provider | string | 否 | mureka、suno 或 default。默认 default,解析为 Mureka |
响应示例:
{
"code": 0,
"message": "",
"data": {
"taskId": "68e780390fc5c9a54f695a7e",
"status": "pending"
}
}两个 provider 的创建响应都只有 taskId 和 status,不含歌词——Mureka 即便任务已是 success 也一样。歌词需要取任务后从 variants 读。
该端点计入请求限制中的创建请求频率。
查询任务列表
GET /v1/lyrics/tasks
按创建时间倒序列出你的歌词任务。
curl -X GET "https://api.marswave.ai/openapi/v1/lyrics/tasks?page=1&pageSize=20&status=success" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
'https://api.marswave.ai/openapi/v1/lyrics/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/lyrics/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、success、failed 过滤 |
data 装的是一页数据,不是裸数组:items 是任务列表(结构见查询单个任务),另有 page、pageSize、total。
查询单个任务
GET /v1/lyrics/tasks/{taskId}
查询单个任务。提交给 Suno 后轮询的就是它;两个 provider 的歌词也都从它读取。
curl -X GET "https://api.marswave.ai/openapi/v1/lyrics/tasks/{taskId}" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
`https://api.marswave.ai/openapi/v1/lyrics/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(data.variants[0].text);import os
import requests
response = requests.get(
f'https://api.marswave.ai/openapi/v1/lyrics/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(data['variants'][0]['text'])响应示例:
{
"code": 0,
"message": "",
"data": {
"id": "68e780390fc5c9a54f695a7e",
"provider": "suno",
"status": "success",
"params": {
"prompt": "A hopeful anthem about leaving a small town at dawn"
},
"variants": [
{
"title": "Dawn Highway",
"text": "Suitcase on the porch light\nEngine turning over slow\n...",
"status": "complete",
"errorMessage": ""
},
{
"title": "First Light Out",
"text": "The bus stop hums awake\nI count the streetlamps one last time\n...",
"status": "complete",
"errorMessage": ""
}
],
"creditCost": 2,
"errorMessage": "",
"createdAt": 1730000000000,
"updatedAt": 1730000021000
}
}任务响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 任务 ID |
provider | string | 实际执行任务的 provider:mureka 或 suno |
status | string | pending、generating、success、failed |
params.prompt | string | 提交时的提示词回显 |
variants | array | 生成的歌词。任务成功前为空 |
variants[].title | string | 建议的歌曲标题 |
variants[].text | string | 生成的歌词正文 |
variants[].status | string | complete 或 failed。成功的任务里仍可能有失败的单条版本 |
variants[].errorMessage | string | 该条失败的原因,否则为空 |
creditCost | number | 实扣积分。任务成功前恒为 0 |
errorMessage | string | 失败原因(仅 status 为 failed 时) |
createdAt | number | 创建时间(毫秒时间戳) |
updatedAt | number | 最后更新时间(毫秒时间戳) |
任务按所属账号隔离:查询不属于自己的任务返回错误,而不是任务内容。
积分
歌词生成固定消耗 2 积分每次请求——两个 provider 一致,也与返回几条版本无关。
积分在创建任务时预扣,任务成功时确认扣除。上游拒绝请求、任务失败、以及 Suno 任务超时这三种情况都全额退还。因此未走到 success 的任务不产生费用,其 creditCost 保持 0。
实时余额用 GET /v1/user/subscription 查询,完整积分说明见积分与定价。
SDK 与 CLI
在 API key 这条路径上,Lyrics API 目前只能直接走 HTTP:OpenAPIClient SDK 和 listenhub openapi CLI 都还没有封装这几个端点。listenhub lyrics 命令与 ListenHubClient 的歌词方法调用的是同一批端点,但走的是账号登录鉴权,不是 API key。