mcpField
C
Convertrilo

Convertrilo

本地服务
github.com/serkandrgn媒体与设计014 周前更新

关于 Convertrilo

Convertrilo 是用于提交和管理视频编码任务的 TypeScript SDK,并附带命令行工具。它适合需要在脚本、CI 或 Agent 工作流中调用 Convertrilo API 的开发者,支持多种来源、输出目标及任务管理操作。

主要功能

  1. 01创建和查询编码任务
  2. 02视频文件夹批量导入
  3. 03保存编码预设与输出目标
  4. 04支持 VMAF 优化编码
  5. 05管理 Webhook 与投递记录
  6. 06幂等创建及文件清理

适用场景

  1. 01在 CI 或定时任务中编码视频
  2. 02将 S3 文件夹视频批量排入编码
  3. 03将编码结果交付至 S3 或 Google Drive
  4. 04从脚本检查任务状态或取消任务

MCP 相关

软件包包含 stdio MCP 服务 convertrilo-mcp,可将视频编码任务操作接入 Agent 和工作流。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"serkandrgn-convertrilo": {
"command": "npx",
"args": [
"-y",
"@convertrilo/sdk"
]
}
}
}
启动命令npx -y @convertrilo/sdk

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@convertrilo/sdk0.1.2

工具

5

收录的工具列表 · 更新于 2 周前

参数类型必填说明
fpsnumber否
codecenum否h264 | h265 | av1
passesenum否1 | 2
presetenum否fast | standard | slow
qualityenum否good | better | best
webhookstring否
metadataobject否
optimizeenum否none | vmaf
outputS3object否
outputS3.keystring否
outputS3.bucketstring是
outputS3.regionstring否
outputS3.endpointstring否
outputS3.accessKeyIdstring否
outputS3.forcePathStyleboolean否
outputS3.secretAccessKeystring否
priorityenum否normal | high
containerenum否mp4 | mkv | webm | mov
sourceUrlstring是可读取的源视频 URL。
externalIdstring否
resolutionenum否480p | 720p | 1080p | 1440p | 2160p
vmafTargetnumber否
idempotencyKeystring否

详细介绍

Convertrilo TypeScript SDK

适用于 Convertrilo API 的类型安全客户端。

VMAF 和编码轮次

请求 optimize: "vmaf" 时,Convertrilo 会进行 VMAF 采样,并执行一次优化后的最终编码。为保持向后兼容,仍接受提供的 passes: 2 值,但 API 实际使用并计费的有效轮次为一次。

定价响应会公开 requestedPasses 和 effectivePasses。新的集成应在使用 VMAF 时设置 passes: 1。

安装

pnpm add @convertrilo/sdk

该软件包目前面向提供全局 fetch 的现代 Node.js 运行时。如果你的运行时不提供 fetch,请向客户端传入 fetchImpl。

CLI 和 MCP 自动化

该软件包包含两个可执行的自动化工具:

export CONVERTRILO_API_KEY="cvr_..."

convertrilo encode https://example.com/input.mp4 \
  --codec h264 \
  --resolution 1080p \
  --audio-policy transcode-aac \
  --frame-rate-policy cap \
  --scale-policy no-upscale \
  --quality better \
  --wait \
  --json

convertrilo-mcp

脚本、CI、cron 和本地操作请使用 convertrilo。Agent 和工作流集成请将 convertrilo-mcp 用作 stdio MCP 服务。

运行 convertrilo login 或 convertrilo init 可在本地保存 API 密钥;也可以不带参数运行 convertrilo,启动交互式编码向导。等待中的命令默认会显示终端进度,并确保 --json 输出干净,便于脚本使用。

可通过以下命令获取 Shell 补全代码片段:

convertrilo completion zsh

请参阅 docs/CLI-AND-MCP.md,了解命令、MCP 客户端配置、S3 输出示例、VMAF、双轮编码、状态、取消和余额工作流。

如果你想要最简单的终端操作指南,请从 docs/CLI-QUICKSTART.md 开始。

客户端配置请参阅 docs/MCP-QUICKSTART.md。

MCP 注册表元数据位于 server.json。

创建客户端

import { ConvertriloClient } from "@convertrilo/sdk";

const client = new ConvertriloClient({
  baseUrl: "https://api.convertrilo.com",
  apiKey: process.env.CONVERTRILO_API_KEY,
});

服务器到服务器集成请使用 API 密钥。浏览器应用应调用你自己的后端,再由后端调用 Convertrilo。

示例

examples/ 目录包含主要集成路径的入门脚本:

  • node-url-to-cdn.ts - 编码公开 URL,并获取签名的 CDN 下载 URL
  • node-url-to-s3.ts - 编码公开 URL,并将结果上传到 S3/S3 兼容存储
  • google-drive-byo-token.ts - 使用客户自有服务账号将输出上传到 Google Drive
  • folder-ingest-s3.ts - 为 S3 前缀中的每个视频排队创建一个编码作业
  • idempotency.ts - 安全地重试 createJob 和 createJobsBulk
  • webhook-receiver-hmac.ts - 在 Node 接收器中验证托管 Webhook 的 HMAC 签名

本地 SDK 冒烟测试使用 .env,但已发布的 SDK 用户应通过自己的服务器环境提供凭据。不要将 Convertrilo API 密钥或客户存储令牌放入前端代码。

如需了解完整的服务器到服务器操作指南,涵盖 URL、S3、文件夹导入、Google Drive 服务账号、轮询和 Webhook,请参阅 docs/API-INTEGRATION-GUIDE.md。

幂等作业创建

从后端重试创建调用时,请使用幂等键。使用相同请求正文重复使用同一个键,会返回原始响应,而不会创建重复作业。

const job = await client.createJob({
  externalId: "upload-123",
  metadata: { customerId: "cus_123" },
  codec: "h264",
  resolution: "1080p",
  fps: 30,
}, {
  idempotencyKey: "job-upload-123",
});

const batch = await client.createJobsBulk({
  jobs: [
    {
      externalId: "batch-42:clip-1",
      codec: "h264",
      resolution: "1080p",
      fps: 30,
      sourceS3: { bucket: "source", key: "clip-1.mp4" },
    },
  ],
  settings: { confirm: true },
}, {
  idempotencyKey: "bulk-batch-42",
});

作业文件清理

作业进入终止状态后,请删除托管的上传和输出对象:

await client.cancelJob(jobId); // required first for created, queued, or running jobs

const result = await client.deleteJobFiles(jobId);
console.log(result.objectsDeleted, result.jobRetained);

作业记录和计费历史仍可供审计。活动作业会返回稳定的 job_active 错误,直到作业被取消。

已保存的编码预设

保存可重复使用的编码设置,而不存储源 URL、存储凭据或输出密钥:

const preset = await client.createEncodePreset({
  name: "Default 1080p web MP4",
  settings: {
    codec: "h264",
    resolution: "1080p",
    fps: 30,
    preset: "standard",
    bitrateTier: "medium",
    passes: 1,
    policy: "fastest",
    container: "mp4",
    quality: "better",
    optimize: "none",
    vmafTarget: 93,
    audioPolicy: "transcode-aac",
    frameRatePolicy: "cap",
    scalePolicy: "no-upscale",
  },
});

const { presets } = await client.getEncodePresets();

已保存的输出目标

保存可重复使用的交付目标,而不在目标本身存储原始存储密钥。S3 目标会引用加密保存的 S3 凭据:

const destination = await client.createOutputDestination({
  name: "Customer uploads bucket",
  config: {
    type: "s3",
    credentialId: "0f5a7f2b-4ff2-45d4-b76f-1f7b6e98d4d1",
    keyPrefix: "processed/",
  },
});

const { destinations } = await client.getOutputDestinations();

URL 源到 CDN 输出

const job = await client.onDemandEncode({
  sourceUrl: "https://example.com/input.mp4",
  externalId: "customer-video-123",
  metadata: {
    customerId: "cus_123",
    workflow: "daily-compression",
  },
  codec: "h264",
  resolution: "1080p",
  quality: "better",
  audioPolicy: "transcode-aac",
  frameRatePolicy: "cap",
  scalePolicy: "no-upscale",
}, {
  idempotencyKey: "encode-customer-video-123",
});

let finalStatus;
while (true) {
  finalStatus = await client.onDemandStatus(job.jobId);

  if (finalStatus.status === "success") break;
  if (finalStatus.status === "failed") {
    throw new Error(finalStatus.failureMessage || "Encoding failed");
  }

  await new Promise((resolve) => setTimeout(resolve, 5000));
}

console.log(finalStatus.downloadUrl);
console.log(finalStatus.requestedExecution);
console.log(finalStatus.effectiveExecution);
console.log(finalStatus.sourceProbe?.color);
console.log(finalStatus.outputProbe);

终端用户可以通过以下命令查看同一份报告:

convertrilo status JOB_ID --json
convertrilo wait JOB_ID --json

URL 源到 S3 输出

const job = await client.onDemandEncode({
  sourceUrl: "https://example.com/input.mp4",
  codec: "h264",
  resolution: "1080p",
  outputS3: {
    bucket: "customer-output-bucket",
    key: "encoded/input-1080p.mp4",
    region: "us-east-1",
    accessKeyId: process.env.CUSTOMER_S3_ACCESS_KEY_ID,
    secretAccessKey: process.env.CUSTOMER_S3_SECRET_ACCESS_KEY,
  },
});

console.log(job.jobId);

对于 S3 兼容服务,请传入 endpoint,通常还应设置 forcePathStyle: true。

URL 源转换为 Google Drive 输出

对于无头 API 集成,请保存一个客户自有的 Google 服务账号,之后即可重复使用。 使用 Google Shared Drive 作为输出位置,并将返回的服务账号邮箱添加为成员, 授予其创建文件的权限。

const credential = await client.createGoogleDriveCredential({
  name: "Production Drive",
  serviceAccount: JSON.parse(process.env.GOOGLE_SERVICE_ACCOUNT_JSON!),
});

const job = await client.onDemandEncode({
  sourceUrl: "https://example.com/input.mp4",
  codec: "h264",
  resolution: "1080p",
  outputGoogleDrive: {
    folderId: "GOOGLE_DRIVE_FOLDER_ID",
    fileName: "input-1080p.mp4",
    credentialId: credential.id,
  },
});

console.log(job.jobId);

Dashboard 的 Google Picker 授权与 SDK 自动化相互独立。

文件夹导入

在 S3 前缀中为每个视频排入一个任务:

const batch = await client.onDemandIngestFolder({
  externalIdPrefix: "batch-2026-06-09",
  metadata: {
    customerId: "cus_123",
    workflow: "folder-compression",
  },
  sourceS3: {
    bucket: "customer-source-bucket",
    prefix: "incoming/",
    region: "us-east-1",
    accessKeyId: process.env.CUSTOMER_S3_ACCESS_KEY_ID,
    secretAccessKey: process.env.CUSTOMER_S3_SECRET_ACCESS_KEY,
  },
  outputDestination: "s3",
  outputS3: {
    bucket: "customer-output-bucket",
    prefix: "encoded/",
    region: "us-east-1",
    accessKeyId: process.env.CUSTOMER_S3_ACCESS_KEY_ID,
    secretAccessKey: process.env.CUSTOMER_S3_SECRET_ACCESS_KEY,
  },
  codec: "h264",
  maxFiles: 25,
  resolution: "1080p",
}, {
  idempotencyKey: "folder-batch-2026-06-09",
});

for (const job of batch.jobs || []) {
  console.log(job.jobId, job.externalId, job.fileName);
}

使用 maxFiles 限制从文件夹中发现并排入队列的视频数量。

在 Google Drive 文件夹中为每个视频排入一个任务:

const batch = await client.onDemandIngestFolder({
  sourceGoogleDrive: {
    folderId: "SOURCE_FOLDER_ID",
    credentialId: credential.id,
  },
  outputDestination: "google-drive",
  outputGoogleDrive: {
    folderId: "OUTPUT_FOLDER_ID",
    credentialId: credential.id,
  },
  codec: "h264",
  maxFiles: 25,
  resolution: "1080p",
});

for (const job of batch.jobs || []) {
  console.log(job.jobId, job.fileName);
}

每个 worker 启动时,Convertrilo 会使用加密的服务账号凭据生成短时有效的 Google 令牌。

使用 client.onDemandStatus(jobId) 轮询每个返回的 jobId。

Webhook 投递历史

托管的 webhook 使用 HMAC 签名。你可以测试 webhook 并检查近期的投递尝试:

await client.testWebhook(webhookId);

const history = await client.getWebhookDeliveries(webhookId);
for (const delivery of history.deliveries || []) {
  console.log(delivery.status, delivery.statusCode, delivery.event);
}

重新生成类型

SDK 类型根据 openapi.yaml 生成。

pnpm run generate
pnpm run build

生成脚本使用 --default-non-nullable false,因此 OpenAPI 默认值在 TypeScript 请求体中仍为可选项。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。