@remotion/lambda 3.2.24 → 3.2.26-crf.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,16 +8,16 @@ export declare type RenderMediaOnLambdaInput = {
8
8
  functionName: string;
9
9
  serveUrl: string;
10
10
  composition: string;
11
- inputProps: unknown;
11
+ inputProps?: unknown;
12
12
  codec: LambdaCodec;
13
- imageFormat: ImageFormat;
13
+ imageFormat?: ImageFormat;
14
14
  crf?: number | undefined;
15
15
  envVariables?: Record<string, string>;
16
16
  pixelFormat?: PixelFormat;
17
17
  proResProfile?: ProResProfile;
18
- privacy: Privacy;
18
+ privacy?: Privacy;
19
19
  quality?: number;
20
- maxRetries: number;
20
+ maxRetries?: number;
21
21
  framesPerLambda?: number;
22
22
  logLevel?: LogLevel;
23
23
  frameRange?: FrameRange;
@@ -30,6 +30,9 @@ export declare type RenderMediaOnLambdaInput = {
30
30
  concurrencyPerLambda?: number;
31
31
  downloadBehavior?: DownloadBehavior | null;
32
32
  muted?: boolean;
33
+ overwrite?: boolean;
34
+ webhook?: string;
35
+ webhookSecret?: string;
33
36
  };
34
37
  export declare type RenderMediaOnLambdaOutput = {
35
38
  renderId: string;
@@ -44,18 +47,19 @@ export declare type RenderMediaOnLambdaOutput = {
44
47
  * @param params.composition The ID of the composition which should be rendered.
45
48
  * @param params.inputProps The input props that should be passed to the composition.
46
49
  * @param params.codec The media codec which should be used for encoding.
47
- * @param params.imageFormat In which image format the frames should be rendered.
50
+ * @param params.imageFormat In which image format the frames should be rendered. Default "jpeg"
48
51
  * @param params.crf The constant rate factor to be used during encoding.
49
52
  * @param params.envVariables Object containing environment variables to be inserted into the video environment
50
53
  * @param params.proResProfile The ProRes profile if rendering a ProRes video
51
54
  * @param params.quality JPEG quality if JPEG was selected as the image format.
52
55
  * @param params.region The AWS region in which the media should be rendered.
53
- * @param params.maxRetries How often rendering a chunk may fail before the media render gets aborted.
56
+ * @param params.maxRetries How often rendering a chunk may fail before the media render gets aborted. Default "1"
54
57
  * @param params.logLevel Level of logging that Lambda function should perform. Default "info".
58
+ * @param params.webhook Webhook URL to be called upon completion or timeout of the rendering process.
55
59
  * @returns {Promise<RenderMediaOnLambdaOutput>} See documentation for detailed structure
56
60
  */
57
- export declare const renderMediaOnLambda: ({ functionName, serveUrl, inputProps, codec, imageFormat, crf, envVariables, pixelFormat, proResProfile, quality, region, maxRetries, composition, framesPerLambda, privacy, logLevel, frameRange, outName, timeoutInMilliseconds, chromiumOptions, scale, numberOfGifLoops, everyNthFrame, concurrencyPerLambda, downloadBehavior, muted, }: RenderMediaOnLambdaInput) => Promise<RenderMediaOnLambdaOutput>;
61
+ export declare const renderMediaOnLambda: ({ functionName, serveUrl, inputProps, codec, imageFormat, crf, envVariables, pixelFormat, proResProfile, quality, region, maxRetries, composition, framesPerLambda, privacy, logLevel, frameRange, outName, timeoutInMilliseconds, chromiumOptions, scale, numberOfGifLoops, everyNthFrame, concurrencyPerLambda, downloadBehavior, muted, overwrite, webhook, webhookSecret }: RenderMediaOnLambdaInput) => Promise<RenderMediaOnLambdaOutput>;
58
62
  /**
59
63
  * @deprecated Renamed to renderMediaOnLambda()
60
64
  */
61
- export declare const renderVideoOnLambda: ({ functionName, serveUrl, inputProps, codec, imageFormat, crf, envVariables, pixelFormat, proResProfile, quality, region, maxRetries, composition, framesPerLambda, privacy, logLevel, frameRange, outName, timeoutInMilliseconds, chromiumOptions, scale, numberOfGifLoops, everyNthFrame, concurrencyPerLambda, downloadBehavior, muted, }: RenderMediaOnLambdaInput) => Promise<RenderMediaOnLambdaOutput>;
65
+ export declare const renderVideoOnLambda: ({ functionName, serveUrl, inputProps, codec, imageFormat, crf, envVariables, pixelFormat, proResProfile, quality, region, maxRetries, composition, framesPerLambda, privacy, logLevel, frameRange, outName, timeoutInMilliseconds, chromiumOptions, scale, numberOfGifLoops, everyNthFrame, concurrencyPerLambda, downloadBehavior, muted, overwrite, webhook, webhookSecret }: RenderMediaOnLambdaInput) => Promise<RenderMediaOnLambdaOutput>;
@@ -18,17 +18,18 @@ const validate_serveurl_1 = require("../shared/validate-serveurl");
18
18
  * @param params.composition The ID of the composition which should be rendered.
19
19
  * @param params.inputProps The input props that should be passed to the composition.
20
20
  * @param params.codec The media codec which should be used for encoding.
21
- * @param params.imageFormat In which image format the frames should be rendered.
21
+ * @param params.imageFormat In which image format the frames should be rendered. Default "jpeg"
22
22
  * @param params.crf The constant rate factor to be used during encoding.
23
23
  * @param params.envVariables Object containing environment variables to be inserted into the video environment
24
24
  * @param params.proResProfile The ProRes profile if rendering a ProRes video
25
25
  * @param params.quality JPEG quality if JPEG was selected as the image format.
26
26
  * @param params.region The AWS region in which the media should be rendered.
27
- * @param params.maxRetries How often rendering a chunk may fail before the media render gets aborted.
27
+ * @param params.maxRetries How often rendering a chunk may fail before the media render gets aborted. Default "1"
28
28
  * @param params.logLevel Level of logging that Lambda function should perform. Default "info".
29
+ * @param params.webhook Webhook URL to be called upon completion or timeout of the rendering process.
29
30
  * @returns {Promise<RenderMediaOnLambdaOutput>} See documentation for detailed structure
30
31
  */
31
- const renderMediaOnLambda = async ({ functionName, serveUrl, inputProps, codec, imageFormat, crf, envVariables, pixelFormat, proResProfile, quality, region, maxRetries, composition, framesPerLambda, privacy, logLevel, frameRange, outName, timeoutInMilliseconds, chromiumOptions, scale, numberOfGifLoops, everyNthFrame, concurrencyPerLambda, downloadBehavior, muted, }) => {
32
+ const renderMediaOnLambda = async ({ functionName, serveUrl, inputProps, codec, imageFormat, crf, envVariables, pixelFormat, proResProfile, quality, region, maxRetries, composition, framesPerLambda, privacy, logLevel, frameRange, outName, timeoutInMilliseconds, chromiumOptions, scale, numberOfGifLoops, everyNthFrame, concurrencyPerLambda, downloadBehavior, muted, overwrite, webhook, webhookSecret }) => {
32
33
  var _a;
33
34
  const actualCodec = (0, validate_lambda_codec_1.validateLambdaCodec)(codec);
34
35
  (0, validate_serveurl_1.validateServeUrl)(serveUrl);
@@ -46,16 +47,16 @@ const renderMediaOnLambda = async ({ functionName, serveUrl, inputProps, codec,
46
47
  framesPerLambda: framesPerLambda !== null && framesPerLambda !== void 0 ? framesPerLambda : null,
47
48
  composition,
48
49
  serveUrl: realServeUrl,
49
- inputProps,
50
+ inputProps: inputProps !== null && inputProps !== void 0 ? inputProps : {},
50
51
  codec: actualCodec,
51
- imageFormat,
52
+ imageFormat: imageFormat !== null && imageFormat !== void 0 ? imageFormat : 'jpeg',
52
53
  crf,
53
54
  envVariables,
54
55
  pixelFormat,
55
56
  proResProfile,
56
57
  quality,
57
- maxRetries,
58
- privacy,
58
+ maxRetries: maxRetries !== null && maxRetries !== void 0 ? maxRetries : 1,
59
+ privacy: privacy !== null && privacy !== void 0 ? privacy : 'public',
59
60
  logLevel: logLevel !== null && logLevel !== void 0 ? logLevel : 'info',
60
61
  frameRange: frameRange !== null && frameRange !== void 0 ? frameRange : null,
61
62
  outName: outName !== null && outName !== void 0 ? outName : null,
@@ -68,6 +69,9 @@ const renderMediaOnLambda = async ({ functionName, serveUrl, inputProps, codec,
68
69
  downloadBehavior: downloadBehavior !== null && downloadBehavior !== void 0 ? downloadBehavior : { type: 'play-in-browser' },
69
70
  muted: muted !== null && muted !== void 0 ? muted : false,
70
71
  version: version_1.VERSION,
72
+ overwrite: overwrite !== null && overwrite !== void 0 ? overwrite : false,
73
+ webhook,
74
+ webhookSecret,
71
75
  },
72
76
  region,
73
77
  });
@@ -24,6 +24,8 @@ declare type LambdaCommandLineOptions = {
24
24
  ['architecture']: LambdaArchitecture;
25
25
  ['custom-role-arn']: string | undefined;
26
26
  privacy: Privacy;
27
+ webhook: string | undefined;
28
+ webhookSecret: string | undefined;
27
29
  };
28
30
  export declare const parsedLambdaCli: LambdaCommandLineOptions & minimist.ParsedArgs;
29
31
  export declare const forceFlagProvided: boolean;
@@ -19,7 +19,7 @@ const log_1 = require("../../log");
19
19
  const progress_1 = require("./progress");
20
20
  exports.RENDER_COMMAND = 'render';
21
21
  const renderCommand = async (args) => {
22
- var _a, _b, _c, _d;
22
+ var _a, _b, _c, _d, _e, _f;
23
23
  const serveUrl = args[0];
24
24
  if (!serveUrl) {
25
25
  log_1.Log.error('No serve URL passed.');
@@ -36,10 +36,16 @@ const renderCommand = async (args) => {
36
36
  log_1.Log.info(`${constants_1.BINARY_NAME} ${exports.RENDER_COMMAND} <serve-url> <composition-id> [output-location]`);
37
37
  (0, quit_1.quit)(1);
38
38
  }
39
- const outName = (_a = args[2]) !== null && _a !== void 0 ? _a : null;
40
- const { chromiumOptions, codec, crf, envVariables, frameRange, imageFormat, inputProps, logLevel, pixelFormat, proResProfile, puppeteerTimeout, quality, scale, everyNthFrame, numberOfGifLoops, muted, } = await cli_1.CliInternals.getCliOptions({
39
+ const outName = args_1.parsedLambdaCli['out-name'];
40
+ const downloadName = (_a = args[2]) !== null && _a !== void 0 ? _a : null;
41
+ const { codec, reason } = cli_1.CliInternals.getFinalCodec({
42
+ downloadName,
43
+ outName: outName !== null && outName !== void 0 ? outName : null,
44
+ });
45
+ const { chromiumOptions, crf, envVariables, frameRange, imageFormat, inputProps, logLevel, pixelFormat, proResProfile, puppeteerTimeout, quality, scale, everyNthFrame, numberOfGifLoops, muted, overwrite, } = await cli_1.CliInternals.getCliOptions({
41
46
  type: 'series',
42
47
  isLambda: true,
48
+ codec,
43
49
  });
44
50
  const functionName = await (0, find_function_name_1.findFunctionName)();
45
51
  const region = (0, get_aws_region_1.getAwsRegion)();
@@ -75,10 +81,14 @@ const renderCommand = async (args) => {
75
81
  everyNthFrame,
76
82
  concurrencyPerLambda: args_1.parsedLambdaCli['concurrency-per-lambda'],
77
83
  muted,
84
+ overwrite,
85
+ webhook: (_e = args_1.parsedLambdaCli.webhook) !== null && _e !== void 0 ? _e : undefined,
86
+ webhookSecret: (_f = args_1.parsedLambdaCli.webhookSecret) !== null && _f !== void 0 ? _f : undefined
78
87
  });
79
- const totalSteps = outName ? 5 : 4;
88
+ const totalSteps = downloadName ? 5 : 4;
80
89
  const progressBar = cli_1.CliInternals.createOverwriteableCliOutput(cli_1.CliInternals.quietFlagProvided());
81
- log_1.Log.info(cli_1.CliInternals.chalk.gray(`Bucket = ${res.bucketName}, renderId = ${res.renderId}, functionName = ${functionName}`));
90
+ log_1.Log.info(cli_1.CliInternals.chalk.gray(`bucket = ${res.bucketName}, function = ${functionName}`));
91
+ log_1.Log.info(cli_1.CliInternals.chalk.gray(`renderId = ${res.renderId}, codec = ${codec} (${reason})`));
82
92
  log_1.Log.verbose(`CloudWatch logs (if enabled): ${res.cloudWatchLogs}`);
83
93
  const status = await (0, get_render_progress_1.getRenderProgress)({
84
94
  functionName,
@@ -116,11 +126,11 @@ const renderCommand = async (args) => {
116
126
  downloadInfo: null,
117
127
  retriesInfo: newStatus.retriesInfo,
118
128
  }));
119
- if (outName) {
129
+ if (downloadName) {
120
130
  const downloadStart = Date.now();
121
131
  const { outputPath, sizeInBytes } = await (0, download_media_1.downloadMedia)({
122
132
  bucketName: res.bucketName,
123
- outPath: outName,
133
+ outPath: downloadName,
124
134
  region: (0, get_aws_region_1.getAwsRegion)(),
125
135
  renderId: res.renderId,
126
136
  onProgress: ({ downloaded, totalSize }) => {
@@ -15,7 +15,7 @@ const quit_1 = require("../helpers/quit");
15
15
  const log_1 = require("../log");
16
16
  exports.STILL_COMMAND = 'still';
17
17
  const stillCommand = async (args) => {
18
- var _a, _b, _c, _d;
18
+ var _a, _b, _c, _d, _e, _f;
19
19
  const serveUrl = args[0];
20
20
  if (!serveUrl) {
21
21
  log_1.Log.error('No serve URL passed.');
@@ -32,22 +32,32 @@ const stillCommand = async (args) => {
32
32
  log_1.Log.info(`${constants_1.BINARY_NAME} ${exports.STILL_COMMAND} <serve-url> <composition-id> [output-location]`);
33
33
  (0, quit_1.quit)(1);
34
34
  }
35
- const outName = (_a = args[2]) !== null && _a !== void 0 ? _a : null;
36
- const { chromiumOptions, envVariables, imageFormat, inputProps, logLevel, puppeteerTimeout, quality, stillFrame, scale, } = await cli_1.CliInternals.getCliOptions({
35
+ const downloadName = (_a = args[2]) !== null && _a !== void 0 ? _a : null;
36
+ const outName = args_1.parsedLambdaCli['out-name'];
37
+ const { chromiumOptions, envVariables, inputProps, logLevel, puppeteerTimeout, quality, stillFrame, scale, } = await cli_1.CliInternals.getCliOptions({
37
38
  type: 'still',
38
39
  isLambda: true,
40
+ codec: 'h264',
39
41
  });
40
42
  const functionName = await (0, find_function_name_1.findFunctionName)();
41
43
  const maxRetries = (_b = args_1.parsedLambdaCli['max-retries']) !== null && _b !== void 0 ? _b : constants_1.DEFAULT_MAX_RETRIES;
42
44
  (0, validate_retries_1.validateMaxRetries)(maxRetries);
43
45
  const privacy = (_c = args_1.parsedLambdaCli.privacy) !== null && _c !== void 0 ? _c : constants_1.DEFAULT_OUTPUT_PRIVACY;
44
46
  (0, validate_privacy_1.validatePrivacy)(privacy);
47
+ const { format: imageFormat, source: imageFormatReason } = cli_1.CliInternals.determineFinalImageFormat({
48
+ downloadName,
49
+ outName: outName !== null && outName !== void 0 ? outName : null,
50
+ configImageFormat: (_d = cli_1.ConfigInternals.getUserPreferredImageFormat()) !== null && _d !== void 0 ? _d : null,
51
+ cliFlag: (_e = cli_1.CliInternals.parsedCli['image-format']) !== null && _e !== void 0 ? _e : null,
52
+ isLambda: true,
53
+ });
45
54
  try {
55
+ log_1.Log.info(cli_1.CliInternals.chalk.gray(`functionName = ${functionName}, imageFormat = ${imageFormat} (${imageFormatReason})`));
46
56
  const res = await (0, render_still_on_lambda_1.renderStillOnLambda)({
47
57
  functionName,
48
58
  serveUrl,
49
59
  inputProps,
50
- imageFormat: imageFormat,
60
+ imageFormat,
51
61
  composition,
52
62
  privacy,
53
63
  region: (0, get_aws_region_1.getAwsRegion)(),
@@ -56,18 +66,18 @@ const stillCommand = async (args) => {
56
66
  frame: stillFrame,
57
67
  quality,
58
68
  logLevel,
59
- outName: args_1.parsedLambdaCli['out-name'],
69
+ outName,
60
70
  chromiumOptions,
61
71
  timeoutInMilliseconds: puppeteerTimeout,
62
72
  scale,
63
73
  });
64
- log_1.Log.verbose(cli_1.CliInternals.chalk.gray(`Bucket = ${res.bucketName}, renderId = ${res.renderId}, functionName = ${functionName}`));
74
+ log_1.Log.info(cli_1.CliInternals.chalk.gray(`Bucket = ${res.bucketName}, renderId = ${res.renderId}`));
65
75
  log_1.Log.verbose(`CloudWatch logs (if enabled): ${res.cloudWatchLogs}`);
66
- if (outName) {
76
+ if (downloadName) {
67
77
  log_1.Log.info('Finished rendering. Downloading...');
68
78
  const { outputPath, sizeInBytes } = await (0, download_media_1.downloadMedia)({
69
79
  bucketName: res.bucketName,
70
- outPath: outName,
80
+ outPath: downloadName,
71
81
  region: (0, get_aws_region_1.getAwsRegion)(),
72
82
  renderId: res.renderId,
73
83
  });
@@ -80,7 +90,7 @@ const stillCommand = async (args) => {
80
90
  }
81
91
  }
82
92
  catch (err) {
83
- const frames = renderer_1.RenderInternals.parseStack(((_d = err.stack) !== null && _d !== void 0 ? _d : '').split('\n'));
93
+ const frames = renderer_1.RenderInternals.parseStack(((_f = err.stack) !== null && _f !== void 0 ? _f : '').split('\n'));
84
94
  const errorWithStackFrame = new renderer_1.RenderInternals.SymbolicateableError({
85
95
  message: err.message,
86
96
  frame: null,
@@ -0,0 +1,8 @@
1
+ import type { AwsRegion } from '../../client';
2
+ import type { LambdaRoutines } from '../../shared/constants';
3
+ export declare const getCloudwatchStreamUrl: ({ region, functionName, method, renderId, }: {
4
+ region: AwsRegion;
5
+ functionName: string;
6
+ method: LambdaRoutines;
7
+ renderId: string;
8
+ }) => string;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCloudwatchStreamUrl = void 0;
4
+ const getCloudwatchStreamUrl = ({ region, functionName, method, renderId, }) => {
5
+ return `https://${region}.console.aws.amazon.com/cloudwatch/home?region=${region}#logsV2:log-groups/log-group/$252Faws$252Flambda$252F${functionName}/log-events$3FfilterPattern$3D$2522method$253D${method}$252CrenderId$253D${renderId}$2522`;
6
+ };
7
+ exports.getCloudwatchStreamUrl = getCloudwatchStreamUrl;
package/dist/cli/index.js CHANGED
@@ -133,7 +133,7 @@ AWS returned an "TooManyRequestsException" error message which could mean you re
133
133
  };
134
134
  exports.executeCommand = executeCommand;
135
135
  const cli = async () => {
136
- await cli_1.CliInternals.initializeRenderCli(cli_1.CliInternals.findRemotionRoot(), 'lambda');
136
+ await cli_1.CliInternals.initializeCli(cli_1.CliInternals.findRemotionRoot());
137
137
  await (0, exports.executeCommand)(args_1.parsedLambdaCli._);
138
138
  };
139
139
  exports.cli = cli;
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findOutputFileInBucket = void 0;
4
- const client_s3_1 = require("@aws-sdk/client-s3");
5
4
  const suggested_policy_1 = require("../../api/iam-validation/suggested-policy");
6
- const aws_clients_1 = require("../../shared/aws-clients");
7
5
  const expected_out_name_1 = require("./expected-out-name");
8
6
  const get_output_url_from_metadata_1 = require("./get-output-url-from-metadata");
7
+ const io_1 = require("./io");
9
8
  const findOutputFileInBucket = async ({ region, renderMetadata, bucketName, customCredentials, }) => {
10
9
  var _a;
11
10
  if (!renderMetadata) {
@@ -13,10 +12,11 @@ const findOutputFileInBucket = async ({ region, renderMetadata, bucketName, cust
13
12
  }
14
13
  const { renderBucketName, key } = (0, expected_out_name_1.getExpectedOutName)(renderMetadata, bucketName, null);
15
14
  try {
16
- const head = await (0, aws_clients_1.getS3Client)(region, customCredentials).send(new client_s3_1.HeadObjectCommand({
17
- Bucket: renderBucketName,
18
- Key: key,
19
- }));
15
+ const head = await (0, io_1.lambdaHeadCommand)({
16
+ bucketName,
17
+ key,
18
+ region,
19
+ });
20
20
  return {
21
21
  lastModified: (_a = head.LastModified) === null || _a === void 0 ? void 0 : _a.getTime(),
22
22
  size: head.ContentLength,
@@ -36,3 +36,11 @@ export declare const lambdaReadFile: ({ bucketName, key, region, expectedBucketO
36
36
  region: AwsRegion;
37
37
  expectedBucketOwner: string;
38
38
  }) => Promise<Readable>;
39
+ export declare const lambdaHeadCommand: ({ bucketName, key, region, }: {
40
+ bucketName: string;
41
+ key: string;
42
+ region: AwsRegion;
43
+ }) => Promise<{
44
+ LastModified?: Date | undefined;
45
+ ContentLength?: number | undefined;
46
+ }>;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.lambdaReadFile = exports.lambdaWriteFile = exports.lambdaDeleteFile = exports.lambdaLs = void 0;
6
+ exports.lambdaHeadCommand = exports.lambdaReadFile = exports.lambdaWriteFile = exports.lambdaDeleteFile = exports.lambdaLs = void 0;
7
7
  const client_s3_1 = require("@aws-sdk/client-s3");
8
8
  const mime_types_1 = __importDefault(require("mime-types"));
9
9
  const aws_clients_1 = require("../../shared/aws-clients");
@@ -79,3 +79,11 @@ const lambdaReadFile = async ({ bucketName, key, region, expectedBucketOwner, })
79
79
  return Body;
80
80
  };
81
81
  exports.lambdaReadFile = lambdaReadFile;
82
+ const lambdaHeadCommand = async ({ bucketName, key, region, }) => {
83
+ const head = await (0, aws_clients_1.getS3Client)(region, null).send(new client_s3_1.HeadObjectCommand({
84
+ Bucket: bucketName,
85
+ Key: key,
86
+ }));
87
+ return head;
88
+ };
89
+ exports.lambdaHeadCommand = lambdaHeadCommand;
@@ -1,6 +1,6 @@
1
1
  import type { FileNameAndSize } from './get-files-in-folder';
2
2
  export declare type LambdaErrorInfo = {
3
- type: 'renderer' | 'browser' | 'stitcher';
3
+ type: 'renderer' | 'browser' | 'stitcher' | 'webhook';
4
4
  message: string;
5
5
  name: string;
6
6
  stack: string;
@@ -12,6 +12,7 @@ const version_1 = require("remotion/version");
12
12
  const aws_clients_1 = require("../shared/aws-clients");
13
13
  const constants_1 = require("../shared/constants");
14
14
  const docs_url_1 = require("../shared/docs-url");
15
+ const invoke_webhook_1 = require("../shared/invoke-webhook");
15
16
  const make_s3_url_1 = require("../shared/make-s3-url");
16
17
  const validate_frames_per_lambda_1 = require("../shared/validate-frames-per-lambda");
17
18
  const validate_outname_1 = require("../shared/validate-outname");
@@ -29,6 +30,7 @@ const concat_videos_1 = require("./helpers/concat-videos");
29
30
  const create_post_render_data_1 = require("./helpers/create-post-render-data");
30
31
  const delete_chunks_1 = require("./helpers/delete-chunks");
31
32
  const expected_out_name_1 = require("./helpers/expected-out-name");
33
+ const find_output_file_in_bucket_1 = require("./helpers/find-output-file-in-bucket");
32
34
  const get_browser_instance_1 = require("./helpers/get-browser-instance");
33
35
  const get_current_region_1 = require("./helpers/get-current-region");
34
36
  const get_files_to_delete_1 = require("./helpers/get-files-to-delete");
@@ -67,6 +69,52 @@ const innerLaunchHandler = async (params, options) => {
67
69
  throw new Error('Expected launch type');
68
70
  }
69
71
  const startedDate = Date.now();
72
+ let webhookInvoked = false;
73
+ const webhookDueToTimeout = setTimeout(async () => {
74
+ if (params.webhook && !webhookInvoked) {
75
+ try {
76
+ await (0, invoke_webhook_1.invokeWebhook)({
77
+ url: params.webhook,
78
+ secret: params.webhookSecret,
79
+ type: 'timeout',
80
+ renderId: params.renderId,
81
+ expectedBucketOwner: options.expectedBucketOwner,
82
+ bucketName: params.bucketName,
83
+ outputUrl: undefined,
84
+ errors: [],
85
+ lambdaErrors: [],
86
+ outputFile: undefined,
87
+ timeToFinish: undefined,
88
+ });
89
+ webhookInvoked = true;
90
+ }
91
+ catch (err) {
92
+ if (process.env.NODE_ENV === 'test') {
93
+ throw err;
94
+ }
95
+ await (0, write_lambda_error_1.writeLambdaError)({
96
+ bucketName: params.bucketName,
97
+ errorInfo: {
98
+ type: 'webhook',
99
+ message: err.message,
100
+ name: err.name,
101
+ stack: err.stack,
102
+ tmpDir: null,
103
+ frame: 0,
104
+ chunk: 0,
105
+ isFatal: false,
106
+ attempt: 1,
107
+ willRetry: false,
108
+ totalAttempts: 1,
109
+ },
110
+ renderId: params.renderId,
111
+ expectedBucketOwner: options.expectedBucketOwner,
112
+ });
113
+ console.log('Failed to invoke webhook:');
114
+ console.log(err);
115
+ }
116
+ }
117
+ }, Math.max(params.timeoutInMilliseconds - 1000, 1000));
70
118
  const [browserInstance, optimization] = await Promise.all([
71
119
  (0, get_browser_instance_1.getBrowserInstance)(renderer_1.RenderInternals.isEqualOrBelowLogLevel(params.logLevel, 'verbose'), params.chromiumOptions),
72
120
  (0, s3_optimization_file_1.getOptimization)({
@@ -107,7 +155,7 @@ const innerLaunchHandler = async (params, options) => {
107
155
  if (chunkCount > constants_1.MAX_FUNCTIONS_PER_RENDER) {
108
156
  throw new Error(`Too many functions: This render would cause ${chunkCount} functions to spawn. We limit this amount to ${constants_1.MAX_FUNCTIONS_PER_RENDER} functions as more would result in diminishing returns. Values set: frameCount = ${frameCount}, framesPerLambda=${framesPerLambda}. See ${docs_url_1.DOCS_URL}/docs/lambda/concurrency for how this parameter is calculated.`);
109
157
  }
110
- (0, validate_outname_1.validateOutname)(params.outName);
158
+ (0, validate_outname_1.validateOutname)(params.outName, params.codec);
111
159
  (0, validate_privacy_1.validatePrivacy)(params.privacy);
112
160
  renderer_1.RenderInternals.validatePuppeteerTimeout(params.timeoutInMilliseconds);
113
161
  const { chunks, didUseOptimization } = (0, plan_frame_ranges_1.planFrameRanges)({
@@ -183,6 +231,29 @@ const innerLaunchHandler = async (params, options) => {
183
231
  outName: (_b = params.outName) !== null && _b !== void 0 ? _b : undefined,
184
232
  privacy: params.privacy,
185
233
  };
234
+ const { key, renderBucketName, customCredentials } = (0, expected_out_name_1.getExpectedOutName)(renderMetadata, params.bucketName, typeof params.outName === 'string' || typeof params.outName === 'undefined'
235
+ ? null
236
+ : (_d = (_c = params.outName) === null || _c === void 0 ? void 0 : _c.s3OutputProvider) !== null && _d !== void 0 ? _d : null);
237
+ const output = await (0, find_output_file_in_bucket_1.findOutputFileInBucket)({
238
+ bucketName: params.bucketName,
239
+ customCredentials,
240
+ region: (0, get_current_region_1.getCurrentRegionInFunction)(),
241
+ renderMetadata,
242
+ });
243
+ if (output) {
244
+ if (params.overwrite) {
245
+ console.info('Deleting', { bucketName: renderBucketName, key }, 'because it already existed and will be overwritten');
246
+ await (0, io_1.lambdaDeleteFile)({
247
+ bucketName: renderBucketName,
248
+ customCredentials,
249
+ key,
250
+ region: (0, get_current_region_1.getCurrentRegionInFunction)(),
251
+ });
252
+ }
253
+ else {
254
+ throw new TypeError(`Output file "${key}" in bucket "${renderBucketName}" in region "${(0, get_current_region_1.getCurrentRegionInFunction)()}" already exists. Delete it before re-rendering, or use the overwrite option to delete it before render."`);
255
+ }
256
+ }
186
257
  await (0, io_1.lambdaWriteFile)({
187
258
  bucketName: params.bucketName,
188
259
  key: (0, constants_1.renderMetadataKey)(params.renderId),
@@ -263,9 +334,6 @@ const innerLaunchHandler = async (params, options) => {
263
334
  if (!encodingStop) {
264
335
  encodingStop = Date.now();
265
336
  }
266
- const { key, renderBucketName, customCredentials } = (0, expected_out_name_1.getExpectedOutName)(renderMetadata, params.bucketName, typeof params.outName === 'string' || typeof params.outName === 'undefined'
267
- ? null
268
- : (_d = (_c = params.outName) === null || _c === void 0 ? void 0 : _c.s3OutputProvider) !== null && _d !== void 0 ? _d : null);
269
337
  const outputSize = fs_1.default.statSync(outfile);
270
338
  await (0, io_1.lambdaWriteFile)({
271
339
  bucketName: renderBucketName,
@@ -357,6 +425,7 @@ const innerLaunchHandler = async (params, options) => {
357
425
  contents,
358
426
  jobs,
359
427
  });
428
+ const outputUrl = (0, get_output_url_from_metadata_1.getOutputUrlFromMetadata)(renderMetadata, params.bucketName, customCredentials);
360
429
  const postRenderData = (0, create_post_render_data_1.createPostRenderData)({
361
430
  expectedBucketOwner: options.expectedBucketOwner,
362
431
  region: (0, get_current_region_1.getCurrentRegionInFunction)(),
@@ -370,7 +439,7 @@ const innerLaunchHandler = async (params, options) => {
370
439
  outputFile: {
371
440
  lastModified: Date.now(),
372
441
  size: outputSize.size,
373
- url: (0, get_output_url_from_metadata_1.getOutputUrlFromMetadata)(renderMetadata, params.bucketName, customCredentials),
442
+ url: outputUrl,
374
443
  },
375
444
  });
376
445
  await finalEncodingProgressProm;
@@ -388,6 +457,50 @@ const innerLaunchHandler = async (params, options) => {
388
457
  customCredentials: null,
389
458
  });
390
459
  await Promise.all([cleanupChunksProm, fs_1.default.promises.rm(outfile)]);
460
+ clearTimeout(webhookDueToTimeout);
461
+ if (params.webhook && !webhookInvoked) {
462
+ try {
463
+ await (0, invoke_webhook_1.invokeWebhook)({
464
+ url: params.webhook,
465
+ secret: params.webhookSecret,
466
+ type: 'success',
467
+ renderId: params.renderId,
468
+ expectedBucketOwner: options.expectedBucketOwner,
469
+ bucketName: params.bucketName,
470
+ outputUrl,
471
+ errors: [],
472
+ lambdaErrors: postRenderData.errors,
473
+ outputFile: postRenderData.outputFile,
474
+ timeToFinish: postRenderData.timeToFinish
475
+ });
476
+ webhookInvoked = true;
477
+ }
478
+ catch (err) {
479
+ if (process.env.NODE_ENV === 'test') {
480
+ throw err;
481
+ }
482
+ await (0, write_lambda_error_1.writeLambdaError)({
483
+ bucketName: params.bucketName,
484
+ errorInfo: {
485
+ type: 'webhook',
486
+ message: err.message,
487
+ name: err.name,
488
+ stack: err.stack,
489
+ tmpDir: null,
490
+ frame: 0,
491
+ chunk: 0,
492
+ isFatal: false,
493
+ attempt: 1,
494
+ willRetry: false,
495
+ totalAttempts: 1,
496
+ },
497
+ renderId: params.renderId,
498
+ expectedBucketOwner: options.expectedBucketOwner,
499
+ });
500
+ console.log('Failed to invoke webhook:');
501
+ console.log(err);
502
+ }
503
+ }
391
504
  };
392
505
  const launchHandler = async (params, options) => {
393
506
  if (params.type !== constants_1.LambdaRoutines.launch) {
@@ -397,6 +510,9 @@ const launchHandler = async (params, options) => {
397
510
  await innerLaunchHandler(params, options);
398
511
  }
399
512
  catch (err) {
513
+ if (process.env.NODE_ENV === 'test') {
514
+ throw err;
515
+ }
400
516
  console.log('Error occurred', err);
401
517
  await (0, write_lambda_error_1.writeLambdaError)({
402
518
  bucketName: params.bucketName,
@@ -416,6 +532,48 @@ const launchHandler = async (params, options) => {
416
532
  expectedBucketOwner: options.expectedBucketOwner,
417
533
  renderId: params.renderId,
418
534
  });
535
+ if (params.webhook) {
536
+ try {
537
+ await (0, invoke_webhook_1.invokeWebhook)({
538
+ url: params.webhook,
539
+ secret: params.webhookSecret,
540
+ type: 'error',
541
+ renderId: params.renderId,
542
+ expectedBucketOwner: options.expectedBucketOwner,
543
+ bucketName: params.bucketName,
544
+ lambdaErrors: [],
545
+ errors: [err],
546
+ outputUrl: undefined,
547
+ outputFile: undefined,
548
+ timeToFinish: undefined,
549
+ });
550
+ }
551
+ catch (error) {
552
+ if (process.env.NODE_ENV === 'test') {
553
+ throw error;
554
+ }
555
+ await (0, write_lambda_error_1.writeLambdaError)({
556
+ bucketName: params.bucketName,
557
+ errorInfo: {
558
+ type: 'webhook',
559
+ message: err.message,
560
+ name: err.name,
561
+ stack: err.stack,
562
+ tmpDir: null,
563
+ frame: 0,
564
+ chunk: 0,
565
+ isFatal: false,
566
+ attempt: 1,
567
+ willRetry: false,
568
+ totalAttempts: 1,
569
+ },
570
+ renderId: params.renderId,
571
+ expectedBucketOwner: options.expectedBucketOwner,
572
+ });
573
+ console.log('Failed to invoke webhook:');
574
+ console.log(error);
575
+ }
576
+ }
419
577
  }
420
578
  };
421
579
  exports.launchHandler = launchHandler;
@@ -187,6 +187,9 @@ const rendererHandler = async (params, options) => {
187
187
  await renderHandler(params, options, logs);
188
188
  }
189
189
  catch (err) {
190
+ if (process.env.NODE_ENV === 'test') {
191
+ throw err;
192
+ }
190
193
  // If this error is encountered, we can just retry as it
191
194
  // is a very rare error to occur
192
195
  const isBrowserError = err.message.includes('FATAL:zygote_communication_linux.cc') ||
@@ -62,6 +62,9 @@ const startHandler = async (params, options) => {
62
62
  concurrencyPerLambda: params.concurrencyPerLambda,
63
63
  downloadBehavior: params.downloadBehavior,
64
64
  muted: params.muted,
65
+ overwrite: params.overwrite,
66
+ webhook: params.webhook,
67
+ webhookSecret: params.webhookSecret,
65
68
  };
66
69
  await (0, aws_clients_1.getLambdaClient)((0, get_current_region_1.getCurrentRegionInFunction)()).send(new client_lambda_1.InvokeCommand({
67
70
  FunctionName: process.env.AWS_LAMBDA_FUNCTION_NAME,
@@ -101,7 +101,10 @@ const innerStillHandler = async (lambdaParams, renderId, options) => {
101
101
  serveUrl: lambdaParams.serveUrl,
102
102
  dumpBrowserLogs: false,
103
103
  envVariables: lambdaParams.envVariables,
104
- frame: lambdaParams.frame,
104
+ frame: renderer_1.RenderInternals.convertToPositiveFrameIndex({
105
+ frame: lambdaParams.frame,
106
+ durationInFrames: composition.durationInFrames,
107
+ }),
105
108
  imageFormat: lambdaParams.imageFormat,
106
109
  inputProps: lambdaParams.inputProps,
107
110
  overwrite: false,
@@ -124,6 +124,9 @@ export declare type LambdaPayloads = {
124
124
  downloadBehavior: DownloadBehavior;
125
125
  muted: boolean;
126
126
  version: string;
127
+ overwrite: boolean;
128
+ webhook: string | undefined;
129
+ webhookSecret: string | undefined;
127
130
  };
128
131
  launch: {
129
132
  type: LambdaRoutines.launch;
@@ -153,6 +156,9 @@ export declare type LambdaPayloads = {
153
156
  concurrencyPerLambda: number;
154
157
  downloadBehavior: DownloadBehavior;
155
158
  muted: boolean;
159
+ overwrite: boolean;
160
+ webhook: string | undefined;
161
+ webhookSecret: string | undefined;
156
162
  };
157
163
  status: {
158
164
  type: LambdaRoutines.status;
@@ -0,0 +1,46 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import http from 'http';
4
+ import https from 'https';
5
+ import type { EnhancedErrorInfo } from '../functions/helpers/write-lambda-error';
6
+ /**
7
+ * @description Calculates cryptographically secure signature for webhooks using Hmac.
8
+ * @link https://remotion.dev/docs/lambda/webhooks#validate-webhooks
9
+ * @param payload Stringified request body to encode in the signature.
10
+ * @param secret User-provided webhook secret used to sign the request.
11
+ * @returns {string} Calculated signature
12
+ */
13
+ export declare function calculateSignature(payload: string, secret?: string): string;
14
+ export declare type InvokeWebhookInput = {
15
+ url: string;
16
+ type: 'success' | 'error' | 'timeout';
17
+ renderId: string;
18
+ secret: string | undefined;
19
+ expectedBucketOwner: string;
20
+ bucketName: string;
21
+ outputUrl: string | undefined;
22
+ lambdaErrors: EnhancedErrorInfo[];
23
+ errors: Error[];
24
+ outputFile: string | undefined;
25
+ timeToFinish: number | undefined;
26
+ };
27
+ export declare const mockableHttpClients: {
28
+ http: typeof http.request;
29
+ https: typeof https.request;
30
+ };
31
+ /**
32
+ * @description Calls a webhook.
33
+ * @link https://remotion.dev/docs/lambda/rendermediaonlambda#webhook
34
+ * @param params.url URL of webhook to call.
35
+ * @param params.renderId assigned render ID.
36
+ * @param params.secret webhook secret provided by the user.
37
+ * @param params.bucketName S3 bucket name.
38
+ * @param params.expectedBucketOwner owner of S3 bucket.
39
+ * @param params.outputUrl URL of rendered media file.
40
+ * @param params.lambdaErrors non-fatal errors that have occurred during the render process.
41
+ * @param params.errors fatal errors that have been thrown during the render process.
42
+ * @param params.outputFile output file.
43
+ * @param params.timeToFinish time to finish of rendering process.
44
+ * @returns {Promise<void>} Promise of HTTP request with resolve/reject to be used for error handling.
45
+ */
46
+ export declare function invokeWebhook({ url, type, renderId, secret, bucketName, expectedBucketOwner, outputUrl, lambdaErrors, errors, outputFile, timeToFinish, }: InvokeWebhookInput): Promise<void>;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.invokeWebhook = exports.mockableHttpClients = exports.calculateSignature = void 0;
30
+ const Crypto = __importStar(require("crypto"));
31
+ const http_1 = __importDefault(require("http"));
32
+ const https_1 = __importDefault(require("https"));
33
+ /**
34
+ * @description Calculates cryptographically secure signature for webhooks using Hmac.
35
+ * @link https://remotion.dev/docs/lambda/webhooks#validate-webhooks
36
+ * @param payload Stringified request body to encode in the signature.
37
+ * @param secret User-provided webhook secret used to sign the request.
38
+ * @returns {string} Calculated signature
39
+ */
40
+ function calculateSignature(payload, secret) {
41
+ if (!secret) {
42
+ return 'NO_SECRET_PROVIDED';
43
+ }
44
+ const hmac = Crypto.createHmac('sha512', secret);
45
+ const signature = 'sha512=' + hmac.update(payload).digest('hex');
46
+ return signature;
47
+ }
48
+ exports.calculateSignature = calculateSignature;
49
+ const getWebhookClient = (url) => {
50
+ if (url.startsWith('https://')) {
51
+ return exports.mockableHttpClients.https;
52
+ }
53
+ if (url.startsWith('http://')) {
54
+ return exports.mockableHttpClients.http;
55
+ }
56
+ throw new Error('Can only request URLs starting with http:// or https://');
57
+ };
58
+ exports.mockableHttpClients = {
59
+ http: http_1.default.request,
60
+ https: https_1.default.request,
61
+ };
62
+ /**
63
+ * @description Calls a webhook.
64
+ * @link https://remotion.dev/docs/lambda/rendermediaonlambda#webhook
65
+ * @param params.url URL of webhook to call.
66
+ * @param params.renderId assigned render ID.
67
+ * @param params.secret webhook secret provided by the user.
68
+ * @param params.bucketName S3 bucket name.
69
+ * @param params.expectedBucketOwner owner of S3 bucket.
70
+ * @param params.outputUrl URL of rendered media file.
71
+ * @param params.lambdaErrors non-fatal errors that have occurred during the render process.
72
+ * @param params.errors fatal errors that have been thrown during the render process.
73
+ * @param params.outputFile output file.
74
+ * @param params.timeToFinish time to finish of rendering process.
75
+ * @returns {Promise<void>} Promise of HTTP request with resolve/reject to be used for error handling.
76
+ */
77
+ function invokeWebhook({ url, type, renderId, secret, bucketName, expectedBucketOwner, outputUrl, lambdaErrors, errors, outputFile, timeToFinish, }) {
78
+ const payload = JSON.stringify({
79
+ result: type,
80
+ renderId,
81
+ bucketName,
82
+ expectedBucketOwner,
83
+ outputUrl,
84
+ outputFile,
85
+ timeToFinish,
86
+ lambdaErrors,
87
+ errors: errors.map((err) => ({
88
+ message: err.message,
89
+ name: err.name,
90
+ stack: err.stack,
91
+ })),
92
+ });
93
+ return new Promise((resolve, reject) => {
94
+ const req = getWebhookClient(url)(url, {
95
+ method: 'POST',
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ "X-Remotion-Mode": 'production',
99
+ 'X-Remotion-Signature': calculateSignature(payload, secret),
100
+ 'X-Remotion-Status': type,
101
+ },
102
+ timeout: 5000,
103
+ }, (res) => {
104
+ if (res.statusCode && res.statusCode > 299) {
105
+ reject(new Error(`Sent a webhook but got a status code of ${res.statusCode} with message '${res.statusMessage}'`));
106
+ return;
107
+ }
108
+ resolve();
109
+ });
110
+ req.write(payload);
111
+ req.on('error', (err) => {
112
+ reject(err);
113
+ });
114
+ req.end();
115
+ });
116
+ }
117
+ exports.invokeWebhook = invokeWebhook;
@@ -1,2 +1,3 @@
1
+ import type { Codec } from '@remotion/renderer';
1
2
  import type { OutNameInputWithoutCredentials } from './constants';
2
- export declare const validateOutname: (outName: OutNameInputWithoutCredentials | undefined | null) => void;
3
+ export declare const validateOutname: (outName: OutNameInputWithoutCredentials | undefined | null, codec?: Codec) => void;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateOutname = void 0;
4
+ const renderer_1 = require("@remotion/renderer");
4
5
  const validate_bucketname_1 = require("./validate-bucketname");
5
6
  const validateS3Key = (s3Key) => {
6
7
  if (typeof s3Key !== 'string') {
@@ -12,11 +13,14 @@ const validateS3Key = (s3Key) => {
12
13
  '. Check for invalid characters.');
13
14
  }
14
15
  };
15
- const validateOutname = (outName) => {
16
+ const validateOutname = (outName, codec) => {
16
17
  if (typeof outName === 'undefined' || outName === null) {
17
18
  return;
18
19
  }
19
20
  if (typeof outName === 'string') {
21
+ if (codec) {
22
+ (0, renderer_1.validateOutputFilename)(codec, renderer_1.RenderInternals.getExtensionOfFilename(outName !== null && outName !== void 0 ? outName : null));
23
+ }
20
24
  validateS3Key(outName);
21
25
  return;
22
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/lambda",
3
- "version": "3.2.24",
3
+ "version": "3.2.26-crf.18+b22217116",
4
4
  "description": "Distributed renderer for Remotion based on AWS Lambda",
5
5
  "main": "dist/index.js",
6
6
  "sideEffects": false,
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "module": "true",
11
11
  "scripts": {
12
- "testintegration": "jest src/test/integration --runInBand",
12
+ "testintegration": "jest src/test/integration --runInBand --forceExit",
13
13
  "lint": "eslint src --ext ts,tsx",
14
14
  "test": "jest src/test/unit",
15
15
  "watch": "tsc -w",
@@ -32,12 +32,12 @@
32
32
  "@aws-sdk/client-service-quotas": "3.58.0",
33
33
  "@aws-sdk/lib-storage": "3.58.0",
34
34
  "@aws-sdk/s3-request-presigner": "3.58.0",
35
- "@remotion/bundler": "3.2.24",
36
- "@remotion/cli": "3.2.24",
37
- "@remotion/renderer": "3.2.24",
35
+ "@remotion/bundler": "3.2.26-crf.18+b22217116",
36
+ "@remotion/cli": "3.2.26-crf.18+b22217116",
37
+ "@remotion/renderer": "3.2.26-crf.18+b22217116",
38
38
  "aws-policies": "^1.0.1",
39
39
  "mime-types": "2.1.34",
40
- "remotion": "3.2.24"
40
+ "remotion": "3.2.26-crf.18+b22217116"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": ">=16.8.0",
@@ -62,5 +62,5 @@
62
62
  "publishConfig": {
63
63
  "access": "public"
64
64
  },
65
- "gitHead": "1f11ef8d122eadb6d6f6aa0570ffc4936d43a886"
65
+ "gitHead": "b222171164aefac1d44e1ad9e08231e9bad9a029"
66
66
  }
Binary file