解密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的林特密码
出版
- 版本缓冲运行
pnpm release以折叠版本( 此使用)bumpp以创建新版本标签)并推到 GitHub - 自动出版: GitHub 动作工作流程将:
- 构建工程
- 发布到 npm
- 创建带有更改日志的 GitHub 发布
软件包以 npm 的形式发布 @decartai/sdk。 。 。 .
许可证
麻省理工学院