路径
POST /video/submit/:taskId
公网入口 https://agentapi.kira.art/video/submit/:taskId。
这是
/video 子路由下唯一搬到 kira-agent 的端点(从 kira-be 整段挪过来,kira-be 那个会删)。其余 video 路由(initialize / task / info / upload DELETE)仍在 kira-cdn,不在本服务。认证
supabaseAuth() —— 仅 JWT,不接受 X-Internal-Key。
/video 子应用挂的是 supabaseAuth()(hono/jwk 验 ES256),跟 agent 端点的 eitherAuth() 不同 —— 这是面向终端用户的 retry 动作,没有服务器到服务器的调用方。userId 取自 jwtPayload.sub。
请求
无 body。taskId 走路径参数。
失败视频 task 的
taskId(对应 thread_version.videos[].taskId)。响应
| 码 | body | 含义 |
|---|---|---|
200 | { "success": true } | 已通过校验并重新触发 Trigger.dev 视频 task |
200 | { "error": "insufficient_credits" | "insufficient_plan" } | billing 复核仍不够格 —— 不重发,记一条 0 credit 的 tool_usage(c.json({error}) 无显式状态码 = 200) |
400 | { "error": "invalid_status", "message": "Video is not in an insufficient state" } | task 当前不是 insufficient_* 状态(其余状态 retry 无意义);代码 c.json({...}, 400) |
400 | { "message": "Task ID is required" } | 缺 taskId 路径参数 |
401 | { "message": "Unauthorized" } | 缺/无效 JWT,jwtPayload.sub 为空 |
404 | { "message": "Video task not found" } | 在该用户的 thread_version.videos 里找不到这个 taskId |
500 | { "message": "Failed to update video status" | "Failed to submit video task" } | 写 JSONB 失败 / 触发 Trigger.dev task 失败 |
两个
error 分支的状态码不同(以代码为准):- billing 不够格(
insufficient_*)→200{error: reason}(c.json({error})不带显式状态)。 invalid_status(task 不在insufficient_*状态)→400{error, message}(c.json({...}, 400))。
400 / 401 / 404 / 500。机制
仅对处于insufficient_credits / insufficient_plan 状态的视频生效 —— 用户在前端点 “Start” 重试时调用。
定位 video
在
thread_version 表里按 resource_id = userId + videos @> [{taskId}] 查出那一行,VideoSchema.parse 后用 taskId 找到数组下标。找不到 → 404。校验状态
video.status 必须是 insufficient_credits 或 insufficient_plan,否则返 400 {error:"invalid_status", message}。billing 复核(只读)
cost = getVideoCreditsCost(video.toolName, duration ?? 5)(duration 取 input.duration ?? output.duration),再 checkVideoEligibility(userId, cost)。不够格 → 记 0 credit tool_usage 并返 200 {error: reason}。这里不扣 credits,真扣在 worker 里。重新触发 Trigger.dev task
publishVideoTask({ taskId, userId, threadId, toolName, provider: video.provider ?? "seedance", input }) —— 内部 tasks.trigger(taskId, payload, { tags, priority }),按 toolName[:provider] 路由到对应 task id(如 generateVideo:seedance → video-generation-seedance),并打上 videoTask:<taskId> tag。失败 → 500。示例
源
src/hono/video/index.ts(handler + supabaseAuth() 挂载)、checkVideoEligibility / getVideoCreditsCost at src/ai/libs/billing.ts、publishVideoTask at src/lib/tasks.ts