@decartai/sdk

中文文档
0.2.14发布于 2026/10/25MITTypeScriptES Module构建来源已验证近 30 天下载 22.5万

Decart 的 Java 脚本 SDK

中文使用文档
文档目录14 节
  1. 安装
  2. 文档
  3. 快速启动
  4. 实时视频转换
  5. 注意流线
  6. 连接质量
  7. Async 处理( API 队列)
  8. 客户端
  9. 反应原生/博览会
  10. 发展
  11. 设置
  12. 发展指挥部
  13. 出版
  14. 许可证

解密SDK

一个JavaScript SDK,用于德卡特的模型.

安装

npm install @decartai/sdk
# or
pnpm add @decartai/sdk
# or
yarn add @decartai/sdk

文档

完整文件、指南和实例访问: https://docs.platform.decart.ai/sdks/javascript

快速启动

实时视频转换

实时连接在SDK中被LiveKit支持. 现有客户用途保持不变: 相机 MediaStream,选择一个实时模型,并处理已变换的远程流.

import { createDecartClient, models } from "@decartai/sdk";

const model = models.realtime("lucy-restyle-2");

// Get user's camera stream
const stream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: { 
        frameRate: model.fps,
        width: model.width,
        height: model.height,
  }
});

// Create a client
const client = createDecartClient({
  apiKey: "your-api-key-here"
});

// Connect and transform the video stream
const realtimeClient = await client.realtime.connect(stream, {
  model,
  onRemoteStream: (transformedStream) => {
    videoElement.srcObject = transformedStream;
  },
  initialState: {
    prompt: {
      text: "Anime",
      enhance: true
    }
  }
});

// Change the style on the fly
realtimeClient.setPrompt("Cyberpunk city");

// Disconnect when done
realtimeClient.disconnect();

前相机镜像

预放输入流 :

const realtimeClient = await client.realtime.connect(stream, {
  model,
  mirror: "auto", // or true to always mirror
  // ...
});

选项 :

  • false (默认)——永远不要镜像.
  • "auto" 输入轨道报告时镜像 facingMode: "user" (移动前相机).
  • true ——总是镜像(例如桌面网络相机).

远程音频

服务器的音频音轨是您发布的音频, 与已转换的视频同步播放 (模型增加了潜伏度,所以服务器会延迟您的音频以匹配). SDK只订阅它 当您的输入流带有音频音轨时; 远程流同时带有视频和音频 音轨,您应该播放远程音频 而不是您的本地麦克风 这样的声音和图片 保持同步。 只有视频输入流从不订阅,所以远程流没有音频音轨和 iOS不显示播放任何远程音频会触发的麦克风许可提示 .

快取模式

快取模式( E)speed: "fast") 以较高的计算级别为会议服务,以降低延迟度和较高的吞吐量;产出质量不变。 目前可供 lucy-2.6, (中文(简体) ), lucy-2.5 编号 : lucy-latest 财务报告和审定财务报表 lucy-vton-3.6 编号 : lucy-vton-3.5 编号 : lucy-vton-latest并按2x的标准实时费率计费。 其他模型忽略了选项. 关闭标准模式的默认值 .

const realtimeClient = await client.realtime.connect(stream, {
  model: models.realtime("lucy-2.5"),
  speed: "fast",
  // ...
});

提供快速模式的模型在定义中列出 supportedSpeeds数字 :

models.realtime("lucy-2.5").supportedSpeeds; // ["fast"]
models.realtime("lucy-2.1").supportedSpeeds; // undefined

通过 speed 对于一个没有容量的模型,通过客户端的日志记录一个警告,会话以标准速度运行.

连接重试并拒绝会话

失败的连接会在前以指数回放(1 s- 10 s) 重拨最多5次 connect() 拒绝。 两次拒绝从未被重审,因为服务器会给出相同的答案: a 政策关闭(代码1008)和API 密钥的会话限制(接近 1013 “会话限制 已经到达。 会话限制拒绝 connect() 使用服务器信件的第一次尝试 (单位:千美元)Concurrent session limit reached.如果在届会确定后着陆,则届会结束 带有 sessionEnded 活动 reason 实值 "session_limit"。拒绝容量( 1013 “再次尝试” ) 后")是短暂的并仍在重复.

当服务器因能力不足拒绝拨号时,它也会发送 error_type: "capacity" (单位:千美元) retry_after 在几秒钟. connect() 然后等那么长(±20%焦急,至少1 s)和拨号 再说一次,只要 capacityRetryBudgetMs 允许(自第一次拨号起默认为60 000 ms),在 以服务器错误拒绝 . retries: 0 把这些再拨掉. onCapacityWait 报告 每个等待让应用程序显示:

const realtimeClient = await client.realtime.connect(stream, {
  model,
  capacityRetryBudgetMs: 30_000,
  onCapacityWait: ({ retryAfterMs }) => showStatus(`Server busy, retrying in ${Math.round(retryAfterMs / 1000)} s`),
  // ...
});

从会话队列中发出连接的应用程序应该关闭重试: 每一次重试都是一个 新的拨号,在排队等候的人之前需要一个空出的位置.

const realtimeClient = await client.realtime.connect(stream, {
  model,
  retries: 0, // dial once; on failure, rejoin your own queue
  // ...
});

realtimeClient.on("sessionEnded", ({ reason }) => {
  // "session_limit" | "policy_violation" | "moderation_violation" | "insufficient_credits" | ...
});

注意流线

连接的实时会话会暴露 SDK subscribeToken 一旦它到达一个 连接状态 。 和观众分享SDK的标志 client.realtime.subscribe 使用它从Decart请求只接收 LiveKit 证书,然后连接到 用于样式输出流的 LiveKit 房间。 不需要摄取相机 . 浏览器生成的流可以包括LiveKit帧元数据用于玻璃到玻璃 耐用,所以观众也需要浏览器运行时间,可以创建SDK的 fram-metadata 工作者; 不支持的运行时间在加入前拒绝这些符号 .

查看器必须是在这个 SDK 版本或更新. 现在的浏览器发布器 默认发布帧时间, 这使得服务器附加一个数据包 拖车在房间里的每一个框架。 年长的观众 @decartai/sdk 忽略符号 frame_timing 在没有脱衣工的情况下加入 连接成功但解码为无, 因此视频元素保持黑色 没有产生错误。 本地观众完全无法脱去拖车 以 UNSUPPORTED_PLATFORM_FEATURE。在升级前升级观众 出版社.

制作人 ——抓取当前会话中的符号:

const realtimeClient = await client.realtime.connect(stream, {
  model,
  onRemoteStream: (transformedStream) => {
    videoElement.srcObject = transformedStream;
  },
});

realtimeClient.on("connectionChange", (state) => {
  if ((state === "connected" || state === "generating") && realtimeClient.subscribeToken) {
    const subscribeToken = realtimeClient.subscribeToken;
    // Pass `subscribeToken` to the viewer snippet below.
  }
});

查看器 ——附送出品人相克之流:

import { createDecartClient, type RealTimeSubscribeClient } from "@decartai/sdk";

const client = createDecartClient({ apiKey: "your-api-key-here" });

const subscriber: RealTimeSubscribeClient = await client.realtime.subscribe({
  token: subscribeToken,
  onRemoteStream: (stream) => {
    videoElement.srcObject = stream;
  },
});

subscriber.on("connectionChange", (state) => {
  console.log(`Viewer state: ${state}`);
});

// Disconnect when done
subscriber.disconnect();

带有会话输入的查看器 - 也收到出版商寄来的东西(其相机和 麦克风),例如显示样式输出旁边的正本:

const subscriber = await client.realtime.subscribe({
  token: subscribeToken,
  onRemoteStream: (stream) => {
    outputVideo.srcObject = stream;
  },
  onInputStream: (stream) => {
    inputVideo.srcObject = stream;
  },
  inputVideoQuality: "low", // "low" | "medium" | "high" (default)
});

无 onInputStream 输入永远不会被下载. inputVideoQuality 设置最高 要接收的输入视频的 simulcast 层; SFU 仍然在带宽需要时向下走.

连接质量

有两层:a 飞行前 连接前检查,以及 会期 质量 在连接时发出信号。 两份关于共享 "good" | "fair" | "poor" | "critical" 比例- sDK报告,你决定怎么做(打开UI,警告用户等).

飞行前(连接前). 快速的,网络专用的可达性检查——它旋转起a 因此没有会话和费用:

const { quality, metrics, reasons } = await client.realtime.checkConnectivity();
// metrics: { transport: "udp" | "relay" | "failed", rttMs }
if (quality === "critical") showFallbackUI(reasons);

会期质量. 在连接时, SDK 从 WebRTC 数据中得出一个平滑的判决 (纬度、数据包丢失、带宽室、帧率)并告诉你哪个维度是 瓶颈 :

const realtimeClient = await client.realtime.connect(stream, {
  model,
  onRemoteStream: (s) => { videoElement.srcObject = s; },
  onConnectionQuality: ({ quality, limitingFactor, metrics }) => {
    // limitingFactor: "bandwidth" | "latency" | "loss" | "stall" | "cpu" | "none"
    // metrics: { rttMs, fps, packetLoss, upstreamJitterMs, availableUpstreamKbps, ... }
    console.log(quality, limitingFactor);
  },
});

// also available as an event and a getter:
realtimeClient.on("connectionQuality", (report) => { /* ... */ });
realtimeClient.getConnectionQuality(); // latest report, or null before the first sample

onConnectionQuality 编辑 connectionQuality 事件为 已卸载 他们只重新开火 当判决时quality编号 :limitingFactor)变化,所以它们不是活的量子饲料. 对a 连续读取原始数字,更新每个数据勾选(~1/s),使用 stats 事件或 民意调查 getConnectionQuality()?.metrics数字 :

realtimeClient.on("stats", (s) => updateLatencyHud(s.glassToGlass?.medianMs, s.video?.framesPerSecond));
// or, on your own interval:
setInterval(() => console.log(realtimeClient.getConnectionQuality()?.metrics.g2gMs), 1000);

玻璃对玻璃后座. 网络RTT在实时视频中隐藏主导成本——模式 推论——所以一个会话可以读出"好",而实际上可以感觉出拉吉. 在浏览器会话中, SDK 当需要的工人是 LiveKit 帧元数据时,自动附加一个捕获时间戳 可用; 服务器通过推论传播, SDK 匹配以输出播放. 这个表面 启动 (单位:千美元)ttffMs和 稳态 (单位:千美元)g2gMs延缓。 现在, 由玻璃对玻璃驱动,而不是RTT.

框架元数据目前在LiveKit中是实验性的,需要编码-转换支持. 它不会改变可见像素 . g2gDropRatio 遗 物 null 直到框架标识被传播 通过服务器管道和时间戳.

const realtimeClient = await client.realtime.connect(stream, {
  model,
});

// g2g updates every stats tick — read it from the `stats` event (the
// `connectionQuality` verdict is debounced and would go stale between changes):
realtimeClient.on("stats", ({ glassToGlass }) => {
  console.log(glassToGlass?.ttffMs, glassToGlass?.medianMs);
});

对a 测量 连接前的判决(而不是只检查网络),使用 深处 探测器:它短暂地打开了一个真实的会话 合成源, 测量玻璃对玻璃,然后 撕下来。 这需要 model 并花费一个短的 GPU 会话 :

const probe = await client.realtime.checkConnectivity({ deep: true, model });
console.log(probe.quality, probe.metrics.g2gMs, probe.metrics.ttffMs);

Async 处理( API 队列)

对于视频生成任务,使用队列 API 提交任务和结果民意调查:

import { createDecartClient, models } from "@decartai/sdk";

const client = createDecartClient({
  apiKey: "your-api-key-here"
});

// Submit and poll automatically
const result = await client.queue.submitAndPoll({
  model: models.video("lucy-latest"),
  prompt: "Make it look like a watercolor painting",
  data: videoFile,
  onStatusChange: (job) => {
    console.log(`Status: ${job.status}`);
  }
});

if (result.status === "completed") {
  videoElement.src = URL.createObjectURL(result.data);
} else {
  console.error("Job failed:", result.error);
}

或手动管理投票:

// Submit the job
const job = await client.queue.submit({
  model: models.video("lucy-latest"),
  prompt: "Make it look like a watercolor painting",
  data: videoFile
});
console.log(`Job ID: ${job.job_id}`);

// Poll for status
const status = await client.queue.status(job.job_id);
console.log(`Status: ${status.status}`);

// Get result when completed
if (status.status === "completed") {
  const blob = await client.queue.result(job.job_id);
  videoElement.src = URL.createObjectURL(blob);
}

客户端

薄荷短寿命客户端在您的服务器上代号, 而不是传送您的 API 密钥 . 答复中还附有一份署名的JWT(token任何服务器或边缘运行时间 可以验证 离线 对平台的公开 JWKS —— 没有 API 键, 没有 往返至德甲 :

import { createDecartClient, verifyClientToken, decodeClientToken } from "@decartai/sdk";

const client = createDecartClient({ apiKey: process.env.DECART_API_KEY });
const { apiKey, token } = await client.tokens.create({ expiresIn: 300, metadata: { service_tier: 0 } });

// Verify offline (EdDSA signature, exp, iss, aud) and read the claims
const claims = await verifyClientToken(token); // or client.tokens.verify(token)
claims.serviceTier; // 0
claims.pool; // "free" for tier 0, otherwise "paid"
// also: userId, organizationId, apiKeyName, apiKeyId, allowedModels, allowedOrigins,
// expiresAt, realtimeConcurrentSessionLimit, zeroDataRetention, attribution, raw

// Read claims WITHOUT verifying — no network, no crypto. Untrusted: display/logging only.
const untrusted = decodeClientToken(token);

JWKS来自 https://platform.decart.ai/api/auth/jwks (平台) 没有主机 baseUrl)并被缓存; JWT 库被如此懒散地装入 永远不能核实,不要运送。 错误 : TOKEN_INVALID, (中文(简体) ), TOKEN_EXPIRED, (中文(简体) ), TOKEN_VERIFY_ERROR (JWKS无法到达). 选项 : { jwksUrl, issuer, audience, clockTolerance }。这是离线检查,不是API电话。 它需要 WebCrypto: 打开 无此功能的运行时间( React Industrial) verify 拒绝方式 UNSUPPORTED_PLATFORM_FEATURE· ; decodeClientToken 到处工作.

托肯寿命:连接前的薄荷

客户签名过期 60秒钟 默认的薄荷后( e)expiresIn, 1-3600 s) (中文(简体) ). 一个标志 在页面载荷或组件挂载上被铸造的,通常在用户授予相机时已死 访问并按下开始, 稍后与同一种符号的重接也会被拒绝 。 SDK读取 标志 exp 在每次实时拨号之前(连接、重试和重接)并拒绝一个 已过期 TOKEN_EXPIRED 而不是拨号: 没有打开套接字, 消息说如何 很久以前就过期了 几秒钟的时钟被容忍.

两种方法保持 标志新鲜:

  • 早点把它薄荷 connect()之后 getUserMedia 和用户的点击和大小 expiresIn 连接窗口,例如. client.tokens.create({ expiresIn: 300 })。 。 。 .
  • 过 apiKeyProvider 而不是(或同时) apiKey. SDK在每次连接之前都叫它 并用它得来的东西重新连接和拨号,每个拨号都携带一个铸造的印记:
const client = createDecartClient({
  apiKeyProvider: async () => {
    // Your server: `client.tokens.create(...)` with your permanent API key.
    const res = await fetch("/api/realtime-token", { method: "POST" });
    const { apiKey } = await res.json();
    return apiKey;
  },
});

const realtimeClient = await client.realtime.connect(stream, { model, onRemoteStream });

如果供应商拒绝 connect(), (中文(简体) ), connect() 以这个错误拒绝; 在 重新连接一个提供者的故障会像其它的拨号故障一样被重试.

供应商还提供服务 process, (中文(简体) ), queue, (中文(简体) ), files 财务报告和审定财务报表 tokens: SDK之前就叫它来着 每个 HTTP 请求, 包括每个 submitAndPoll 状态民调和结果下载,所以一个 客户端也为批量任务工作(代理模式从不为HTTP请求调用). SDK没有 缓存它返回的东西; 提供者可能会发出它早先铸造的标志, 而该标志仍然存在 足够的生命了。 API在请求体完全到达后检查了信使,所以使用了一个信使 上传必须超过上传:用薄荷薄荷 expiresIn 它覆盖了您最大的上传.

反应原生/博览会

实时反应原生需要 LiveKit 的回放本地软件包 和早点 registerGlobals() 电话 平面 react-native-webrtc 没有 已支持。 SDK进口和 createDecartClient(...) 用法不变.

npm install @decartai/sdk [email protected] \
  @livekit/[email protected] \
  @livekit/[email protected]

从在路由器或应用程序之前运行的副作用模块调用 LiveKit 设置 切入点 :

// livekit-bootstrap.ts
import { registerGlobals } from "@livekit/react-native";

registerGlobals();
// index.ts
import "./livekit-bootstrap";
import "expo-router/entry"; // or import your root App component

随着全球注册,实时使用与网络上相同. 使用 模型的数值 FPS 当配置本地相机捕获,然后通过 MediaStream 给SDK:

import { createDecartClient, models, resolveFpsNumber } from "@decartai/sdk";
import { mediaDevices } from "@livekit/react-native-webrtc";

const client = createDecartClient({ apiKey: "your-api-key-here" });
const model = models.realtime("lucy-2.5");
const captureFps = resolveFpsNumber(model.fps);

const cameraStream = await mediaDevices.getUserMedia({
  audio: false,
  video: {
    facingMode: "user",
    frameRate: captureFps,
    width: model.width,
    height: model.height,
  },
});

const realtimeClient = await client.realtime.connect(cameraStream, {
  model,
  preferredVideoCodec: "vp8",
  onRemoteStream,
});

对于 Expo,请安装配置插件 :

npm install @livekit/[email protected] \
  @config-plugins/react-native-webrtc

把它们添加到 app.json数字 :

{
  "expo": {
    "plugins": [
      "@livekit/react-native-expo-plugin",
      "@config-plugins/react-native-webrtc"
    ]
  }
}

运行 npx expo prebuild 重建本地应用程序。 LiveKit 不在博览会运行 开始 赤裸回放原生应用程序必须遵循LiveKit的原生设置指令.

发送 mirror 和深层连通性飞行前仅限浏览器且与失败 UNSUPPORTED_PLATFORM_FEATURE 在反应土著。 与您一起映射本地预览 改为本土视频取景.

发展

设置

pnpm install

发展指挥部

  • pnpm build - 建设项目
  • pnpm dev:example - 运行 Vite dev 服务器以获取实例
  • pnpm test - 运行单元测试
  • pnpm test:e2e - 运行端到端测试
  • pnpm typecheck - 使用类型脚本进行类型检查
  • pnpm format - 有Biome格式代码
  • pnpm lint - 与Biome的林特密码

出版

  1. 版本缓冲运行 pnpm release 以折叠版本( 此使用) bumpp 以创建新版本标签)并推到 GitHub
  2. 自动出版: GitHub 动作工作流程将:
  • 构建工程
  • 发布到 npm
  • 创建带有更改日志的 GitHub 发布

软件包以 npm 的形式发布 @decartai/sdk。 。 。 .

许可证

麻省理工学院

版本与发布记录

@decartai/sdk 共发布 104 个版本,首次发布于 2025/09/30;过去 12 个月发布了 95 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.2.14latest2026/10/2517 天前
0.2.132026/10/2517 天前
0.2.122026/10/1627 天前
0.2.112026/10/1428 天前
0.2.102026/10/1230 天前
0.2.92026/10/111 个月前

关于 @decartai/sdk 的常见问题

@decartai/sdk 是什么?

Decart 的 Java 脚本 SDK

如何安装 @decartai/sdk?

在项目目录运行 npm install @decartai/sdk,或使用 pnpm add / yarn add / bun add。

@decartai/sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@decartai/sdk 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@decartai/sdk 可以商用吗?

@decartai/sdk 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@decartai/sdk 的下载量有多少?

根据 npm 官方下载统计,@decartai/sdk 在 2026/10/12 – 2026/11/10 这 30 天内被下载 225,078 次,日均约 7,503 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@decartai/sdk 还在维护吗?

最新版本 0.2.14 发布于 2026/10/25(17 天前);至今共发布 104 个版本,其中过去 12 个月发布了 95 个;首次发布于 2025/09/30。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。