音楽生成
Mureka または Suno で楽曲、インストゥルメンタル、サウンドトラックを生成し、既存の音声を分析します——歌詞認識、音声の説明、ステム分離。
Music API はテキスト、歌詞、画像、参照音声を音楽に変換し、既存のトラックを分析します。生成機能は Mureka と Suno の 2 つのプロバイダーが担い、両方に対応するエンドポイントではリクエストごとに provider フィールドで選択します。すべてのエンドポイントは https://api.marswave.ai/openapi/v1/music 配下にあり、Authorization: Bearer $LISTENHUB_API_KEY で認証します。
この API は 2 つのレスポンスパターンに分かれます:
| パターン | エンドポイント | 結果の返り方 |
|---|---|---|
| 非同期生成 | /generate、/cover、/instrumental、/soundtrack、/track、/remix、/extend | 202 と taskId を返します。status が success になるまで GET /v1/music/tasks/{taskId} をポーリングします。 |
| 同期分析 | /recognize、/describe、/stem | 200 を返し、結果は同じレスポンスに含まれます。ポーリングは不要です。 |
すべてのレスポンスは { "code": 0, "message": "", "data": { ... } } の形にラップされます。code が 0 以外ならエラーです——エラーハンドリングを参照してください。以下の例はすべて data からフィールドを読み取ります。
プロバイダー
provider は mureka、suno、default を受け付けます。default は Mureka に解決されます。このフィールドを読むのは 2 つのエンドポイントだけで、残りは単一のプロバイダーが担当し、指定しても無視されます。
| エンドポイント | Mureka | Suno | プロバイダーの決まり方 |
|---|---|---|---|
/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 フィールドでわかります。
モデル
model の値はリクエストを担当するプロバイダーごとに決まります。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 のデフォルト。最新の階層です。 |
どの階層も明示的に指定できます。model を省いた Suno のリクエストは V6 で実行されます。
ステム分離(/stem)は別のモデルセットを使います:audio-separation-1(デフォルト)または audio-separation-2(MIDI も出力)。
Suno 固有のパラメータ
Suno には Mureka に対応するもののないパラメータが 7 つあります。/generate と /cover では providerParams の中に、/extend ではトップレベルのフォームフィールドとして指定します。
| フィールド | 型 | 対象エンドポイント | 説明 |
|---|---|---|---|
negativeTags | string | /generate、/cover、/extend | 避けたいスタイルタグ(カンマ区切り) |
vocalGender | string | /generate、/cover、/extend | m または f。male / female を取る /track とは異なる点に注意してください |
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 ではカスタムモードのみ有効です |
personaModel | string | /generate、/cover | その persona を作成したモデル階層。personaId と併せて指定します |
上記以外のキーは、リクエストが Suno に届く前に providerParams から取り除かれます。
非同期タスクのライフサイクル
- 生成リクエストを送信します。レスポンスには
taskIdと初期statusのpendingが含まれます。 GET /v1/music/tasks/{taskId}をポーリングします。statusはpending→generating→uploading→successと遷移します。successになったら、完成したtracks配列(タイトル、タグ、長さ、署名付きaudioUrl)を読み取ります。failedの場合は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 は署名付きで、タスクを取得してから約 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 のフォールバックとして使われます |
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 | いいえ | プロバイダー固有のパラメータ。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 から、楽器またはボーカルのトラックを 1 本生成します。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 | いいえ | 範囲の終了位置(秒) |
既存の楽曲をリミックスする
POST /v1/music/remix
既存の楽曲を新しい歌詞で歌い直させます。元音源は次のいずれか 1 つの方法で指定します:アップロードした 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 | 元音源のいずれか 1 つ | 音声ファイル(mp3/m4a、最大 10MB) |
audioUrl | string | 元音源のいずれか 1 つ | ListenHub 内部の音声 URL(自分のものか公開されている必要があります) |
providerSongId | string | 元音源のいずれか 1 つ | 過去の結果に含まれる 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 | カスタムモードでは必須 | 新しいボーカルの歌詞。customMode が true かつ instrumental が false のときは必須です。カスタムモード以外では自由記述の説明になります |
style | string | カスタムモードでは必須 | 音楽スタイル |
title | string | カスタムモードでは必須 | トラックのタイトル |
instrumental | boolean | いいえ | ボーカルなしでカバーを生成します。デフォルトは false |
providerParams | object | いいえ | Suno 固有のパラメータ。Suno 固有のパラメータを参照 |
202 と { "taskId": "...", "status": "pending" } を返します。/generate と同じく Suno のモデル階層で課金されます。
楽曲を延長する
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 | 元音源のいずれか 1 つ | 音声ファイル(mp3/m4a、最大 10MB)。uploadUrl / providerSongId とは排他です |
uploadUrl | string | 元音源のいずれか 1 つ | 音声の URL(到達可能な外部リンク、または内部の GCS URL) |
providerSongId | string | 元音源のいずれか 1 つ | 過去の結果に含まれる 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 はクレジットを予約する前に検証されます。モデルの 2 つの表にない値はその場で拒否されます。provider を明示すると、検証はその provider の階層だけに絞られます。
2 つの経路が共有するのは 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 が含まれます。
ステムを分離する
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 ページあたりの件数、1–100。デフォルトは 20 |
status | string | いいえ | pending、generating、uploading、success、failed で絞り込みます |
data は配列ではなくページです。items にこのページのタスク、total に全件数が入り、page と pageSize には実際に適用された値が返ります。
単一タスクを取得する
GET /v1/music/tasks/{taskId}
タスクを 1 件取得します。非同期の生成リクエストを送信したあとにポーリングするのは、このエンドポイントです。
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。
非同期生成では、送信時にクレジットを予約し、success で確定、failure の場合は自動的に返却されます。実際のコストはタスクごとに creditCost として返されます(分析系の呼び出しも結果に creditCost を含みます)。現在の残高は GET /v1/user/subscription で確認でき、クレジットと機能の対応関係は料金を参照してください。
SDK と CLI
公式 SDK と CLI は、非同期のポーリングも含め、以下のエンドポイントをラップしています。どちらもまだ provider の指定と Suno 固有のパラメータには対応していないため、その 2 つは 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 を使います。