ListenHubDocs
API リファレンス

音楽生成

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、/extend202 と taskId を返します。status が success になるまで GET /v1/music/tasks/{taskId} をポーリングします。
同期分析/recognize、/describe、/stem200 を返し、結果は同じレスポンスに含まれます。ポーリングは不要です。

すべてのレスポンスは { "code": 0, "message": "", "data": { ... } } の形にラップされます。code が 0 以外ならエラーです——エラーハンドリングを参照してください。以下の例はすべて data からフィールドを読み取ります。

プロバイダー

provider は mureka、suno、default を受け付けます。default は Mureka に解決されます。このフィールドを読むのは 2 つのエンドポイントだけで、残りは単一のプロバイダーが担当し、指定しても無視されます。

エンドポイントMurekaSunoプロバイダーの決まり方
/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 のモデル:

モデルクレジット説明
auto10Mureka のデフォルト。サービス側がモデルを自動選択します。
mureka-7.65
mureka-810
mureka-910/instrumental では利用できません。
mureka-o210

Suno のモデル:

モデルクレジット説明
V415
V4_515
V4_5PLUS15
V4_5ALL15
V515
V5_520
V620Suno のデフォルト。最新の階層です。

どの階層も明示的に指定できます。model を省いた Suno のリクエストは V6 で実行されます。

ステム分離(/stem)は別のモデルセットを使います:audio-separation-1(デフォルト)または audio-separation-2(MIDI も出力)。

Suno 固有のパラメータ

Suno には Mureka に対応するもののないパラメータが 7 つあります。/generate と /cover では providerParams の中に、/extend ではトップレベルのフォームフィールドとして指定します。

フィールド型対象エンドポイント説明
negativeTagsstring/generate、/cover、/extend避けたいスタイルタグ(カンマ区切り)
vocalGenderstring/generate、/cover、/extendm または f。male / female を取る /track とは異なる点に注意してください
styleWeightnumber/generate、/cover、/extend0–1。結果が style にどれだけ忠実かを決めます
weirdnessConstraintnumber/generate、/cover、/extend0–1。結果が定石からどれだけ離れてよいかを決めます
audioWeightnumber/generate、/cover、/extend0–1。元音源の重み。元音源を伴うリクエストでのみ意味を持ちます
personaIdstring/generate、/coverトラックを歌う Suno の persona。/cover ではカスタムモードのみ有効です
personaModelstring/generate、/coverその persona を作成したモデル階層。personaId と併せて指定します

上記以外のキーは、リクエストが Suno に届く前に providerParams から取り除かれます。

非同期タスクのライフサイクル

  1. 生成リクエストを送信します。レスポンスには taskId と初期 status の pending が含まれます。
  2. GET /v1/music/tasks/{taskId} をポーリングします。status は pending → generating → uploading → success と遷移します。
  3. 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'])

リクエストパラメータ:

フィールド型必須説明
promptstringいいえMureka ではスタイル / 内容のプロンプト。Suno は歌詞として読み取るため、lyrics を使いスタイルは style に渡してください
lyricsstringいいえ歌詞。instrumental が true でない限り Mureka では必須。Suno は楽曲の歌詞としてこの値を使います
stylestringいいえスタイルタグ。prompt のフォールバックとして使われます
titlestringいいえトラックのタイトル
instrumentalbooleanいいえボーカルなしで生成します
customModebooleanいいえSuno のみ。デフォルトは true で、style と title が説明を担い、歌詞本文は lyrics から取られます。false にすると曲全体を prompt だけで生成します
modelstringいいえモデルを参照。デフォルトは Mureka が auto、Suno が V6
vocalIdstringいいえMureka の vocal id を再利用します。Mureka のみ
providerstringいいえdefault(Mureka)、mureka、suno。デフォルトは default
providerParamsobjectいいえプロバイダー固有のパラメータ。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'])

リクエストパラメータ:

フィールド型必須説明
promptstringいずれかスタイル / ジャンルの説明。referenceAudio とは排他です
referenceAudiofileいずれか参照音声(mp3/m4a、最大 10MB)。prompt とは排他です
modelstringいいえ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'])

リクエストパラメータ:

フィールド型必須説明
imagefileいずれか画像(jpg/jpeg/png/webp)。video とは排他です
videofileいずれか動画(mp4/mov/avi/mkv/webm)。image とは排他です
promptstringいいえスタイル / 内容のプロンプト
modelstringいいえ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'])

リクエストパラメータ:

フィールド型必須説明
generateTypestringはい生成するトラックの種類。Vocals、Instrumental、Drums、Bass、Guitar、Keyboard、Percussion、Strings、Synth、FX、Brass、Woodwinds のいずれか
promptstringはいスタイル / ジャンルの説明
audiofileいずれか参照音声(mp3/m4a/wav、最大 10MB)。providerSongId とは排他です
providerSongIdstringいずれか過去の結果に含まれる Mureka の song id。audio とは排他です
lyricsstringVocals の場合歌詞。generateType が Vocals のときは必須
vocalGenderstringいいえmale または female。generateType=Vocals のときのみ有効
generateStartnumberいいえ範囲の開始位置(秒)
generateEndnumberいいえ範囲の終了位置(秒)

既存の楽曲をリミックスする

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'])

リクエストパラメータ:

フィールド型必須説明
lyricsstringはい新しい歌詞
promptstringはいスタイル / ジャンルの説明
audiofile元音源のいずれか 1 つ音声ファイル(mp3/m4a、最大 10MB)
audioUrlstring元音源のいずれか 1 つListenHub 内部の音声 URL(自分のものか公開されている必要があります)
providerSongIdstring元音源のいずれか 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'])

リクエストパラメータ:

フィールド型必須説明
uploadUrlstringはい元の録音。一般に到達可能な URL、または自分が所有する ListenHub アセットの URL。後者は所有権を検証したうえで短期間有効なダウンロードリンクが発行されます
modelstringいいえSuno のモデル。モデルを参照。デフォルトは V6
customModebooleanいいえデフォルトは true。false にすると prompt だけでカバーを生成します
promptstringカスタムモードでは必須新しいボーカルの歌詞。customMode が true かつ instrumental が false のときは必須です。カスタムモード以外では自由記述の説明になります
stylestringカスタムモードでは必須音楽スタイル
titlestringカスタムモードでは必須トラックのタイトル
instrumentalbooleanいいえボーカルなしでカバーを生成します。デフォルトは false
providerParamsobjectいいえ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 の場合):

フィールド型必須説明
audiofile元音源のいずれか 1 つ音声ファイル(mp3/m4a、最大 10MB)。uploadUrl / providerSongId とは排他です
uploadUrlstring元音源のいずれか 1 つ音声の URL(到達可能な外部リンク、または内部の GCS URL)
providerSongIdstring元音源のいずれか 1 つ過去の結果に含まれる Mureka の song id
modelstringいいえMureka のモデル名。モデルを参照。デフォルトは auto で、このエンドポイントでは mureka-7.6 に解決されます
extendAtnumberはい延長の起点となる時間オフセット。8–420 秒の範囲で指定します
extendTypestringいいえtail(前方向、デフォルト)または head(後方向、mureka-8 のみ)
lyricsstringはい新しいセクションの歌詞
promptstringいいえスタイル / 内容の説明
stylestringいいえ音楽スタイル
titlestringいいえトラックのタイトル
instrumentalbooleanいいえ新しいセクションをボーカルなしで生成します

リクエストパラメータ(Suno 経路):

フィールド型必須説明
providerstringはいsuno。指定しない場合は Mureka 経路になります
uploadUrlstringはい元の録音。一般に到達可能な URL、または自分が所有する ListenHub アセットの URL
continueAtnumberはい続きを生成し始める秒数。0 より大きい必要があります
modelstringいいえSuno のモデル。モデルを参照。デフォルトは V6
promptstringいいえ続きのセクションの歌詞。instrumental が true のときは無視されます
stylestringいいえ音楽スタイル
titlestringいいえトラックのタイトル
instrumentalbooleanいいえ続きをボーカルなしで生成します
negativeTagsstringいいえSuno 固有のパラメータを参照
vocalGenderstringいいえSuno 固有のパラメータを参照
styleWeightnumberいいえSuno 固有のパラメータを参照
weirdnessConstraintnumberいいえSuno 固有のパラメータを参照
audioWeightnumberいいえ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']))

リクエストパラメータ:

フィールド型必須説明
audiofileはい音声ファイル(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'])

リクエストパラメータ:

フィールド型必須説明
audiofileはい分析する音声ファイル(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'])

リクエストパラメータ:

フィールド型必須説明
audiofileはい分離する音声ファイル(mp3/m4a、最大 10MB)
modelstringいいえ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')

クエリパラメータ:

フィールド型必須説明
pageintegerいいえページ番号、最小 1。デフォルトは 1
pageSizeintegerいいえ1 ページあたりの件数、1–100。デフォルトは 20
statusstringいいえ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'])

タスクレスポンスのフィールド:

フィールド型説明
idstringタスク ID
providerstringmureka または suno。作成時に解決済みで、default のまま保存されることはありません
taskTypestringGENERATE、INSTRUMENTAL、REMIX、EXTEND、COVER、SOUNDTRACK、TRACK、RECOGNIZE、DESCRIBE、STEM、REGION_EDIT
statusstringpending、generating、uploading、success、failed
paramsobject生成リクエストの内容をそのまま返します。model にはタスクが実行されたモデル階層が入ります
tracksarray完成したトラック:title、tags、duration(秒)、署名付き audioUrl
creditCostnumber消費したクレジット
errorMessagestring失敗理由(status が failed のときのみ)
createdAtnumber作成時刻(ミリ秒タイムスタンプ)
updatedAtnumber最終更新時刻(ミリ秒タイムスタンプ)

クレジット

/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 で直接呼び出してください。

このページの内容