Ratgeber

Audio per API masterieren: curl, Python, Node, Stapel und MCP

Die API von Jam Jam masteriert eine Audiodatei auf dem Server mit denselben Einstellungen wie das kostenlose Browser-Werkzeug. Du lädst eine Datei hoch, wählst ein Preset oder schickst eigene Einstellungen, verfolgst den Job und lädst eine WAV-Datei herunter. Diese Anleitung zeigt den ganzen Weg in curl, Python und Node, die Stapelverarbeitung, den Umgang mit Fehlern und den MCP-Server für Assistenten.

Einen Song masterieren →

Passendes Tool · Kostenloses Audio-Mastering, direkt im Browser

Was die API macht

Die Familie /mastering der REST-API von Jam Jam rendert eine Audiodatei mit einem Preset: Sie gleicht den Klang aus, zähmt Zischlaute, stellt die Stereobreite ein und bringt den Pegel auf ein Lautheitsziel (Streaming, Apple Music, Deezer, Podcast oder Club), mit den Einstellungen des Web-Werkzeugs unter jam-jam.org/app/mastering. Der OpenAPI-3.1-Vertrag liegt unter jam-jam.org/api/v1/openapi.json, die Referenz unter jam-jam.org/developers. Eine Datei darf höchstens 200 MB und 10 Minuten haben, mono oder stereo (bei mehr als zwei Kanälen werden die ersten beiden verwendet), und wird mit 48 kHz verarbeitet. Die Ausgabe ist eine WAV-Datei mit 16 Bit (wav-pcm16, Standard) oder 32 Bit Float (wav-f32); 24 Bit bietet die API nicht an. Die Quelldatei wird gelöscht, sobald sie dekodiert ist, und das Ergebnis wird 24 Stunden aufbewahrt. Ein Server-Render ist reproduzierbar (gleiche Datei, gleiche Einstellungen, gleiche engineVersion), aber nicht garantiert bitgenau identisch mit dem Export des Browsers.

Einen Song masterieren →

Einen Schlüssel holen und deinen Zugang prüfen

Lege ein Konto auf jam-jam.org an, öffne Einstellungen und dann API-Schlüssel (jam-jam.org/app/prefs/api-keys) und erstelle einen Schlüssel mit den Berechtigungen mastering:read und mastering:write. Der Schlüssel beginnt mit jj_live_, wird nur einmal angezeigt, und ein Konto kann fünf halten. Bewahre ihn in der Umgebungsvariable JAM_JAM_API_KEY auf, nie in einem Repository oder in einer geteilten Kommandozeile. Das Rendern einer Datei über die API (POST /mastering/jobs) steht jedem Konto offen: 3 Renderings pro ISO-Woche mit einem kostenlosen Konto, auf demselben Zähler wie das Web-Werkzeug, ohne Obergrenze mit Premium. Den Vertrag lesen sowie Presets auflisten oder speichern steht ebenfalls jedem Konto offen.

Den aktuellen Vertrag lesen

GET /mastering/capabilities braucht keinen Schlüssel. Es liefert die Engine-Version, Bereich und Schrittweite jeder Einstellung, die Lautheitsziele, die integrierten Presets und die Grenzen, und mit Schlüssel zusätzlich renderAllowed und den Stand deines Zählers. Lies es, statt die Grenzen fest einzucodieren. Fünf integrierte Presets sind schreibgeschützt und werden als preset=builtin:<id> verwendet: builtin:balanced, builtin:warm, builtin:bright, builtin:punchy und builtin:crushed. Du kannst auch bis zu 50 eigene Presets (Name mit höchstens 60 Zeichen) mit POST /mastering/presets speichern und über ihre ID aufrufen.

Den Vertrag lesen (kein Schlüssel nötig)

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

Eine Datei mit curl rendern

Der Ablauf ist der aller Jam-Jam-Jobs: ein POST, der 202 antwortet, Abfragen bis zum Ende, dann der Download. Der Header Idempotency-Key (16 bis 80 Zeichen aus A-Z, a-z, 0-9, _ und -) ist bei jedem Schreibzugriff Pflicht: Dieselbe Kennung mit demselben Inhalt erneut zu senden liefert denselben Job ohne zweite Abbuchung. Der Job durchläuft queued, decoding, analyzing und rendering und endet als done, failed, cancelled oder expired; fertig trägt er einen report mit der integrierten Lautheit (LUFS) und dem True Peak (dBTP) vorher und nachher. Ein Konto hat höchstens ein aktives Rendering und drei wartende. Das Beispiel-Repository enthält dieselben Schritte als nummerierte Skripte, von curl/09-mastering-capabilities.sh bis curl/14-mastering-delete.sh.

Mit einem integrierten Preset rendern, den Job verfolgen, die WAV-Datei herunterladen

# 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 und Node

Diese beiden Ausschnitte verdichten python/mastering_lib.py und javascript/mastering-lib.mjs aus dem Beispiel-Repository github.com/titouannwtt/jam-jam-api-examples (MIT-Lizenz): Python 3.10 oder neuer mit requests, Node 20 oder neuer ohne Abhängigkeiten. Die vollständigen Skripte liefern zu jedem HTTP-Code eine lesbare Meldung und werden mit python mastering.py master mix.wav --preset builtin:warm oder node mastering.mjs master mix.wav --preset builtin:warm gestartet.

Python (3.10 oder neuer, 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 oder neuer, ohne Abhängigkeiten)

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()));

Deine eigenen Einstellungen

Statt eines Presets schickst du die Einstellungen als JSON im Feld settings: genau eines von beiden, preset oder settings. Das Format (MasteringSettingsV1) enthält acht Module, jedes mit einem value und einem Flag enabled, ein Lautheitsziel (streaming, apple, deezer, podcast oder club) und normalize. Klangeinstellungen sind in Dezibel, die übrigen in Prozent, bis 150; ein Wert außerhalb seines Bereichs oder seiner Schrittweite beantwortet 422 invalid-settings mit einem Eintrag pro Problem. Um einen Satz Einstellungen wiederzuverwenden, speichere ihn mit POST /mastering/presets und übergib seine ID in preset. Einstellungen werden beim Hochladen kopiert: Das spätere Ändern des Presets verändert einen bereits gestarteten Job nicht.

Eigene Einstellungen senden

{
  "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
}

Eigene Einstellungen senden

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

Einen ganzen Ordner im Stapel masterieren

Das Repository enthält zwei Stapel-Skripte, python/mastering_batch.py und javascript/mastering-batch.mjs, die einen Ordner mit einem Preset masterieren, eine Datei nach der anderen. Drei Entscheidungen lohnen sich zum Übernehmen. Dateien werden einzeln gesendet, weil ein Konto ein aktives Rendering und drei wartende zulässt. Eine Datei, deren name-master.wav schon existiert, wird übersprungen, du kannst also nach einer Unterbrechung neu starten. Bei einem 429 mit kurzer Wartezeit (höchstens fünf Minuten) wartet das Skript auf Retry-After und sendet dieselbe Datei mit derselben Idempotenz-Kennung erneut, und es stoppt bei einem 403 oder einem langen 429, weil die nächsten Dateien genauso scheitern würden.

Einen Ordner masterieren, eine Datei nach der anderen

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

Fehler und Kontingente

Jeder Fehler ist ein application/problem+json mit einem stabilen code, den du prüfen kannst, und Render-Antworten tragen die Header X-Mastering-Quota-Limit, X-Mastering-Quota-Remaining und X-Mastering-Quota-Reset. Premium-Konten haben keine Obergrenze für Renderings. Bei einem kostenlosen Konto meldet ein 429 mit dem Code quota-exhausted, dass die Renderings der Woche aufgebraucht sind; jeder andere 429 meldet ein Ratenlimit oder eine volle Warteschlange. Ein fehlgeschlagenes oder abgebrochenes Rendering zählt nicht. Das Rendern einer Datei über die API (POST /mastering/jobs) steht jedem Konto offen: 3 Renderings pro ISO-Woche mit einem kostenlosen Konto, auf demselben Zähler wie das Web-Werkzeug, ohne Obergrenze mit Premium. Den Vertrag lesen sowie Presets auflisten oder speichern steht ebenfalls jedem Konto offen.

Mastering-Fehler und was zu tun ist
StatusCodeBedeutung
401Schlüssel fehlt oder ist ungültig.
403insufficient-scopeDem Schlüssel fehlt die Berechtigung mastering:read oder mastering:write.
403premium-requiredDas Rendering steht deinem Tarif nicht offen (siehe renderAllowed in GET /mastering/capabilities).
409not-readyErgebnis angefordert, bevor das Rendering fertig ist.
410expiredDie 24 Stunden sind vorbei: Rendere erneut.
413, 415, 422Datei zu groß, Format nicht unterstützt, Audio über 10 Minuten oder ungültige Einstellungen (lies errors[]).
429rate-limitedZu viele Anfragen, oder schon ein Rendering aktiv und drei wartend (client-quota), oder volle Warteschlange (queue-full): Warte Retry-After Sekunden und schleife nicht.

Der MCP-Server für Assistenten

Der offizielle MCP-Server @jam-jam/convert-mcp stellt das Mastering Claude Desktop, Claude Code, Cursor und anderen Model-Context-Protocol-Clients zur Verfügung und zeigt nur die Tools, die die Berechtigungen deines Schlüssels erlauben. Sechs Tools decken das Mastering ab: jj_mastering_capabilities (ohne Berechtigung), jj_list_mastering_presets, jj_create_mastering_preset, jj_master_audio, jj_mastering_get_job und jj_mastering_cancel_job. jj_master_audio lädt eine lokale Datei mit einem Preset oder Inline-Einstellungen hoch und wartet mit maxWaitMs auf das Ergebnis und lädt es herunter. Du kannst deinen Assistenten dann bitten, eine Datei mit dem Preset warm zu masterieren und dir die Lautheit vorher und nachher zu nennen. Lege den Schlüssel in die Umgebung, nie in eine Kommandozeile.

Konfiguration eines MCP-Clients

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

Um zu verstehen, was die Einstellungen tun und welche Lautheit du anpeilen solltest, lies unsere Anleitung, einen Song kostenlos zu masterieren.

Häufige Fragen zur Mastering-API

Ist die Mastering-API von Jam Jam kostenlos?

Ja. Mit einem kostenlosen Konto rendert POST /mastering/jobs 3 Dateien pro ISO-Woche, auf demselben Zähler wie das Web-Werkzeug; ein fehlgeschlagenes oder abgebrochenes Rendering wird gutgeschrieben. Premium hebt die Obergrenze auf. Den aktuellen Vertrag lesen und deine Presets verwalten kostet nichts.

Welche Dateigrenzen gelten?

Höchstens 200 MB und 10 Minuten, mono oder stereo. Das Ergebnis ist eine WAV-Datei mit 48 kHz, 16 Bit, 24 Bit oder 32 Bit Float, 24 Stunden aufbewahrt.

Ist das Ergebnis identisch mit dem des Browsers?

Es ist auf dem Server reproduzierbar (gleiche Datei, gleiche Einstellungen, gleiche engineVersion), aber nicht garantiert bitgenau identisch mit dem Export des Browsers. Die Einstellungen sind dieselben.

Kann ich mehrere Dateien gleichzeitig senden?

Ein Konto hat ein aktives Rendering und drei wartende. Sende bei einem Ordner die Dateien einzeln mit den Stapel-Skripten des Beispiel-Repositorys.

Wie nutze ich sie mit einem KI-Assistenten?

Mit dem MCP-Server @jam-jam/convert-mcp: Das Tool jj_master_audio masteriert eine lokale Datei, und jj_mastering_get_job liest die Lautheit vorher und nachher.

Dieselbe Engine kannst du kostenlos im Browser ausprobieren, mit deiner Datei auf deinem Gerät.