Poradnik

Mastering audio przez API: curl, Python, Node, wsad i MCP

API Jam Jam masteruje plik audio na serwerze z tymi samymi ustawieniami co darmowe narzędzie w przeglądarce. Wysyłasz plik, wybierasz preset lub przesyłasz własne ustawienia, śledzisz zadanie i pobierasz plik WAV. Ten przewodnik pokazuje całą drogę w curl, Pythonie i Node, przetwarzanie wsadowe, obsługę błędów i serwer MCP dla asystentów.

Zmasteruj utwór →

Powiązane narzędzie · Darmowy mastering audio, w przeglądarce

Co robi API

Rodzina /mastering API REST Jam Jam renderuje plik audio z presetem: wyrównuje brzmienie, temperuje głoski syczące, ustawia szerokość stereo i doprowadza poziom do celu głośności (streaming, Apple Music, Deezer, podcast lub klub), z ustawieniami narzędzia webowego pod adresem jam-jam.org/app/mastering. Kontrakt OpenAPI 3.1 jest pod adresem jam-jam.org/api/v1/openapi.json, a dokumentacja pod jam-jam.org/developers. Plik ma najwyżej 200 MB i 10 minut, mono lub stereo (powyżej dwóch kanałów używane są dwa pierwsze) i jest przetwarzany przy 48 kHz. Wynikiem jest plik WAV 16-bitowy (wav-pcm16, domyślnie) lub 32-bitowy zmiennoprzecinkowy (wav-f32); API nie oferuje 24 bitów. Plik źródłowy jest usuwany zaraz po zdekodowaniu, a wynik jest przechowywany 24 godziny. Render na serwerze jest powtarzalny (ten sam plik, te same ustawienia, ta sama engineVersion), ale nie ma gwarancji, że jest identyczny bit w bit z eksportem z przeglądarki.

Zmasteruj utwór →

Zdobądź klucz i sprawdź swój dostęp

Załóż konto na jam-jam.org, otwórz Ustawienia, potem Klucze API (jam-jam.org/app/prefs/api-keys) i utwórz klucz z zakresami mastering:read i mastering:write. Klucz zaczyna się od jj_live_, jest pokazywany tylko raz, a konto może mieć pięć kluczy. Trzymaj go w zmiennej środowiskowej JAM_JAM_API_KEY, nigdy w repozytorium ani we wspólnej linii poleceń. Renderowanie pliku przez API (POST /mastering/jobs) jest otwarte dla każdego konta: 3 renderowania na tydzień ISO z darmowym kontem, na tym samym liczniku co narzędzie webowe, bez limitu z Premium. Czytanie kontraktu oraz wyświetlanie i zapisywanie presetów też jest otwarte dla każdego konta.

Przeczytaj aktualny kontrakt

GET /mastering/capabilities nie wymaga klucza. Zwraca wersję silnika, zakres i krok każdego ustawienia, cele głośności, wbudowane presety i limity, a z kluczem dodaje renderAllowed i stan licznika. Czytaj go zamiast zakodowywać granice na stałe. Pięć wbudowanych presetów jest tylko do odczytu i używa się ich jako preset=builtin:<id>: builtin:balanced, builtin:warm, builtin:bright, builtin:punchy i builtin:crushed. Możesz też zapisać do 50 własnych presetów (nazwa do 60 znaków) przez POST /mastering/presets i wywoływać je po identyfikatorze.

Przeczytaj kontrakt (klucz niepotrzebny)

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

Renderowanie pliku za pomocą curl

Przebieg jest taki jak każdego zadania Jam Jam: POST odpowiadający 202, odpytywanie do końca, potem pobranie. Nagłówek Idempotency-Key (od 16 do 80 znaków spośród A-Z, a-z, 0-9, _ i -) jest wymagany przy każdym zapisie: ponowne wysłanie tego samego klucza z tą samą treścią zwraca to samo zadanie bez drugiego obciążenia. Zadanie przechodzi przez queued, decoding, analyzing i rendering, po czym kończy się jako done, failed, cancelled lub expired; po zakończeniu zawiera report ze zintegrowaną głośnością (LUFS) i szczytem rzeczywistym (dBTP) przed i po. Konto może mieć najwyżej jedno aktywne renderowanie i trzy oczekujące. Repozytorium przykładów zawiera te same kroki jako ponumerowane skrypty, od curl/09-mastering-capabilities.sh do curl/14-mastering-delete.sh.

Renderuj z wbudowanym presetem, śledź zadanie, pobierz 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 i Node

Te dwa fragmenty streszczają python/mastering_lib.py i javascript/mastering-lib.mjs z repozytorium przykładów github.com/titouannwtt/jam-jam-api-examples (licencja MIT): Python 3.10 lub nowszy z requests, Node 20 lub nowszy bez zależności. Pełne skrypty dodają czytelny komunikat dla każdego kodu HTTP i uruchamia się je poleceniem python mastering.py master mix.wav --preset builtin:warm lub node mastering.mjs master mix.wav --preset builtin:warm.

Python (3.10 lub nowszy, 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 lub nowszy, bez zależności)

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

Twoje własne ustawienia

Zamiast presetu prześlij ustawienia jako JSON w polu settings: dokładnie jedno z dwóch, preset albo settings. Format (MasteringSettingsV1) zawiera osiem modułów, każdy z value i znacznikiem enabled, cel głośności (streaming, apple, deezer, podcast lub club) oraz normalize. Ustawienia brzmienia są w decybelach, pozostałe w procentach, do 150; wartość spoza zakresu lub kroku odpowiada 422 invalid-settings z jednym wpisem na problem. Aby użyć zestawu ustawień ponownie, zapisz go przez POST /mastering/presets i podaj jego identyfikator w preset. Ustawienia są kopiowane przy wysyłaniu: późniejsza zmiana presetu nie wpływa na zadanie już rozpoczęte.

Prześlij własne ustawienia

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

Prześlij własne ustawienia

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

Mastering całego folderu wsadowo

Repozytorium zawiera dwa skrypty wsadowe, python/mastering_batch.py i javascript/mastering-batch.mjs, które masterują folder jednym presetem, plik po pliku. Warto przejąć trzy decyzje. Pliki wysyłane są pojedynczo, bo konto przyjmuje jedno aktywne renderowanie i trzy oczekujące. Plik, którego nazwa-master.wav już istnieje, jest pomijany, więc po przerwaniu możesz uruchomić ponownie. Przy 429 z krótkim oczekiwaniem (najwyżej pięć minut) skrypt czeka Retry-After i ponawia ten sam plik z tym samym kluczem idempotencji, a przy 403 lub długim 429 się zatrzymuje, bo kolejne pliki zakończyłyby się tak samo.

Mastering folderu, plik po pliku

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

Błędy i limity

Każdy błąd to application/problem+json ze stabilnym code, który możesz testować, a odpowiedzi renderowania niosą nagłówki X-Mastering-Quota-Limit, X-Mastering-Quota-Remaining i X-Mastering-Quota-Reset. Konta Premium nie mają limitu liczby renderowań. Na darmowym koncie 429 z kodem quota-exhausted oznacza, że renderowania z tego tygodnia się wyczerpały; każdy inny 429 oznacza ograniczenie częstotliwości lub zajętą kolejkę. Nieudane lub anulowane renderowanie nie jest liczone. Renderowanie pliku przez API (POST /mastering/jobs) jest otwarte dla każdego konta: 3 renderowania na tydzień ISO z darmowym kontem, na tym samym liczniku co narzędzie webowe, bez limitu z Premium. Czytanie kontraktu oraz wyświetlanie i zapisywanie presetów też jest otwarte dla każdego konta.

Błędy masteringu i co robić
StatusKodZnaczenie
401Brak klucza lub klucz nieprawidłowy.
403insufficient-scopeKlucz nie ma zakresu mastering:read ani mastering:write.
403premium-requiredRenderowanie nie jest otwarte dla Twojego planu (zobacz renderAllowed w GET /mastering/capabilities).
409not-readyWynik zażądany przed końcem renderowania.
410expiredMinęły 24 godziny: wyrenderuj ponownie.
413, 415, 422Plik za duży, format nieobsługiwany, audio dłuższe niż 10 minut lub nieprawidłowe ustawienia (przeczytaj errors[]).
429rate-limitedZa dużo żądań, albo jedno renderowanie już trwa i trzy czekają (client-quota), albo kolejka jest pełna (queue-full): poczekaj Retry-After sekund i nie zapętlaj.

Serwer MCP dla asystentów

Oficjalny serwer MCP @jam-jam/convert-mcp udostępnia Mastering w Claude Desktop, Claude Code, Cursor i innych klientach Model Context Protocol i pokazuje tylko te narzędzia, na które pozwalają zakresy Twojego klucza. Sześć narzędzi obejmuje Mastering: jj_mastering_capabilities (bez zakresu), jj_list_mastering_presets, jj_create_mastering_preset, jj_master_audio, jj_mastering_get_job i jj_mastering_cancel_job. jj_master_audio wysyła lokalny plik z presetem lub ustawieniami w treści i z maxWaitMs czeka na wynik i go pobiera. Możesz potem poprosić asystenta o zmasterowanie pliku presetem warm i podanie głośności przed i po. Klucz umieść w środowisku, nigdy w linii poleceń.

Konfiguracja klienta MCP

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

Aby zrozumieć, co robią ustawienia i jaką głośność wybrać, przeczytaj nasz przewodnik po masteringu utworu za darmo.

Najczęstsze pytania o API masteringu

Czy API masteringu Jam Jam jest darmowe?

Tak. Z darmowym kontem POST /mastering/jobs renderuje 3 pliki na tydzień ISO, na tym samym liczniku co narzędzie webowe; nieudane lub anulowane renderowanie jest zwracane. Premium znosi limit. Czytanie aktualnego kontraktu i zarządzanie presetami nic nie kosztuje.

Jakie są limity pliku?

Najwyżej 200 MB i 10 minut, mono lub stereo. Wynikiem jest plik WAV 48 kHz, 16-bitowy, 24-bitowy lub 32-bitowy zmiennoprzecinkowy, przechowywany 24 godziny.

Czy wynik jest identyczny z przeglądarkowym?

Jest powtarzalny na serwerze (ten sam plik, te same ustawienia, ta sama engineVersion), ale nie ma gwarancji, że jest identyczny bit w bit z eksportem z przeglądarki. Ustawienia są te same.

Czy mogę wysłać kilka plików naraz?

Konto ma jedno aktywne renderowanie i trzy oczekujące. Dla folderu wysyłaj pliki pojedynczo skryptami wsadowymi z repozytorium przykładów.

Jak używać tego z asystentem AI?

Przez serwer MCP @jam-jam/convert-mcp: narzędzie jj_master_audio masteruje lokalny plik, a jj_mastering_get_job odczytuje głośność przed i po.

Ten sam silnik możesz wypróbować za darmo w przeglądarce, z plikiem zostającym na Twoim urządzeniu.