在 Node.js 里做 stem 分离。
面向 AI Stem Splitter 的 typed Node 和 TypeScript client。从 npm 或 JSR 安装,运行在 Node、Bun 或 Deno 上,用真正 12 行脚本交付一个可用的 stem-separation 功能——提交音轨、轮询到 ready,并在下次站会 demo 前把 4 条 stem 写到磁盘。
安装
认证
从 developer settings 生成一个 key,把它作为 AISTEMSPLITTER_API_KEY 放进环境变量,并传给 client constructor。SDK 不会记录这个 key,页面也只会在 tooltip 中渲染 public-safe 的 ast_live_ 前缀。
import { AiStemSplitter } from "@aistemsplitter/sdk";
const client = new AiStemSplitter({
apiKey: process.env.AISTEMSPLITTER_API_KEY!,
});Hello world
12 行,端到端。提交音轨,等待 htdemucs_ft 模型完成,然后把四条 stem——vocals、drums、bass、other——写到磁盘。把它粘进一个 .mjs 文件,设置 key,在站会 demo 前跑起来。
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));
}Methods
6 个 typed methods 覆盖完整 job lifecycle。每一个都是已发布 package 上真实的 TypeScript signature——编辑器自动补全,无需自己写 fetch wrapper,也不用背 schema。
提交新的 split job;返回 job id 和 queued status。
获取某个 split job 的当前状态。
持续轮询,直到 job 成功、失败或超时。
按页列出这个 API key 最近的 split jobs。
获取 pre-signed PUT URL,用于浏览器/服务器直接上传。
验证传入 webhook payload 上的 HMAC-SHA256 signature。
Webhooks
轮询能帮你跑通 demo。Webhooks 才能带你进 production。把 signed callback URL 放进 createSplit,然后在现有 Express 或 Hono handler 中用一次 SDK 调用验证 HMAC-SHA256 signature。
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 能在 Bun 和 Deno 里无 polyfill 运行吗?
可以。这个 package 同时发布到 npm 和 JSR,所以 Bun 可通过 `bun add jsr:@aistemsplitter/sdk` 安装,Deno 可通过 `deno add jsr:@aistemsplitter/sdk` 安装。client core 中没有 @types/node polyfills、无需 Buffer shimming,也没有 node:fs imports——typed surface 使用 Web Fetch + Web Streams APIs,Node 18+、Bun 和 Deno 都原生实现。
如何在 Express、Hono 或 Next.js 中验证 webhook signatures?
调用 ast.verifyWebhook({ headers, body })——它会基于 raw body 计算 HMAC-SHA256,与 aistemsplitter-signature header 做 constant-time compare,并在被篡改时抛错。上方 Webhooks 部分展示了可运行的 Express 和 Hono handlers;如果是 Next.js App Router,请在 route.ts handler 中使用 Hono 模式,通过 `await request.text()` 读取 raw body 后再验证。
TypeScript surface 是真实类型,还是到处都是 `any`?
是真实类型。AistemsplitterClient 上每个 method 都有 typed input + Promise return:createSplit(input: CreateSplitInput) → Promise<Split>、getSplit(id: string) → Promise<Split>、waitForSplit、listSplits、presignUpload、verifyWebhook。Split + Stem + WebhookEvent types 从 package root 导出,所以你可以把它们 import 到自己的 handlers 和 storage layer 中,不用重新推导 shape。
SDK 的错误和 retry 怎么处理?
所有 methods 都会抛出 typed errors:AistemsplitterApiError(4xx/5xx,带 code + message + requestId)、AistemsplitterRateLimitError(429,带 retryAfter seconds)、AistemsplitterNetworkError(transport-level)。waitForSplit 会自动用 exponential backoff retry 轮询,直到 SDK timeout(默认 5 min)——如果需要 at-least-once submission 语义,请把 createSplit / presignUpload 包进你自己的 retry helper。
我可以在浏览器里运行它吗?
不可以——SDK 是 server-side client。浏览器使用会暴露你的 API key(任何到达用户设备的代码都能读到它),并且会遇到 upload endpoints 的 CORS 限制。请在你的 server 上用 presignUpload 创建 short-lived signed URL,只把这个 URL 交给浏览器;实际的 createSplit + waitForSplit 调用应放在 server route、n8n workflow 或 background worker 中。
下一步
在站会前交付 4 条 stem。
免费注册,无需信用卡。积分包永不过期——按购买量不同,每分钟 $0.08–$0.14。