网络钩子
在 AWS Lambda 上渲染时,Remotion 可以发送 webhooks 来通知你渲染何时结束,无论是成功还是失败。本页面描述了 webhook 的负载以及如何设置 webhook API 端点。
🌐 When rendering on AWS Lambda, Remotion can send webhooks to notify you when the render ends, successfully or with failures. This page describes the webhook payloads and how to set up a webhook API endpoint.
请参考 renderMediaOnLambda() 文档以了解如何在启用 webhook 的情况下触发渲染。
🌐 Refer to the renderMediaOnLambda() documentation to learn how to trigger a render with webhooks enabled.
设置
🌐 Setup
你需要设置一个带有 POST 请求处理程序的 API 端点。确保该端点可访问并接受来自 AWS 的请求。
🌐 You will need to set up an API endpoint with a POST request handler. Make sure that the endpoint is reachable and accepts requests from AWS.
如果你在本地机器(即“localhost”上)运行webhook端点,你需要使用像[tunnelmole](https://tunnelmole.com/docs)这样的开源隧道工具或[ngrok](https://ngrok.com/)这类流行的闭源隧道工具来设置一个公共反向代理。运行任一工具都会生成一个公共URL,转发到localhost上的服务。
Response
每个 webhook 都有以下头信息:
🌐 Every webhook has the following headers:
{
"Content-Type": "application/json",
"X-Remotion-Mode": "production" | "demo",
"X-Remotion-Signature": "sha512=HASHED_SIGNATURE" | "NO_SECRET_PROVIDED",
"X-Remotion-Status": "success" | "timeout" | "error",
}你可以使用这些头信息来验证请求的真实性,检查渲染过程的状态,以及检查 webhook 是否从部署在 AWS 的生产代码或像下面的工具或你自己的测试套件这样的演示应用中调用。
🌐 You can use these headers to verify the authenticity of the request, to check the status of your rendering process and to check whether the webhook was called from production code deployed to AWS or a demo application such the tool below or your own test suite.
请求体具有以下结构:
🌐 The request body has the following structure:
type StaticWebhookPayload = {
renderId: string;
expectedBucketOwner: string;
bucketName: string;
customData: Record<string, unknown> | null;
};
export type WebhookErrorPayload = StaticWebhookPayload & {
type: 'error';
errors: {
message: string;
name: string;
stack: string;
}[];
};
export type WebhookSuccessPayload = StaticWebhookPayload & {
type: 'success';
lambdaErrors: EnhancedErrorInfo[];
outputUrl: string | undefined;
outputFile: string | undefined;
timeToFinish: number | undefined;
costs: AfterRenderCost;
};
export type WebhookTimeoutPayload = StaticWebhookPayload & {
type: 'timeout';
};
export type WebhookPayload = WebhookErrorPayload | WebhookSuccessPayload | WebhookTimeoutPayload;字段 renderId、bucketName 将会 像 renderMediaOnLambda() 本身返回它们一样返回。
🌐 The fields renderId, bucketName will be returned just like they are returned by renderMediaOnLambda() itself.
你可以使用字段 customData 来设置一个可序列化为 JSON 的对象,这对于向 webhook 端点传递自定义数据非常有用。customData 字段在序列化后必须小于 1KB(1024 字节),否则会抛出错误。将较大的数据存储在 inputProps 中,并通过调用 getRenderProgress() 并读取 progress.renderMetadata.inputProps 来取回。
🌐 You can use the field customData to set a JSON-serializable object, which is useful to pass on custom data to the webhook endpoint. The customData field must be less than 1KB (1024 bytes) when serialized, otherwise an error is thrown. Store larger data in inputProps and retrieve it back by calling getRenderProgress() and reading progress.renderMetadata.inputProps.
如果渲染进程超时,响应体将不包含任何其他字段。
🌐 If the render process times out, the reponse body will not contain any other fields.
outputUrl、outputFile 和 timeToFinish 键仅在渲染成功时返回。请注意,即使渲染过程成功,仍可能存在非致命的 lambdaErrors:
🌐 The outputUrl, outputFile and timeToFinish keys are only returned if the render was successful. Note that a successful render process may still have non-fatal lambdaErrors:
{
"s3Location": "string",
"explanation": "string" | null,
"type": "renderer" | "browser" | "stitcher",
"message": "string",
"name": "string",
"stack": "string",
"frame": "number"| null,
"chunk": "number"| null,
"isFatal": "boolean",
"attempt": "number",
"willRetry": "boolean",
"totalAttempts": "number",
"tmpDir": {
"files": [{
"filename": "string",
"size": "number",
}],
"total": "number"
} | null,
}errors 数组将包含在渲染过程中发生的任何 致命 错误的错误信息和堆栈跟踪。
🌐 The errors array will contain the error message and stack trace of any fatal error that occurs during the render process.
验证 Webhooks
🌐 Validate Webhooks
如果你在 CLI 参数中提供了 webhook 密钥,Remotion 将对所有 webhook 请求进行签名。
🌐 Remotion will sign all webhook requests if you provide a webhook secret in the CLI arguments.
如果你不提供密钥,X-Remotion-Signature 将被设置为 NO_SECRET_PROVIDED。无法验证使用 NO_SECRET_PROVIDED 签名发送的 webhook 请求的真实性和数据完整性。如果你想验证传入的 webhook,必须提供 webhook 密钥。
Remotion 使用 HMAC 和 SHA-512 算法 对其发送的 Webhook 请求进行加密签名。这使你能够验证传入 Webhook 请求的真实性和数据完整性。
🌐 Remotion uses HMAC with the SHA-512 algorithm to cryptographically sign the webhook requests it sends. This allows you to verify the authenticity and data integrity of incoming webhook requests.
为了验证 webhook 请求,你需要使用提供的 webhook 密钥和请求正文创建 SHA-512 HMAC 签名的十六进制摘要。如果它与 X-Remotion-Signature 头匹配,则该请求确实是由 Remotion 发送的,并且其请求正文是完整的。
🌐 In order to verify a webhook request, you will need to create a hex digest of a SHA-512 HMAC signature using your provided webhook key and the request body. If it matches the X-Remotion-Signature header, the request was indeed sent by Remotion and its request body is complete.
如果不匹配,要么数据完整性受到破坏且请求体不完整,要么请求不是由 Remotion 发送的。
🌐 If it does not match, either the data integrity is compromised and the request body is incomplete or the request was not sent by Remotion.
这就是 Remotion 计算签名的方式:
🌐 This is how Remotion calculates the signature:
import * as Crypto from "crypto";
function calculateSignature(payload: string, secret?: string) {
if (!secret) {
return "NO_SECRET_PROVIDED";
}
const hmac = Crypto.createHmac("sha512", secret);
const signature = "sha512=" + hmac.update(payload).digest("hex");
return signature;
}在你的 webhook 端点中,payload 参数是请求体,secret 参数是你的 webhook 密钥。
🌐 In your webhook endpoint, the payload parameter is the request body and the secret parameter is your webhook secret.
你可以使用 validateWebhookSignature() 函数在签名无效时抛出错误,而不是自己验证签名。
🌐 Instead of validating the signature yourself, you can use the validateWebhookSignature() function to throw an error if the signature is invalid.
示例 Webhook 端点(Express)
🌐 Example webhook endpoint (Express)
你可以使用任何网络框架和语言来设置你的 webhook 端点。以下示例使用 JavaScript 和 Express 框架编写,我们使用 expressWebhook() 来简化该过程。
🌐 You can use any web framework and language to set up your webhook endpoint. The following example is written in JavaScript using the Express framework, we are using expressWebhook() to simplify the process.
server.jsconst ENABLE_TESTING = false; // ---cut--- import express from 'express'; import bodyParser from 'body-parser'; import {expressWebhook} from '@remotion/lambda/client'; const router = express(); const jsonParser = bodyParser.json(); const handler = expressWebhook({ secret: 'mysecret', testing: ENABLE_TESTING, onSuccess: ({renderId}) => console.log('Finished render', renderId), onTimeout: ({renderId}) => console.log('Time out', renderId), onError: ({renderId}) => console.log('Error', renderId), }); router.post('/webhook', jsonParser, handler); router.options('/webhook', jsonParser, handler); router.listen(3000, () => { console.log('Server is running on port 3000'); });
这也可以手动完成,以便对端点的逻辑拥有最大的控制权:
🌐 This can also be done manually, to have the maximum control over the endpoint's logic:
server.jsimport express from 'express'; import bodyParser from 'body-parser'; import {validateWebhookSignature} from '@remotion/lambda/client'; const router = express(); const jsonParser = bodyParser.json(); const handler = (req, res) => { // add headers to enable testing const ENABLE_TESTING = true; if (ENABLE_TESTING) { res.setHeader('Access-Control-Allow-Origin', 'https://www.remotion.dev'); res.setHeader('Access-Control-Allow-Methods', 'OPTIONS,POST'); res.setHeader('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, X-Remotion-Status, X-Remotion-Signature, X-Remotion-Mode'); } // dont go forward if just testing if (req.method === 'OPTIONS') { // custom code to handle OPTIONS request // logger(req).info('OPTIONS request received'); res.status(200).end(); return; } // validate the webhook signature validateWebhookSignature({ signatureHeader: req.header('X-Remotion-Signature'), body: req.body, secret: 'mysecret', }); // custom logic const payload = req.body; if (payload.type === 'success') { //success logic here } else if (payload.type === 'error') { //error logic here } else if (payload.type === 'timeout') { //timeout logic here } // send response res.status(200).json({success: true}); }; router.post('/webhook', jsonParser, handler); router.options('/webhook', jsonParser, handler); router.listen(3000, () => { console.log('Server is running on port 3000'); });
示例 webhook 端点(Next.JS 应用路由)
🌐 Example webhook endpoint (Next.JS App Router)
类似地,这里是在 Next.JS 中为 App Router 使用 appRouterWebhook() 的示例端点。可从 v4.0.246 使用。
🌐 Similarly, here is an example endpoint in Next.JS for the App Router using appRouterWebhook(). Available from v4.0.246.
app/api/webhook.tsimport {appRouterWebhook } from '@remotion/lambda/client'; export constPOST =appRouterWebhook ({secret : 'mysecret', // Enable testing through the tool belowtesting :ENABLE_TESTING ,onSuccess : ({renderId }) =>console .log ('Finished render',renderId ),onTimeout : ({renderId }) =>console .log ('Time out',renderId ),onError : ({renderId }) =>console .log ('Error',renderId ), }); export constOPTIONS =POST ;
示例 webhook 端点(Next.JS 页面路由)
🌐 Example webhook endpoint (Next.JS Pages Router)
与上面相同的端点,但使用 Pages 路由并借助 pagesRouterWebhook()。可从 v4.0.246 使用。
🌐 The same endpoint as above, but using the Pages Router with the help of pagesRouterWebhook(). Available from v4.0.246.
pages/api/webhook.tsimport {pagesRouterWebhook } from '@remotion/lambda/client'; consthandler =pagesRouterWebhook ({secret : 'mysecret', // Enable testing through the tool belowtesting :ENABLE_TESTING ,onSuccess : ({renderId }) =>console .log ('Finished render',renderId ),onTimeout : ({renderId }) =>console .log ('Time out',renderId ),onError : ({renderId }) =>console .log ('Error',renderId ), }); export defaulthandler ;
测试你的 webhook 端点
🌐 Test your webhook endpoint
你可以使用此工具来验证你的 webhook 端点是否正常工作。该工具将发送一个适当的演示负载,并将响应记录到屏幕上。此工具发送的所有请求都将把 "X-Remotion-Mode" 头设置为 "demo"。
🌐 You can use this tool to verify that your webhook endpoint is working properly. The tool will send an appropriate demo payload and log the response to the screen. All requests sent by this tool will have the "X-Remotion-Mode" header set to "demo".
此工具直接从你的浏览器发送演示 webhook 请求,这具有以下含义:
- CORS 要求:
- 确保你的 API 端点已配置为通过设置
"Access-Control-Allow-Origin": "https://www.remotion.dev"来接受来自remotion.dev的请求。这对于此工具的工作是必要的,但对于你的生产 webhook 端点 不是 必需的。 - 你必须设置
"Access-Control-Allow-Headers": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, X-Remotion-Status, X-Remotion-Signature, X-Remotion-Mode" - 你必须设置
"Access-Control-Allow-Methods": "OPTIONS,POST"。 - 查看开发者工具中的错误信息以调试潜在的跨域问题。
- 确保你的 API 端点已配置为通过设置
- 你可以使用监听在
localhost上的服务器,而不需要使用反向代理。