Séparation de stems, en Node.js.
Un client Node et TypeScript typé pour AI Stem Splitter. Installez depuis npm ou JSR, exécutez sur Node, Bun ou Deno, et livrez une fonctionnalité de séparation de stems opérationnelle dans un script littéral de 12 lignes — soumettez un morceau, poll jusqu’à ce qu’il soit prêt, puis écrivez les 4 stems sur disque avant la prochaine démo de standup.
Installation
Authentification
Générez une clé depuis vos paramètres développeur, placez-la dans votre environnement comme AISTEMSPLITTER_API_KEY, puis transmettez-la au constructeur client. Le SDK ne journalise jamais la clé et la page n’affiche jamais plus que le préfixe public-safe ast_live_ dans les tooltips.
import { AiStemSplitter } from "@aistemsplitter/sdk";
const client = new AiStemSplitter({
apiKey: process.env.AISTEMSPLITTER_API_KEY!,
});Hello world
Douze lignes, de bout en bout. Soumettez un morceau, attendez que le modèle htdemucs_ft se termine, puis écrivez les quatre stems — vocals, drums, bass, other — sur disque. Collez ceci dans un seul fichier .mjs, définissez votre clé et exécutez-le avant la démo de standup.
import { AiStemSplitter } from "@aistemsplitter/sdk";
import { writeFile } from "node:fs/promises";
const client = new AiStemSplitter({
apiKey: process.env.AISTEMSPLITTER_API_KEY!,
});
// 1. Submit a split job
const job = await client.createSplit({
input: { type: "direct_url", url: "https://example.com/song.mp3" },
stemModel: "htdemucs_ft",
});
// 2. Wait until completion (polls under the hood)
const result = await client.waitForSplit(job.id);
// 3. Download all six stems
for (const [name, url] of Object.entries(result.stems)) {
const audio = await fetch(url).then((r) => r.arrayBuffer());
await writeFile(`./${name}.wav`, Buffer.from(audio));
}Méthodes
Six méthodes typées couvrent tout le cycle de vie du job. Chacune est une vraie signature TypeScript dans le package publié — autocomplétion dans votre éditeur, aucun wrapper fetch à écrire, aucun schéma à mémoriser.
Soumet un nouveau job de séparation ; renvoie un job id et le statut queued.
Récupère le statut actuel d’un job de séparation.
Poll jusqu’à ce que le job réussisse, échoue ou que le timeout expire.
Liste paginée des jobs de séparation récents pour la clé API.
Obtient une URL PUT présignée pour les uploads directs navigateur/serveur.
Vérifie la signature HMAC-SHA256 d’un payload webhook entrant.
Webhooks
Le polling vous mène à la démo. Les webhooks vous mènent à la production. Déposez une URL de callback signée dans createSplit, puis vérifiez la signature HMAC-SHA256 avec un seul appel SDK dans votre handler Express ou Hono existant.
import { AiStemSplitter } from "@aistemsplitter/sdk";
import { Hono } from "hono";
const app = new Hono();
const client = new AiStemSplitter({
apiKey: process.env.AISTEMSPLITTER_API_KEY!,
});
app.post("/webhooks/aistemsplitter", async (c) => {
const raw = await c.req.text();
const event = client.verifyWebhook(c.req.header(), raw); // throws if invalid
switch (event.type) {
case "split.succeeded":
// event.data.stems → six URLs
break;
case "split.failed":
// event.data.error → { code, message }
break;
}
return c.text("ok");
});FAQ
Does @aistemsplitter/sdk work in Bun and Deno without polyfills?
Yes. The package is dual-published to npm and JSR, so Bun installs via `bun add jsr:@aistemsplitter/sdk` and Deno via `deno add jsr:@aistemsplitter/sdk`. There are no @types/node polyfills, no Buffer shimming required, and no node:fs imports in the client core — the typed surface uses the Web Fetch + Web Streams APIs, which Node 18+, Bun, and Deno all implement natively.
How do I verify webhook signatures in Express, Hono, or Next.js?
Call ast.verifyWebhook({ headers, body }) — it computes the HMAC-SHA256 over the raw body, constant-time-compares against the aistemsplitter-signature header, and throws on tamper. The Webhooks section above shows runnable Express and Hono handlers; for Next.js App Router, use the Hono pattern in a route.ts handler with `await request.text()` to read the raw body before verification.
Is the TypeScript surface real, or `any` everywhere?
Real. Every method on AistemsplitterClient has a typed input + Promise return: createSplit(input: CreateSplitInput) → Promise<Split>, getSplit(id: string) → Promise<Split>, waitForSplit, listSplits, presignUpload, verifyWebhook. The Split + Stem + WebhookEvent types are exported from the package root, so you can import them into your own handlers and storage layer without re-deriving the shape.
How do I handle errors and retries from the SDK?
All methods throw typed errors: AistemsplitterApiError (4xx/5xx with code + message + requestId), AistemsplitterRateLimitError (429 with retryAfter seconds), AistemsplitterNetworkError (transport-level). waitForSplit retries polls automatically with exponential backoff until the SDK timeout (default 5 min) — wrap createSplit / presignUpload in your own retry helper if you need at-least-once submission semantics.
Can I run this in the browser?
No — the SDK is a server-side client. Browser use would expose your API key (any code that reaches the user's machine can read it) and run into CORS on the upload endpoints. Mint a short-lived signed URL on your server with presignUpload and hand only that URL to the browser; do the actual createSplit + waitForSplit calls from a server route, n8n workflow, or background worker.
@aistemsplitter/sdk fonctionne-t-il dans Bun et Deno sans polyfills ?
Oui. Le package est publié à la fois sur npm et JSR, donc Bun l’installe via `bun add jsr:@aistemsplitter/sdk` et Deno via `deno add jsr:@aistemsplitter/sdk`. Il n’y a pas de polyfills @types/node, aucun shim Buffer requis, et aucun import node:fs dans le cœur client — la surface typée utilise les APIs Web Fetch + Web Streams, que Node 18+, Bun et Deno implémentent tous nativement.
Comment vérifier les signatures webhook dans Express, Hono ou Next.js ?
Appelez ast.verifyWebhook({ headers, body }) — il calcule le HMAC-SHA256 sur le corps brut, compare en temps constant avec le header aistemsplitter-signature et lève une erreur en cas de falsification. La section Webhooks ci-dessus montre des handlers Express et Hono exécutables ; pour Next.js App Router, utilisez le pattern Hono dans un handler route.ts avec `await request.text()` pour lire le corps brut avant vérification.
La surface TypeScript est-elle réelle, ou du `any` partout ?
Réelle. Chaque méthode sur AistemsplitterClient a une entrée typée + un retour Promise : createSplit(input: CreateSplitInput) → Promise<Split>, getSplit(id: string) → Promise<Split>, waitForSplit, listSplits, presignUpload, verifyWebhook. Les types Split + Stem + WebhookEvent sont exportés depuis la racine du package, afin que vous puissiez les importer dans vos propres handlers et votre couche de stockage sans redériver la forme.
Comment gérer les erreurs et retries du SDK ?
Toutes les méthodes lèvent des erreurs typées : AistemsplitterApiError (4xx/5xx avec code + message + requestId), AistemsplitterRateLimitError (429 avec retryAfter en secondes), AistemsplitterNetworkError (niveau transport). waitForSplit retente automatiquement les polls avec exponential backoff jusqu’au timeout du SDK (5 min par défaut) — encapsulez createSplit / presignUpload dans votre propre helper de retry si vous avez besoin d’une sémantique de soumission at-least-once.
Puis-je l’exécuter dans le navigateur ?
Non — le SDK est un client côté serveur. Un usage navigateur exposerait votre clé API (tout code qui arrive sur la machine de l’utilisateur peut la lire) et rencontrerait CORS sur les endpoints d’upload. Créez une URL signée à durée courte sur votre serveur avec presignUpload et donnez seulement cette URL au navigateur ; exécutez les appels createSplit + waitForSplit depuis une route serveur, un workflow n8n ou un worker en arrière-plan.
Étapes suivantes
Livrez 4 stems avant le standup.
Inscription gratuite, sans carte bancaire. Packs de crédits sans expiration — 0,08–0,14 $ par minute selon le volume.