跳到主要内容

接收项目通知

配置接收服务、验证通知,并在 CaptionBolt 项目变化时测试工作流。

集成能力向 Max 订阅用户开放。视频处理使用账户现有的时长和套餐限制。
打开集成设置

准备接收服务

视频可供检查、导出完成、处理失败或项目取消时,Webhooks 会向应用发送 HTTP 请求。集成能力向 Max 订阅用户开放。

需要接受 POST 的公共 HTTPS URL,仅支持 443 端口。localhost 和私有网络地址无法直接接收,CaptionBolt 不跟随重定向。本地测试可通过公共 HTTPS 隧道连接接收服务。

示例使用 https://receiver.example/captionbolt,请替换为实际接收地址。

添加接收地址

  1. 打开设置 → 集成。
  2. 填写 HTTPS 接收地址 并选择事件。
  3. 点击 添加 Webhook。
  4. 保存显示的签名密钥,它只显示一次。

接收服务用此密钥验证通知;它与 API Key 是不同的密钥。

也可通过 REST 创建地址。按 API 指南将 CAPTIONBOLT_API_KEY 设置为拥有 webhooks:manage 权限的密钥:

curl --fail-with-body https://api.captionbolt.com/v1/webhooks \
  -H "Authorization: Bearer $CAPTIONBOLT_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"url":"https://receiver.example/captionbolt","events":["project.completed","project.failed"]}'

响应返回接收地址的 id 和签名 secret。将密钥安全地存入接收服务环境。

选择事件

| 事件 | 含义 | | --- | --- | | project.ready | 视频处理完成,可供检查或导出 | | project.completed | 导出完成,可获取结果;默认选中 | | project.failed | 处理或导出失败;默认选中 | | project.cancelled | 项目已取消 |

事件覆盖账户中符合条件的视频项目,无论通过网站、REST 或 MCP 创建。新地址只接收之后发生的事件,不重放之前的项目变化。不包含独立 Transcripts、已删除或超出访问期的项目。

project.ready 不表示视频已导出,也不表示用户已人工检查。

{
  "id": "event-uuid",
  "type": "project.completed",
  "createdAt": "2026-09-27T12:00:00.000Z",
  "data": {
    "projectId": "project-uuid",
    "status": "completed",
    "stage": "export",
    "resultUrl": "https://api.captionbolt.com/v1/projects/project-uuid/result"
  }
}

事件只含元数据,不含视频文件或字幕文本。data.resultUrl 是需要鉴权的 REST 端点。用具有 projects:read 的 API Key 获取新下载链接,再下载文件;下载文件时不发送密钥。参见下载结果。

验证收到的请求

CaptionBolt 使用 Standard Webhooks。解析或处理前,针对未经修改的原始请求体验证签名。请求头为 webhook-id、webhook-timestamp 和 webhook-signature。

Node.js 接收服务示例

此最小示例验证签名并打印事件 ID 和类型,供测试投递。示例使用 Node.js 24,接收服务也可用其他语言实现。在自己的接收服务项目中安装 JavaScript 验证库:

npm install standardwebhooks
read -r -s -p 'CaptionBolt signing secret: ' CAPTIONBOLT_WEBHOOK_SECRET
export CAPTIONBOLT_WEBHOOK_SECRET
printf '\n'

保存以下代码为 receiver.mjs:

import { createServer } from "node:http";
import { Webhook } from "standardwebhooks";

const secret = process.env.CAPTIONBOLT_WEBHOOK_SECRET;
if (!secret) throw new Error("Set CAPTIONBOLT_WEBHOOK_SECRET.");
const verifier = new Webhook(secret);

createServer(async (request, response) => {
  if (request.method !== "POST" || request.url !== "/captionbolt") {
    response.writeHead(404).end();
    return;
  }
  let event;
  try {
    const chunks = [];
    let size = 0;
    for await (const chunk of request) {
      size += chunk.length;
      if (size > 65536) {
        response.writeHead(413).end();
        return;
      }
      chunks.push(chunk);
    }
    const rawBody = Buffer.concat(chunks).toString("utf8");
    event = verifier.verify(rawBody, {
      "webhook-id": request.headers["webhook-id"],
      "webhook-timestamp": request.headers["webhook-timestamp"],
      "webhook-signature": request.headers["webhook-signature"],
    });
  } catch {
    response.writeHead(400).end("Invalid webhook");
    return;
  }
  console.log("Verified event:", event.id, event.type);
  response.writeHead(204).end();
}).listen(3000, "127.0.0.1");

运行 node receiver.mjs,通过 HTTPS 服务或公共 HTTPS 隧道公开 /captionbolt。CaptionBolt 需访问公共 HTTPS URL,而非本地地址。

验证库检查签名和时间戳,需保持服务器时钟准确。验证前不要解析并重新序列化 JSON,也不要记录签名密钥或完整请求体。

生产工作流应将打印替换为持久化接收:按 id 去重,先保存事件或任务,再返回 2xx,并异步处理。持久化失败应返回错误,以便 CaptionBolt 重试。示例只验证接收,不提供持久化队列,也不下载结果。

发送测试

  1. 启动接收服务并配置签名密钥。
  2. 在设置 → 集成打开对应地址,选择 发送测试。
  3. 在投递记录中确认投递成功。
  4. 确认接收服务记录了通过验证的 webhook.test。

每个地址同时只能有一个测试。等待测试结束,再等至少 60 秒后发送下一个测试。手动重新投递也有冷却时间,请遵循返回的等待时间。

单独处理 webhook.test,它不代表视频完成。用之后发生的真实项目事件测试结果获取。

投递失败时,检查公共 URL、签名密钥、原始请求体处理和接收响应。需在 15 秒内确认接收;非 2xx、连接错误或无响应会触发重试。

处理重试和密钥变更

通知可能重复或乱序。按事件 ID 去重;工作流需要最新状态时,查询项目当前状态。

CaptionBolt 自动尝试三次:首次请求、首次失败约一分钟后重试、第二次失败约五分钟后再次重试。第三次失败后停止自动投递。修复接收服务后,在设置中选择 重新投递,保留事件 ID 并开始新一轮三次尝试。投递记录保留 30 天。

通过 轮换密钥 更换签名密钥。保存新密钥并更新接收服务。旧密钥在 24 小时内仍有效,期间投递包含新旧密钥的签名;重叠期结束前无法再次轮换。

停用地址会停止待投递任务,已发送中的请求可能完成。删除地址还会删除投递记录。删除项目或项目访问期结束,会停止待投递项目通知。Webhooks 不延长 14 天访问期,请在到期前获取并保存结果。

我们使用 Cookie 记住你的偏好、衡量网站表现,并持续改进 CaptionBolt。