跳转到内容

SDK 与 API 示例

下面是一组可串联执行的 API 示例:登录、刷新 token、创建房间、创建 WebSocket ticket、连接 Realtime、读取播放状态、处理错误和调用 Provider。字段完整定义以 OpenAPI JSON 和 protobuf 为准。

先读 客户端集成指南 理解总体约定,再按示例落地代码。

目标接口
生成多语言 SDKHTTP OpenAPI
强类型服务端或桌面客户端gRPC/protobuf
房间实时消息、聊天、播放同步WebSocket Realtime
管理实例和运维CLI 或 management gRPC
Provider 浏览、登录、代理HTTP Provider routes 或 provider gRPC

启动带 OpenAPI 的服务:

Terminal window
cargo run -p synctv --features openapi --bin synctv -- serve

导出 schema:

Terminal window
curl -fsSL http://localhost:8080/api-docs/openapi.json -o openapi.json

TypeScript 类型:

Terminal window
npx openapi-typescript openapi.json -o synctv-api.d.ts

完整入口见 OpenAPI 文档入口

Terminal window
BASE_URL=http://localhost:8080
curl -sS "$BASE_URL/api/auth/opaque/login/start" \
-H 'Content-Type: application/json' \
-d '{"username":"root","credentialRequest":[/* OPAQUE 客户端生成的字节 */]}'

继续调用 /api/auth/opaque/login/finish 完成 OPAQUE 交换。如果 finish 响应里 mfa.required=true,继续完成 MFA。无密码邮箱 token 登录使用 /api/auth/email/confirm

浏览器示例使用 protobufjs 生成的类型名作为说明,实际导入路径取决于你的构建。

const ws = new WebSocket(`wss://app.example.com/ws/rooms/${roomId}?ticket=${ticket}`);
ws.binaryType = 'arraybuffer';
ws.onmessage = async (event) => {
const bytes =
event.data instanceof Blob
? new Uint8Array(await event.data.arrayBuffer())
: new Uint8Array(event.data);
const message = ServerMessage.decode(bytes);
dispatchServerMessage(message);
};
function send(message: ClientMessage) {
ws.send(ClientMessage.encode(message).finish());
}
send({
observeResource: {
observeId: 'playback-state',
version: cachedVersion ?? '',
deliveryMode: 2,
playbackState: {},
},
});

资源观察、delivery mode、重连和错误处理见 Realtime API

公开 gRPC 共用主端口:

Terminal window
grpcurl -plaintext localhost:8080 list synctv.client.AuthService

本地密码登录只支持 OPAQUE。客户端先生成 credential request,调用 StartOpaqueLogin,再用 FinishOpaqueLogin 完成登录:

Terminal window
grpcurl -plaintext \
-d '{"username":"root","credentialRequest":"<base64-opaque-request>"}' \
localhost:8080 synctv.client.AuthService/StartOpaqueLogin

AuthService/Login 只用于无密码邮箱 token 登录。

房间内 RPC 需要 room metadata:

Terminal window
grpcurl -plaintext \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "x-room-id: $ROOM_ID" \
-d '{}' \
localhost:8080 synctv.client.RoomService/GetPlayback

不要把管理端点暴露给普通客户端。CLI/management gRPC 是运维控制面,和公开 gRPC 不是同一个入口。

Provider 管理 API 用于实例配置;Provider 业务 API 用于登录、浏览、搜索或解析。

Terminal window
curl -sS "$BASE_URL/api/providers/instances/available" \
-H "Authorization: Bearer $ACCESS_TOKEN"

Alist 列表请求示例:

Terminal window
curl -sS "$BASE_URL/api/providers/alist/list" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"serverId":"<serverId-from-login-or-binds>","path":"/","instanceName":"alist-main"}'

添加媒体时,sourceProviderproviderInstanceNamesourceConfig 的组合由 Provider 定义。Provider 凭据由用户、实例或服务端 Provider 管理层解析。

HTTP 错误响应:

{
"error": "Invalid username or password",
"status": 401,
"code": 1002,
"requestId": "01HX..."
}

客户端规则:

  • 按 HTTP status 决定大类。
  • code 做程序化分支。
  • 记录 requestId,便于服务端日志排查。
  • 429 时读取 Retry-After
  • 5xx 文案会被服务端脱敏,不要依赖原始错误文本。

完整错误码见 错误参考

操作处理
登录、MFA、OAuth2 exchange不要无脑重试;失败可能触发限流或 state 失效
读取列表、设置、播放状态可按退避重试;Realtime 资源观察优先使用版本判断
创建房间、添加媒体、修改设置请求超时后先重新读取资源,避免重复创建
WebSocket 断线重新申请 ticket,重建观察,带上缓存版本
Provider 请求对上游超时做退避,区分凭据失效和上游不可用