@remotion/serverless 4.0.244 → 4.0.245

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.
Files changed (92) hide show
  1. package/.turbo/turbo-formatting.log +7 -0
  2. package/.turbo/turbo-lint.log +11 -0
  3. package/.turbo/turbo-make.log +1 -1
  4. package/LICENSE.md +1 -1
  5. package/dist/best-frames-per-function-param.d.ts +1 -0
  6. package/dist/best-frames-per-function-param.js +17 -0
  7. package/dist/calculate-chunk-times.d.ts +5 -0
  8. package/dist/calculate-chunk-times.js +29 -0
  9. package/dist/can-concat-seamlessly.d.ts +3 -0
  10. package/dist/can-concat-seamlessly.js +17 -0
  11. package/dist/cleanup-props.d.ts +9 -0
  12. package/dist/cleanup-props.js +23 -0
  13. package/dist/cleanup-serialized-input-props.d.ts +15 -0
  14. package/dist/cleanup-serialized-input-props.js +34 -0
  15. package/dist/concat-videos.d.ts +26 -0
  16. package/dist/concat-videos.js +53 -0
  17. package/dist/create-post-render-data.d.ts +20 -0
  18. package/dist/create-post-render-data.js +68 -0
  19. package/dist/docs-url.d.ts +1 -0
  20. package/dist/docs-url.js +4 -0
  21. package/dist/estimate-price-from-bucket.d.ts +15 -0
  22. package/dist/estimate-price-from-bucket.js +31 -0
  23. package/dist/find-output-file-in-bucket.d.ts +16 -0
  24. package/dist/find-output-file-in-bucket.js +41 -0
  25. package/dist/format-costs-info.d.ts +2 -0
  26. package/dist/format-costs-info.js +23 -0
  27. package/dist/get-overall-progress-from-storage.d.ts +11 -0
  28. package/dist/get-overall-progress-from-storage.js +25 -0
  29. package/dist/get-overall-progress.d.ts +9 -0
  30. package/dist/get-overall-progress.js +23 -0
  31. package/dist/handlers/compositions.d.ts +11 -0
  32. package/dist/handlers/compositions.js +81 -0
  33. package/dist/handlers/launch.d.ts +17 -0
  34. package/dist/handlers/launch.js +601 -0
  35. package/dist/handlers/progress.d.ts +12 -0
  36. package/dist/handlers/progress.js +51 -0
  37. package/dist/handlers/renderer.d.ts +23 -0
  38. package/dist/handlers/renderer.js +342 -0
  39. package/dist/handlers/start.d.ts +14 -0
  40. package/dist/handlers/start.js +105 -0
  41. package/dist/handlers/still.d.ts +20 -0
  42. package/dist/handlers/still.js +334 -0
  43. package/dist/inspect-error.d.ts +4 -0
  44. package/dist/inspect-error.js +39 -0
  45. package/dist/invoke-webhook.d.ts +39 -0
  46. package/dist/invoke-webhook.js +116 -0
  47. package/dist/leak-detection.d.ts +4 -0
  48. package/dist/leak-detection.js +40 -0
  49. package/dist/make-timeout-error.d.ts +13 -0
  50. package/dist/make-timeout-error.js +32 -0
  51. package/dist/make-timeout-message.d.ts +12 -0
  52. package/dist/make-timeout-message.js +75 -0
  53. package/dist/merge-chunks.d.ts +37 -0
  54. package/dist/merge-chunks.js +92 -0
  55. package/dist/min-max.d.ts +2 -0
  56. package/dist/min-max.js +33 -0
  57. package/dist/most-expensive-chunks.d.ts +13 -0
  58. package/dist/most-expensive-chunks.js +28 -0
  59. package/dist/on-downloads-helpers.d.ts +2 -0
  60. package/dist/on-downloads-helpers.js +29 -0
  61. package/dist/overall-render-progress.d.ts +59 -0
  62. package/dist/overall-render-progress.js +180 -0
  63. package/dist/plan-frame-ranges.d.ts +7 -0
  64. package/dist/plan-frame-ranges.js +17 -0
  65. package/dist/progress.d.ts +16 -0
  66. package/dist/progress.js +254 -0
  67. package/dist/render-has-audio-video.d.ts +6 -0
  68. package/dist/render-has-audio-video.js +21 -0
  69. package/dist/render-progress.d.ts +51 -0
  70. package/dist/render-progress.js +2 -0
  71. package/dist/return-values.d.ts +38 -0
  72. package/dist/return-values.js +2 -0
  73. package/dist/stackback.d.ts +6 -0
  74. package/dist/stackback.js +59 -0
  75. package/dist/stream-renderer.d.ts +17 -0
  76. package/dist/stream-renderer.js +148 -0
  77. package/dist/types.d.ts +54 -0
  78. package/dist/types.js +2 -0
  79. package/dist/validate-download-behavior.d.ts +1 -0
  80. package/dist/validate-download-behavior.js +21 -0
  81. package/dist/validate-frames-per-function.d.ts +4 -0
  82. package/dist/validate-frames-per-function.js +29 -0
  83. package/dist/validate-frames-per-lambda.d.ts +4 -0
  84. package/dist/validate-frames-per-lambda.js +29 -0
  85. package/dist/validate-privacy.d.ts +2 -0
  86. package/dist/validate-privacy.js +14 -0
  87. package/dist/validate.d.ts +4 -0
  88. package/dist/validate.js +8 -0
  89. package/dist/why-is-node-running.d.ts +15 -0
  90. package/dist/why-is-node-running.js +89 -0
  91. package/package.json +5 -5
  92. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,334 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.stillHandler = void 0;
7
+ const renderer_1 = require("@remotion/renderer");
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const no_react_1 = require("remotion/no-react");
11
+ const version_1 = require("remotion/version");
12
+ const cleanup_serialized_input_props_1 = require("../cleanup-serialized-input-props");
13
+ const compress_props_1 = require("../compress-props");
14
+ const constants_1 = require("../constants");
15
+ const expected_out_name_1 = require("../expected-out-name");
16
+ const format_costs_info_1 = require("../format-costs-info");
17
+ const get_or_create_bucket_1 = require("../get-or-create-bucket");
18
+ const on_downloads_helpers_1 = require("../on-downloads-helpers");
19
+ const overall_render_progress_1 = require("../overall-render-progress");
20
+ const validate_composition_1 = require("../validate-composition");
21
+ const validate_download_behavior_1 = require("../validate-download-behavior");
22
+ const validate_outname_1 = require("../validate-outname");
23
+ const validate_privacy_1 = require("../validate-privacy");
24
+ const write_lambda_error_1 = require("../write-lambda-error");
25
+ const innerStillHandler = async ({ params: lambdaParams, expectedBucketOwner, renderId, onStream, timeoutInMilliseconds, providerSpecifics, }, cleanup) => {
26
+ var _a, _b, _c, _d, _e, _f, _g;
27
+ if (lambdaParams.type !== constants_1.ServerlessRoutines.still) {
28
+ throw new TypeError('Expected still type');
29
+ }
30
+ if (lambdaParams.version !== version_1.VERSION) {
31
+ if (!lambdaParams.version) {
32
+ throw new Error(`Version mismatch: When calling renderStillOnLambda(), you called the function ${process.env.AWS_LAMBDA_FUNCTION_NAME} which has the version ${version_1.VERSION} but the @remotion/lambda package is an older version. Deploy a new function and use it to call renderStillOnLambda(). See: https://www.remotion.dev/docs/lambda/upgrading`);
33
+ }
34
+ throw new Error(`Version mismatch: When calling renderStillOnLambda(), you passed ${process.env.AWS_LAMBDA_FUNCTION_NAME} as the function, which has the version ${version_1.VERSION}, but the @remotion/lambda package you used to invoke the function has version ${lambdaParams.version}. Deploy a new function and use it to call renderStillOnLambda(). See: https://www.remotion.dev/docs/lambda/upgrading`);
35
+ }
36
+ (0, validate_download_behavior_1.validateDownloadBehavior)(lambdaParams.downloadBehavior);
37
+ (0, validate_privacy_1.validatePrivacy)(lambdaParams.privacy, true);
38
+ (0, validate_outname_1.validateOutname)({
39
+ outName: lambdaParams.outName,
40
+ codec: null,
41
+ audioCodecSetting: null,
42
+ separateAudioTo: null,
43
+ });
44
+ const start = Date.now();
45
+ const browserInstancePromise = providerSpecifics.getBrowserInstance({
46
+ logLevel: lambdaParams.logLevel,
47
+ indent: false,
48
+ chromiumOptions: lambdaParams.chromiumOptions,
49
+ providerSpecifics,
50
+ });
51
+ const bucketNamePromise = (_a = lambdaParams.bucketName) !== null && _a !== void 0 ? _a : (0, get_or_create_bucket_1.internalGetOrCreateBucket)({
52
+ region: providerSpecifics.getCurrentRegionInFunction(),
53
+ enableFolderExpiry: null,
54
+ customCredentials: null,
55
+ providerSpecifics,
56
+ forcePathStyle: lambdaParams.forcePathStyle,
57
+ skipPutAcl: false,
58
+ }).then((b) => b.bucketName);
59
+ const outputDir = renderer_1.RenderInternals.tmpDir('remotion-render-');
60
+ const outputPath = node_path_1.default.join(outputDir, 'output');
61
+ const region = providerSpecifics.getCurrentRegionInFunction();
62
+ const bucketName = await bucketNamePromise;
63
+ const serializedInputPropsWithCustomSchema = await (0, compress_props_1.decompressInputProps)({
64
+ bucketName,
65
+ expectedBucketOwner,
66
+ region,
67
+ serialized: lambdaParams.inputProps,
68
+ propsType: 'input-props',
69
+ providerSpecifics,
70
+ forcePathStyle: lambdaParams.forcePathStyle,
71
+ });
72
+ const serveUrl = providerSpecifics.convertToServeUrl({
73
+ urlOrId: lambdaParams.serveUrl,
74
+ region,
75
+ bucketName,
76
+ });
77
+ const { server, cleanupServer } = await renderer_1.RenderInternals.makeOrReuseServer(undefined, {
78
+ concurrency: 1,
79
+ indent: false,
80
+ port: null,
81
+ remotionRoot: process.cwd(),
82
+ logLevel: lambdaParams.logLevel,
83
+ webpackConfigOrServeUrl: serveUrl,
84
+ offthreadVideoCacheSizeInBytes: lambdaParams.offthreadVideoCacheSizeInBytes,
85
+ binariesDirectory: null,
86
+ forceIPv4: false,
87
+ }, {
88
+ onDownload: () => undefined,
89
+ });
90
+ cleanup.push(() => cleanupServer(true));
91
+ const browserInstance = await browserInstancePromise;
92
+ const composition = await (0, validate_composition_1.validateComposition)({
93
+ serveUrl,
94
+ browserInstance: browserInstance.instance,
95
+ composition: lambdaParams.composition,
96
+ serializedInputPropsWithCustomSchema,
97
+ envVariables: (_b = lambdaParams.envVariables) !== null && _b !== void 0 ? _b : {},
98
+ chromiumOptions: lambdaParams.chromiumOptions,
99
+ timeoutInMilliseconds: lambdaParams.timeoutInMilliseconds,
100
+ port: null,
101
+ forceHeight: lambdaParams.forceHeight,
102
+ forceWidth: lambdaParams.forceWidth,
103
+ logLevel: lambdaParams.logLevel,
104
+ server,
105
+ offthreadVideoCacheSizeInBytes: lambdaParams.offthreadVideoCacheSizeInBytes,
106
+ onBrowserDownload: () => {
107
+ throw new Error('Should not download a browser in Lambda');
108
+ },
109
+ onServeUrlVisited: () => undefined,
110
+ providerSpecifics,
111
+ });
112
+ const renderMetadata = {
113
+ startedDate: Date.now(),
114
+ codec: null,
115
+ compositionId: lambdaParams.composition,
116
+ estimatedTotalLambdaInvokations: 1,
117
+ estimatedRenderLambdaInvokations: 1,
118
+ siteId: serveUrl,
119
+ totalChunks: 1,
120
+ type: 'still',
121
+ imageFormat: lambdaParams.imageFormat,
122
+ inputProps: lambdaParams.inputProps,
123
+ lambdaVersion: version_1.VERSION,
124
+ framesPerLambda: 1,
125
+ memorySizeInMb: Number(process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE),
126
+ region: providerSpecifics.getCurrentRegionInFunction(),
127
+ renderId,
128
+ outName: (_c = lambdaParams.outName) !== null && _c !== void 0 ? _c : undefined,
129
+ privacy: lambdaParams.privacy,
130
+ audioCodec: null,
131
+ deleteAfter: lambdaParams.deleteAfter,
132
+ numberOfGifLoops: null,
133
+ downloadBehavior: lambdaParams.downloadBehavior,
134
+ audioBitrate: null,
135
+ metadata: null,
136
+ functionName: process.env.AWS_LAMBDA_FUNCTION_NAME,
137
+ dimensions: {
138
+ height: composition.height * ((_d = lambdaParams.scale) !== null && _d !== void 0 ? _d : 1),
139
+ width: composition.width * ((_e = lambdaParams.scale) !== null && _e !== void 0 ? _e : 1),
140
+ },
141
+ };
142
+ const still = (0, overall_render_progress_1.makeInitialOverallRenderProgress)(timeoutInMilliseconds);
143
+ still.renderMetadata = renderMetadata;
144
+ await providerSpecifics.writeFile({
145
+ bucketName,
146
+ key: (0, constants_1.overallProgressKey)(renderId),
147
+ body: JSON.stringify(still),
148
+ region: providerSpecifics.getCurrentRegionInFunction(),
149
+ privacy: 'private',
150
+ expectedBucketOwner,
151
+ downloadBehavior: null,
152
+ customCredentials: null,
153
+ forcePathStyle: lambdaParams.forcePathStyle,
154
+ });
155
+ const onBrowserDownload = () => {
156
+ throw new Error('Should not download a browser in Lambda');
157
+ };
158
+ const receivedArtifact = [];
159
+ const { key, renderBucketName, customCredentials } = (0, expected_out_name_1.getExpectedOutName)(renderMetadata, bucketName, (0, expected_out_name_1.getCredentialsFromOutName)(lambdaParams.outName));
160
+ const onArtifact = (artifact) => {
161
+ if (receivedArtifact.find((a) => a.filename === artifact.filename)) {
162
+ return { alreadyExisted: true };
163
+ }
164
+ const storageKey = (0, constants_1.artifactName)(renderMetadata.renderId, artifact.filename);
165
+ receivedArtifact.push(providerSpecifics.makeArtifactWithDetails({
166
+ storageKey,
167
+ artifact,
168
+ region,
169
+ renderBucketName,
170
+ }));
171
+ const startTime = Date.now();
172
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel: lambdaParams.logLevel }, 'Writing artifact ' + artifact.filename + ' to S3');
173
+ providerSpecifics
174
+ .writeFile({
175
+ bucketName: renderBucketName,
176
+ key: storageKey,
177
+ body: artifact.content,
178
+ region,
179
+ privacy: lambdaParams.privacy,
180
+ expectedBucketOwner,
181
+ downloadBehavior: lambdaParams.downloadBehavior,
182
+ customCredentials,
183
+ forcePathStyle: lambdaParams.forcePathStyle,
184
+ })
185
+ .then(() => {
186
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel: lambdaParams.logLevel }, `Wrote artifact to S3 in ${Date.now() - startTime}ms`);
187
+ })
188
+ .catch((err) => {
189
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: lambdaParams.logLevel }, 'Failed to write artifact to S3', err);
190
+ });
191
+ return { alreadyExisted: false };
192
+ };
193
+ await renderer_1.RenderInternals.internalRenderStill({
194
+ composition,
195
+ output: outputPath,
196
+ serveUrl,
197
+ envVariables: (_f = lambdaParams.envVariables) !== null && _f !== void 0 ? _f : {},
198
+ frame: renderer_1.RenderInternals.convertToPositiveFrameIndex({
199
+ frame: lambdaParams.frame,
200
+ durationInFrames: composition.durationInFrames,
201
+ }),
202
+ imageFormat: lambdaParams.imageFormat,
203
+ serializedInputPropsWithCustomSchema,
204
+ overwrite: false,
205
+ puppeteerInstance: browserInstance.instance,
206
+ jpegQuality: (_g = lambdaParams.jpegQuality) !== null && _g !== void 0 ? _g : renderer_1.RenderInternals.DEFAULT_JPEG_QUALITY,
207
+ chromiumOptions: lambdaParams.chromiumOptions,
208
+ scale: lambdaParams.scale,
209
+ timeoutInMilliseconds: lambdaParams.timeoutInMilliseconds,
210
+ browserExecutable: providerSpecifics.getChromiumPath(),
211
+ cancelSignal: null,
212
+ indent: false,
213
+ onBrowserLog: null,
214
+ onDownload: (0, on_downloads_helpers_1.onDownloadsHelper)(lambdaParams.logLevel),
215
+ port: null,
216
+ server,
217
+ logLevel: lambdaParams.logLevel,
218
+ serializedResolvedPropsWithCustomSchema: no_react_1.NoReactInternals.serializeJSONWithDate({
219
+ indent: undefined,
220
+ staticBase: null,
221
+ data: composition.props,
222
+ }).serializedString,
223
+ offthreadVideoCacheSizeInBytes: lambdaParams.offthreadVideoCacheSizeInBytes,
224
+ binariesDirectory: null,
225
+ onBrowserDownload,
226
+ onArtifact,
227
+ });
228
+ const { size } = await node_fs_1.default.promises.stat(outputPath);
229
+ await providerSpecifics.writeFile({
230
+ bucketName: renderBucketName,
231
+ key,
232
+ privacy: lambdaParams.privacy,
233
+ body: node_fs_1.default.createReadStream(outputPath),
234
+ expectedBucketOwner,
235
+ region: providerSpecifics.getCurrentRegionInFunction(),
236
+ downloadBehavior: lambdaParams.downloadBehavior,
237
+ customCredentials,
238
+ forcePathStyle: lambdaParams.forcePathStyle,
239
+ });
240
+ await Promise.all([
241
+ node_fs_1.default.promises.rm(outputPath, { recursive: true }),
242
+ (0, cleanup_serialized_input_props_1.cleanupSerializedInputProps)({
243
+ region: providerSpecifics.getCurrentRegionInFunction(),
244
+ serialized: lambdaParams.inputProps,
245
+ providerSpecifics,
246
+ forcePathStyle: lambdaParams.forcePathStyle,
247
+ }),
248
+ server.closeServer(true),
249
+ ]);
250
+ const estimatedPrice = providerSpecifics.estimatePrice({
251
+ durationInMilliseconds: Date.now() - start + 100,
252
+ memorySizeInMb: Number(process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE),
253
+ region: providerSpecifics.getCurrentRegionInFunction(),
254
+ lambdasInvoked: 1,
255
+ diskSizeInMb: providerSpecifics.getEphemeralStorageForPriceCalculation(),
256
+ });
257
+ const { key: outKey, url } = providerSpecifics.getOutputUrl({
258
+ renderMetadata,
259
+ bucketName,
260
+ customCredentials,
261
+ currentRegion: providerSpecifics.getCurrentRegionInFunction(),
262
+ });
263
+ const payload = {
264
+ type: 'success',
265
+ output: url,
266
+ size,
267
+ sizeInBytes: size,
268
+ bucketName,
269
+ estimatedPrice: (0, format_costs_info_1.formatCostsInfo)(estimatedPrice),
270
+ renderId,
271
+ outKey,
272
+ receivedArtifacts: receivedArtifact,
273
+ };
274
+ onStream({
275
+ type: 'still-rendered',
276
+ payload,
277
+ });
278
+ await server.closeServer(true);
279
+ };
280
+ const stillHandler = async (options) => {
281
+ const { params } = options;
282
+ const cleanUpFn = [];
283
+ if (params.type !== constants_1.ServerlessRoutines.still) {
284
+ throw new Error('Params must be renderer');
285
+ }
286
+ try {
287
+ await innerStillHandler(options, cleanUpFn);
288
+ return { type: 'success' };
289
+ }
290
+ catch (err) {
291
+ // If this error is encountered, we can just retry as it
292
+ // is a very rare error to occur
293
+ const isBrowserError = options.providerSpecifics.isFlakyError(err);
294
+ const willRetry = isBrowserError || params.maxRetries > 0;
295
+ renderer_1.RenderInternals.Log.error({
296
+ indent: false,
297
+ logLevel: params.logLevel,
298
+ }, 'Got error:', err.stack, `Will retry = ${willRetry}`);
299
+ if (params.streamed) {
300
+ await options.onStream({
301
+ type: 'error-occurred',
302
+ payload: {
303
+ error: err.stack,
304
+ shouldRetry: willRetry,
305
+ errorInfo: {
306
+ name: err.name,
307
+ message: err.message,
308
+ stack: err.stack,
309
+ chunk: null,
310
+ frame: params.frame,
311
+ type: 'renderer',
312
+ isFatal: false,
313
+ tmpDir: (0, write_lambda_error_1.getTmpDirStateIfENoSp)(err.stack, options.providerSpecifics),
314
+ attempt: params.attempt,
315
+ totalAttempts: 1 + params.maxRetries,
316
+ willRetry,
317
+ },
318
+ },
319
+ });
320
+ }
321
+ return {
322
+ type: 'error',
323
+ message: err.message,
324
+ stack: err.stack,
325
+ };
326
+ }
327
+ finally {
328
+ options.providerSpecifics.forgetBrowserEventLoop(options.params.type === constants_1.ServerlessRoutines.still
329
+ ? options.params.logLevel
330
+ : 'error');
331
+ cleanUpFn.forEach((c) => c());
332
+ }
333
+ };
334
+ exports.stillHandler = stillHandler;
@@ -0,0 +1,4 @@
1
+ import type { EnhancedErrorInfo, LambdaErrorInfo } from './write-lambda-error';
2
+ export declare const inspectErrors: ({ errors, }: {
3
+ errors: LambdaErrorInfo[];
4
+ }) => EnhancedErrorInfo[];
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.inspectErrors = void 0;
4
+ const docs_url_1 = require("./docs-url");
5
+ const error_category_1 = require("./error-category");
6
+ const FAILED_TO_LAUNCH_TOKEN = 'Failed to launch browser.';
7
+ const getExplanation = (stack) => {
8
+ if (stack.includes('FATAL:zygote_communication_linux.cc')) {
9
+ return (FAILED_TO_LAUNCH_TOKEN +
10
+ ' Will be retried - you can probably ignore this error.');
11
+ }
12
+ if (stack.includes('error while loading shared libraries: libnss3.so')) {
13
+ return (FAILED_TO_LAUNCH_TOKEN +
14
+ ' Will be retried - you can probably ignore this error.');
15
+ }
16
+ if (stack.includes('TooManyRequestsException')) {
17
+ return `AWS returned an "TooManyRequestsException" error message which could mean you reached the concurrency limit of AWS Lambda. You can increase the limit - read this troubleshooting page: ${docs_url_1.DOCS_URL}/docs/lambda/troubleshooting/rate-limit`;
18
+ }
19
+ if ((0, error_category_1.errorIsOutOfSpaceError)(stack)) {
20
+ return `Your lambda function reached the storage limit. Reduce the amount of space needed per lambda function or increase the storage limit: ${docs_url_1.DOCS_URL}/docs/lambda/disk-size.`;
21
+ }
22
+ if ((0, error_category_1.isErrInsufficientResourcesErr)(stack)) {
23
+ return 'The lambda ran out of memory. Deploy a new function with more memory.';
24
+ }
25
+ if ((0, error_category_1.isBrowserCrashedError)(stack)) {
26
+ return 'The browser crashed while rendering the video. Deploy a new function with memory to give the browser more resources.';
27
+ }
28
+ return null;
29
+ };
30
+ const inspectErrors = ({ errors, }) => {
31
+ return errors.map((e) => {
32
+ return {
33
+ ...e,
34
+ explanation: getExplanation(e.stack),
35
+ s3Location: '',
36
+ };
37
+ });
38
+ };
39
+ exports.inspectErrors = inspectErrors;
@@ -0,0 +1,39 @@
1
+ import type { LogLevel } from '@remotion/renderer';
2
+ import type https from 'https';
3
+ import type http from 'node:http';
4
+ import type { AfterRenderCost } from './constants';
5
+ import type { EnhancedErrorInfo } from './write-lambda-error';
6
+ export declare function calculateSignature(payload: string, secret: string | null): string;
7
+ type DynamicWebhookPayload = {
8
+ type: 'error';
9
+ errors: {
10
+ message: string;
11
+ name: string;
12
+ stack: string;
13
+ }[];
14
+ } | {
15
+ type: 'success';
16
+ lambdaErrors: EnhancedErrorInfo[];
17
+ outputUrl: string | undefined;
18
+ outputFile: string | undefined;
19
+ timeToFinish: number | undefined;
20
+ costs: AfterRenderCost;
21
+ } | {
22
+ type: 'timeout';
23
+ };
24
+ export type WebhookPayload = {
25
+ renderId: string;
26
+ expectedBucketOwner: string;
27
+ bucketName: string;
28
+ customData: Record<string, unknown> | null;
29
+ } & DynamicWebhookPayload;
30
+ export type WebhookClient = (url: string | URL, options: https.RequestOptions, callback?: (res: http.IncomingMessage) => void) => http.ClientRequest;
31
+ type InvokeWebhookOptions = {
32
+ payload: WebhookPayload;
33
+ url: string;
34
+ secret: string | null;
35
+ redirectsSoFar: number;
36
+ client: WebhookClient;
37
+ };
38
+ export declare const invokeWebhook: (options: InvokeWebhookOptions, logLevel: LogLevel, retries?: number, errors?: number) => Promise<void>;
39
+ export {};
@@ -0,0 +1,116 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.invokeWebhook = void 0;
27
+ exports.calculateSignature = calculateSignature;
28
+ const renderer_1 = require("@remotion/renderer");
29
+ const Crypto = __importStar(require("node:crypto"));
30
+ function calculateSignature(payload, secret) {
31
+ if (!secret) {
32
+ return 'NO_SECRET_PROVIDED';
33
+ }
34
+ const hmac = Crypto.createHmac('sha512', secret);
35
+ const signature = 'sha512=' + hmac.update(payload).digest('hex');
36
+ return signature;
37
+ }
38
+ // Don't handle 304 status code (Not Modified) as a redirect,
39
+ // since the browser will display the right page.
40
+ const redirectStatusCodes = [301, 302, 303, 307, 308];
41
+ function invokeWebhookRaw({ payload, secret, url, redirectsSoFar, client, }) {
42
+ const jsonPayload = JSON.stringify(payload);
43
+ return new Promise((resolve, reject) => {
44
+ const req = client(url, {
45
+ method: 'POST',
46
+ headers: {
47
+ 'Content-Type': 'application/json',
48
+ 'Content-Length': jsonPayload.length,
49
+ 'X-Remotion-Mode': 'production',
50
+ 'X-Remotion-Signature': calculateSignature(jsonPayload, secret),
51
+ 'X-Remotion-Status': payload.type,
52
+ },
53
+ timeout: 5000,
54
+ }, (res) => {
55
+ if (res.statusCode && res.statusCode > 299) {
56
+ if (redirectStatusCodes.includes(res.statusCode)) {
57
+ if (!res.headers.location) {
58
+ reject(new Error(`Received a status code ${res.statusCode} but no "Location" header while calling ${res.headers.location}`));
59
+ return;
60
+ }
61
+ if (redirectsSoFar > 10) {
62
+ reject(new Error(`Too many redirects while downloading ${url}`));
63
+ return;
64
+ }
65
+ invokeWebhookRaw({
66
+ payload,
67
+ secret,
68
+ url: res.headers.location,
69
+ redirectsSoFar: redirectsSoFar + 1,
70
+ client,
71
+ })
72
+ .then(resolve)
73
+ .catch(reject);
74
+ return;
75
+ }
76
+ reject(new Error(`Sent a webhook to ${url} but got a status code of ${res.statusCode} with message '${res.statusMessage}'`));
77
+ return;
78
+ }
79
+ resolve();
80
+ });
81
+ req.write(jsonPayload, (err) => {
82
+ if (err) {
83
+ reject(err);
84
+ }
85
+ else {
86
+ req.end();
87
+ }
88
+ });
89
+ req.on('error', (err) => {
90
+ reject(err);
91
+ });
92
+ });
93
+ }
94
+ function exponentialBackoff(errorCount) {
95
+ return 1000 * 2 ** (errorCount - 1);
96
+ }
97
+ const invokeWebhook = async (options, logLevel, retries = 2, errors = 0) => {
98
+ try {
99
+ await invokeWebhookRaw(options);
100
+ }
101
+ catch (err) {
102
+ if (retries === 0) {
103
+ throw err;
104
+ }
105
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, 'Could not send webhook due to error:');
106
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, err.stack);
107
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, `Retrying in ${exponentialBackoff(errors)}ms.`);
108
+ await new Promise((resolve) => {
109
+ setTimeout(() => {
110
+ resolve();
111
+ }, exponentialBackoff(errors));
112
+ });
113
+ return (0, exports.invokeWebhook)(options, logLevel, retries - 1, errors + 1);
114
+ }
115
+ };
116
+ exports.invokeWebhook = invokeWebhook;
@@ -0,0 +1,4 @@
1
+ import type { NodeIntrospection } from './why-is-node-running';
2
+ export declare const stopLeakDetection: () => void;
3
+ export declare const setCurrentRequestId: (awsRequestId: string) => void;
4
+ export declare const startLeakDetection: (leakDetection: NodeIntrospection, awsRequestId: string) => void;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startLeakDetection = exports.setCurrentRequestId = exports.stopLeakDetection = void 0;
4
+ const why_is_node_running_1 = require("./why-is-node-running");
5
+ let currentRequestId = null;
6
+ let leakDetectionTimeout = null;
7
+ const stopLeakDetection = () => {
8
+ if (leakDetectionTimeout !== null) {
9
+ clearTimeout(leakDetectionTimeout.timeout);
10
+ leakDetectionTimeout = null;
11
+ }
12
+ };
13
+ exports.stopLeakDetection = stopLeakDetection;
14
+ const setCurrentRequestId = (awsRequestId) => {
15
+ currentRequestId = awsRequestId;
16
+ };
17
+ exports.setCurrentRequestId = setCurrentRequestId;
18
+ const startLeakDetection = (leakDetection, awsRequestId) => {
19
+ currentRequestId = awsRequestId;
20
+ leakDetectionTimeout = {
21
+ awsRequestId,
22
+ timeout: setTimeout(() => {
23
+ // First allow request ID to be set
24
+ setTimeout(() => {
25
+ if (currentRequestId !== awsRequestId) {
26
+ // New function, all good
27
+ return;
28
+ }
29
+ console.log('Leak detected: Lambda function is still running 10s after the render has finished.');
30
+ console.log('You may report this to the Remotion team.');
31
+ console.log('Include the logs below:');
32
+ (0, why_is_node_running_1.whyIsNodeRunning)(leakDetection);
33
+ console.log('Force-quitting the Lambda function now.');
34
+ process.exit(0);
35
+ }, 100);
36
+ }, 10000),
37
+ };
38
+ leakDetectionTimeout.timeout.unref();
39
+ };
40
+ exports.startLeakDetection = startLeakDetection;
@@ -0,0 +1,13 @@
1
+ import type { ProviderSpecifics } from './provider-implementation';
2
+ import type { RenderMetadata } from './render-metadata';
3
+ import type { CloudProvider } from './types';
4
+ import type { EnhancedErrorInfo } from './write-lambda-error';
5
+ export declare const makeTimeoutError: <Provider extends CloudProvider>({ timeoutInMilliseconds, missingChunks, renderMetadata, renderId, functionName, region, providerSpecifics, }: {
6
+ timeoutInMilliseconds: number;
7
+ renderMetadata: RenderMetadata<Provider>;
8
+ renderId: string;
9
+ missingChunks: number[];
10
+ functionName: string;
11
+ region: Provider["region"];
12
+ providerSpecifics: ProviderSpecifics<Provider>;
13
+ }) => EnhancedErrorInfo;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeTimeoutError = void 0;
4
+ const make_timeout_message_1 = require("./make-timeout-message");
5
+ const makeTimeoutError = ({ timeoutInMilliseconds, missingChunks, renderMetadata, renderId, functionName, region, providerSpecifics, }) => {
6
+ const message = (0, make_timeout_message_1.makeTimeoutMessage)({
7
+ missingChunks,
8
+ renderMetadata,
9
+ timeoutInMilliseconds,
10
+ renderId,
11
+ functionName,
12
+ region,
13
+ providerSpecifics,
14
+ });
15
+ const error = new Error(message);
16
+ return {
17
+ attempt: 1,
18
+ chunk: null,
19
+ explanation: null,
20
+ frame: null,
21
+ isFatal: true,
22
+ s3Location: '',
23
+ stack: error.stack,
24
+ tmpDir: null,
25
+ totalAttempts: 1,
26
+ type: 'stitcher',
27
+ willRetry: false,
28
+ message,
29
+ name: 'TimeoutError',
30
+ };
31
+ };
32
+ exports.makeTimeoutError = makeTimeoutError;
@@ -0,0 +1,12 @@
1
+ import type { ProviderSpecifics } from './provider-implementation';
2
+ import type { RenderMetadata } from './render-metadata';
3
+ import type { CloudProvider } from './types';
4
+ export declare const makeTimeoutMessage: <Provider extends CloudProvider>({ timeoutInMilliseconds, missingChunks, renderMetadata, renderId, functionName, region, providerSpecifics, }: {
5
+ timeoutInMilliseconds: number;
6
+ missingChunks: number[];
7
+ renderMetadata: RenderMetadata<Provider>;
8
+ renderId: string;
9
+ region: Provider["region"];
10
+ functionName: string;
11
+ providerSpecifics: ProviderSpecifics<Provider>;
12
+ }) => string;