ガイド

APIでオーディオをマスタリングする:curl、Python、Node、バッチ、MCP

Jam JamのAPIは、無料のブラウザツールと同じ設定で、サーバー上で音声ファイルをマスタリングします。ファイルをアップロードし、プリセットを選ぶか自分の設定を送り、ジョブを追跡してWAVをダウンロードします。このガイドでは、curl、Python、Nodeでの全手順、バッチ処理、エラー処理、アシスタント向けのMCPサーバーを紹介します。

曲をマスタリングする →

関連ツール · 無料のオンラインマスタリング、ブラウザで

APIでできること

Jam JamのREST APIの/masteringファミリーは、プリセットで音声ファイルをレンダリングします。音色のバランスを整え、歯擦音を抑え、ステレオ幅を設定し、音量をターゲット(ストリーミング、Apple Music、Deezer、ポッドキャスト、クラブ)に合わせます。設定は、jam-jam.org/app/masteringのWebツールの設定に対応します。OpenAPI 3.1の仕様はjam-jam.org/api/v1/openapi.json、リファレンスはjam-jam.org/developersにあります。ファイルは最大200 MBで10分まで、モノラルまたはステレオ(3チャンネル以上は先頭の2つを使用)で、48 kHzで処理されます。出力は16ビット(wav-pcm16、既定)または32ビット浮動小数点(wav-f32)のWAVで、APIは24ビットに対応していません。元のファイルはデコード後すぐに削除され、結果は24時間保存されます。サーバーのレンダリングは再現できます(同じファイル、同じ設定、同じengineVersion)が、ブラウザの書き出しとビット単位で同一になる保証はありません。

曲をマスタリングする →

キーを取得してアクセスを確認する

jam-jam.orgでアカウントを作成し、設定、APIキー(jam-jam.org/app/prefs/api-keys)の順に開いて、mastering:readとmastering:writeのスコープを付けたキーを作ります。キーはjj_live_で始まり、表示されるのは1回だけで、1つのアカウントで5つまで持てます。キーは環境変数JAM_JAM_API_KEYに保存し、リポジトリや共有のコマンドラインには置かないでください。APIでのファイルのレンダリング(POST /mastering/jobs)は、どのアカウントでも使えます。無料アカウントはISO週あたり3回(Webツールと同じカウンター)、Premiumは上限なしです。仕様の読み取りと、プリセットの一覧表示や保存も、どのアカウントでも使えます。

最新の仕様を読む

GET /mastering/capabilitiesはキーが不要です。エンジンのバージョン、各設定の範囲とステップ、音量ターゲット、内蔵プリセット、制限を返し、キーを付けるとrenderAllowedとカウンターの残りも返します。範囲をコードに固定せず、これを読んでください。内蔵プリセット5つは読み取り専用で、preset=builtin:<id>として使います。builtin:balanced、builtin:warm、builtin:bright、builtin:punchy、builtin:crushedです。POST /mastering/presetsで自分のプリセットを最大50個(名前は60文字まで)保存し、IDで呼び出すこともできます。

仕様を読む(キー不要)

curl https://jam-jam.org/api/v1/mastering/capabilities

curlでファイルをレンダリングする

流れはJam Jamのどのジョブとも同じです。202を返すPOST、終わるまでのポーリング、そしてダウンロードです。Idempotency-Keyヘッダー(A-Z、a-z、0-9、_、-の16〜80文字)はすべての書き込みで必須で、同じキーと同じ本文を再送すると、二重課金なしで同じジョブが返ります。ジョブはqueued、decoding、analyzing、renderingを経て、done、failed、cancelled、expiredのいずれかで終わり、完了するとレンダリング前後の統合ラウドネス(LUFS)とトゥルーピーク(dBTP)を含むreportが付きます。1つのアカウントで、実行中のレンダリングは1つ、待機は3つまでです。サンプルのリポジトリには、同じ手順が番号付きスクリプト(curl/09-mastering-capabilities.shからcurl/14-mastering-delete.shまで)として入っています。

内蔵プリセットでレンダリングし、ジョブを追跡してWAVをダウンロード

# 1. Upload the file with a built-in preset (Idempotency-Key is required)
curl -X POST https://jam-jam.org/api/v1/mastering/jobs \
  -H "Authorization: Bearer $JAM_JAM_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F [email protected] -F preset=builtin:warm -F format=wav-pcm16
# The 202 answer carries the job "id": JOB_ID=<that id>

# 2. Follow the job, honouring Retry-After, until "status" is "done"
curl https://jam-jam.org/api/v1/mastering/jobs/$JOB_ID \
  -H "Authorization: Bearer $JAM_JAM_API_KEY"

# 3. Download the mastered WAV
curl -o mix-master.wav https://jam-jam.org/api/v1/mastering/jobs/$JOB_ID/result \
  -H "Authorization: Bearer $JAM_JAM_API_KEY"

PythonとNode

この2つのコードは、サンプルのリポジトリgithub.com/titouannwtt/jam-jam-api-examples(MITライセンス)のpython/mastering_lib.pyとjavascript/mastering-lib.mjsを要約したものです。Pythonは3.10以降とrequests、Nodeは20以降で依存パッケージは不要です。完成版のスクリプトは各HTTPコードに分かりやすいメッセージを付け、python mastering.py master mix.wav --preset builtin:warm、またはnode mastering.mjs master mix.wav --preset builtin:warmで実行します。

Python(3.10以降、requests)

import os, time, uuid, requests

API = "https://jam-jam.org/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['JAM_JAM_API_KEY']}"}
FINAL = ("done", "failed", "cancelled", "expired")

# 1. Upload the file with a built-in preset. Idempotency-Key is required.
with open("mix.wav", "rb") as audio:
    res = requests.post(
        f"{API}/mastering/jobs",
        headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
        data={"preset": "builtin:warm", "format": "wav-pcm16"},
        files={"file": ("mix.wav", audio)},
    )
res.raise_for_status()
job = res.json()

# 2. Poll, waiting as long as the server asks.
while job["status"] not in FINAL:
    time.sleep(int(res.headers.get("Retry-After") or 2))
    res = requests.get(f"{API}/mastering/jobs/{job['id']}", headers=HEADERS)
    res.raise_for_status()
    job = res.json()
if job["status"] != "done":
    raise SystemExit(f"mastering {job['status']}: {job.get('error')}")

before, after = job["report"]["before"], job["report"]["after"]
print(f"LUFS {before['integratedLufs']} -> {after['integratedLufs']}")

# 3. Download the mastered WAV.
audio = requests.get(f"{API}/mastering/jobs/{job['id']}/result", headers=HEADERS)
audio.raise_for_status()
with open("mix-master.wav", "wb") as out:
    out.write(audio.content)

Node(20以降、依存なし)

import { openAsBlob } from 'node:fs';
import { writeFile } from 'node:fs/promises';

const API = 'https://jam-jam.org/api/v1';
const headers = { Authorization: `Bearer ${process.env.JAM_JAM_API_KEY}` };
const FINAL = ['done', 'failed', 'cancelled', 'expired'];

// 1. Upload the file with a built-in preset. Idempotency-Key is required.
const body = new FormData();
body.append('file', await openAsBlob('mix.wav'), 'mix.wav');
body.append('preset', 'builtin:warm');
body.append('format', 'wav-pcm16');
let res = await fetch(`${API}/mastering/jobs`, {
  method: 'POST',
  headers: { ...headers, 'Idempotency-Key': crypto.randomUUID() },
  body,
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
let job = await res.json();

// 2. Poll, waiting as long as the server asks.
while (!FINAL.includes(job.status)) {
  await new Promise((r) => setTimeout(r, (Number(res.headers.get('retry-after')) || 2) * 1000));
  res = await fetch(`${API}/mastering/jobs/${job.id}`, { headers });
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  job = await res.json();
}
if (job.status !== 'done') throw new Error(`mastering ${job.status}: ${JSON.stringify(job.error)}`);

const { before, after } = job.report;
console.log(`LUFS ${before.integratedLufs} -> ${after.integratedLufs}`);

// 3. Download the mastered WAV.
res = await fetch(`${API}/mastering/jobs/${job.id}/result`, { headers });
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
await writeFile('mix-master.wav', Buffer.from(await res.arrayBuffer()));

自分の設定を使う

プリセットの代わりに、設定をJSONでsettingsフィールドに入れて送ります。presetとsettingsのどちらか一方だけを指定します。形式(MasteringSettingsV1)は、valueとenabledフラグを持つ8つのモジュール、音量ターゲット(streaming、apple、deezer、podcast、club)、normalizeで構成されます。音色の設定はデシベル、それ以外はパーセントで、最大150です。範囲やステップから外れた値には、問題ごとに1件のエントリーを付けた422 invalid-settingsが返ります。設定を再利用するには、POST /mastering/presetsで保存し、そのIDをpresetに渡します。設定はアップロード時にコピーされるので、あとでプリセットを変えても、開始済みのジョブには影響しません。

自分の設定を送る

{
  "modules": {
    "autoEq":   { "value": 50, "enabled": true },
    "lows":     { "value": 2, "enabled": true },
    "mids":     { "value": -0.5, "enabled": true },
    "highs":    { "value": -1.5, "enabled": true },
    "deEss":    { "value": 40, "enabled": true },
    "width":    { "value": 10, "enabled": true },
    "loudness": { "value": 45, "enabled": true },
    "destruct": { "value": 0, "enabled": false }
  },
  "target": "streaming",
  "normalize": false
}

自分の設定を送る

curl -X POST https://jam-jam.org/api/v1/mastering/jobs \
  -H "Authorization: Bearer $JAM_JAM_API_KEY" -H "Idempotency-Key: $(uuidgen)" \
  -F [email protected] -F "settings=<samples/mastering-settings.json" -F format=wav-pcm16

フォルダ全体をバッチで処理する

リポジトリには、フォルダを1つのプリセットで1ファイルずつマスタリングするバッチスクリプト、python/mastering_batch.pyとjavascript/mastering-batch.mjsが入っています。真似する価値のある工夫が3つあります。ファイルは1つずつ送ります。1つのアカウントで受け付けるのは、実行中1つと待機3つまでだからです。名前-master.wavがすでにあるファイルはスキップするので、中断後に再実行できます。待ち時間が短い429(最大5分)ではRetry-Afterの間待って、同じファイルを同じ冪等キーで再送し、403や長い429では停止します。後続のファイルも同じように失敗するからです。

フォルダを1ファイルずつマスタリング

python mastering_batch.py ~/Music/mixes --preset builtin:balanced --out masters
node mastering-batch.mjs ~/Music/mixes --preset builtin:balanced --out masters

エラーとクォータ

エラーはすべて、確認できる安定したcodeを持つapplication/problem+jsonで、レンダリングの応答にはX-Mastering-Quota-Limit、X-Mastering-Quota-Remaining、X-Mastering-Quota-Resetのヘッダーが付きます。Premiumアカウントにはレンダリング回数の上限がありません。無料アカウントでコードquota-exhaustedの429が返った場合は、その週のレンダリング回数を使い切ったことを意味し、それ以外の429はレート制限か待機列の混雑を意味します。失敗または取り消したレンダリングは数えられません。APIでのファイルのレンダリング(POST /mastering/jobs)は、どのアカウントでも使えます。無料アカウントはISO週あたり3回(Webツールと同じカウンター)、Premiumは上限なしです。仕様の読み取りと、プリセットの一覧表示や保存も、どのアカウントでも使えます。

マスタリングのエラーと対処
ステータスコード意味
401キーがない、または無効です。
403insufficient-scopeキーにmastering:readまたはmastering:writeのスコープがありません。
403premium-requiredお使いのプランではレンダリングを利用できません(GET /mastering/capabilitiesのrenderAllowedを確認)。
409not-readyレンダリングが終わる前に結果を要求しました。
410expired24時間が過ぎました。もう一度レンダリングしてください。
413, 415, 422ファイルが大きすぎる、形式が非対応、音声が10分を超える、または設定が無効です(errors[]を確認)。
429rate-limitedリクエストが多すぎる、レンダリングが1件実行中で3件待機中(client-quota)、または待機列が満杯(queue-full):Retry-Afterの秒数だけ待ち、ループしないでください。

アシスタント向けのMCPサーバー

公式のMCPサーバー@jam-jam/convert-mcpは、Claude Desktop、Claude Code、Cursorなど、Model Context Protocolのクライアントにマスタリングを提供し、キーのスコープが許可するツールだけを表示します。マスタリングのツールは6つです。jj_mastering_capabilities(スコープなし)、jj_list_mastering_presets、jj_create_mastering_preset、jj_master_audio、jj_mastering_get_job、jj_mastering_cancel_jobです。jj_master_audioは、ローカルのファイルをプリセットまたはインライン設定でアップロードし、maxWaitMsを付けると、結果を待ってダウンロードします。そのあと、アシスタントに「warmプリセットでこのファイルをマスタリングして、前後の音量を教えて」と頼めます。キーは環境変数に置き、コマンドラインには書かないでください。

MCPクライアントの設定

{
  "mcpServers": {
    "jam-jam": {
      "command": "npx",
      "args": ["-y", "@jam-jam/convert-mcp"],
      "env": { "JAM_JAM_API_KEY": "jj_live_..." }
    }
  }
}

設定の意味や目指す音量を知りたい場合は、 曲を無料でマスタリングする方法のガイドをどうぞ。

マスタリングAPIのよくある質問

Jam JamのマスタリングAPIは無料ですか?

はい。無料アカウントでは、POST /mastering/jobsでISO週あたり3ファイルをレンダリングできます(Webツールと同じカウンター)。失敗または取り消したレンダリングは戻されます。Premiumなら上限はありません。最新の仕様の読み取りとプリセットの管理は無料です。

ファイルの制限は?

最大200 MBで10分まで、モノラルまたはステレオです。結果は48 kHzの16ビット、24ビット、または32ビット浮動小数点のWAVで、24時間保存されます。

結果はブラウザと同じですか?

サーバー上では再現できます(同じファイル、同じ設定、同じengineVersion)が、ブラウザの書き出しとビット単位で同一になる保証はありません。設定は同じです。

複数のファイルを一度に送れますか?

1つのアカウントで、実行中のレンダリングは1つ、待機は3つまでです。フォルダは、サンプルのリポジトリのバッチスクリプトで1ファイルずつ送ってください。

AIアシスタントからはどう使いますか?

MCPサーバー@jam-jam/convert-mcpを使います。jj_master_audioツールがローカルのファイルをマスタリングし、jj_mastering_get_jobが前後の音量を読み取ります。

同じエンジンをブラウザで無料で試せます。ファイルは端末の外に出ません。