@remotion/serverless 4.0.244 → 4.0.246

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 (122) hide show
  1. package/.turbo/turbo-make.log +1 -1
  2. package/LICENSE.md +1 -1
  3. package/dist/best-frames-per-function-param.d.ts +1 -0
  4. package/dist/best-frames-per-function-param.js +17 -0
  5. package/dist/calculate-chunk-times.d.ts +5 -0
  6. package/dist/calculate-chunk-times.js +29 -0
  7. package/dist/can-concat-seamlessly.d.ts +3 -0
  8. package/dist/can-concat-seamlessly.js +17 -0
  9. package/dist/cleanup-props.d.ts +9 -0
  10. package/dist/cleanup-props.js +23 -0
  11. package/dist/cleanup-serialized-input-props.d.ts +15 -0
  12. package/dist/cleanup-serialized-input-props.js +34 -0
  13. package/dist/client.d.ts +9 -0
  14. package/dist/client.js +30 -12
  15. package/dist/compress-props.d.ts +6 -2
  16. package/dist/compress-props.js +5 -3
  17. package/dist/concat-videos.d.ts +25 -0
  18. package/dist/concat-videos.js +53 -0
  19. package/dist/constants.d.ts +39 -3
  20. package/dist/constants.js +8 -1
  21. package/dist/create-post-render-data.d.ts +20 -0
  22. package/dist/create-post-render-data.js +68 -0
  23. package/dist/docs-url.d.ts +1 -0
  24. package/dist/docs-url.js +4 -0
  25. package/dist/estimate-price-from-bucket.d.ts +15 -0
  26. package/dist/estimate-price-from-bucket.js +31 -0
  27. package/dist/expected-out-name.d.ts +1 -1
  28. package/dist/find-output-file-in-bucket.d.ts +16 -0
  29. package/dist/find-output-file-in-bucket.js +41 -0
  30. package/dist/format-costs-info.d.ts +2 -0
  31. package/dist/format-costs-info.js +23 -0
  32. package/dist/get-browser-instance.d.ts +5 -12
  33. package/dist/get-browser-instance.js +8 -7
  34. package/dist/get-custom-out-name.d.ts +1 -1
  35. package/dist/get-or-create-bucket.d.ts +1 -1
  36. package/dist/get-overall-progress-from-storage.d.ts +11 -0
  37. package/dist/get-overall-progress-from-storage.js +25 -0
  38. package/dist/get-overall-progress.d.ts +9 -0
  39. package/dist/get-overall-progress.js +23 -0
  40. package/dist/handlers/check-version-mismatch.d.ts +8 -0
  41. package/dist/handlers/check-version-mismatch.js +23 -0
  42. package/dist/handlers/compositions.d.ts +16 -0
  43. package/dist/handlers/compositions.js +81 -0
  44. package/dist/handlers/launch.d.ts +18 -0
  45. package/dist/handlers/launch.js +600 -0
  46. package/dist/handlers/progress.d.ts +16 -0
  47. package/dist/handlers/progress.js +54 -0
  48. package/dist/handlers/renderer.d.ts +24 -0
  49. package/dist/handlers/renderer.js +344 -0
  50. package/dist/handlers/start.d.ts +19 -0
  51. package/dist/handlers/start.js +104 -0
  52. package/dist/handlers/still.d.ts +21 -0
  53. package/dist/handlers/still.js +335 -0
  54. package/dist/index.d.ts +21 -5
  55. package/dist/index.js +54 -7
  56. package/dist/info.d.ts +1 -1
  57. package/dist/inner-routine.d.ts +22 -0
  58. package/dist/inner-routine.js +267 -0
  59. package/dist/inspect-error.d.ts +4 -0
  60. package/dist/inspect-error.js +39 -0
  61. package/dist/invoke-webhook.d.ts +42 -0
  62. package/dist/invoke-webhook.js +116 -0
  63. package/dist/is-warm.d.ts +2 -0
  64. package/dist/is-warm.js +10 -0
  65. package/dist/leak-detection.d.ts +4 -0
  66. package/dist/leak-detection.js +40 -0
  67. package/dist/make-bucket-name.d.ts +1 -1
  68. package/dist/make-timeout-error.d.ts +13 -0
  69. package/dist/make-timeout-error.js +32 -0
  70. package/dist/make-timeout-message.d.ts +12 -0
  71. package/dist/make-timeout-message.js +76 -0
  72. package/dist/merge-chunks.d.ts +38 -0
  73. package/dist/merge-chunks.js +92 -0
  74. package/dist/min-max.d.ts +2 -0
  75. package/dist/min-max.js +33 -0
  76. package/dist/most-expensive-chunks.d.ts +13 -0
  77. package/dist/most-expensive-chunks.js +28 -0
  78. package/dist/on-downloads-helpers.d.ts +2 -0
  79. package/dist/on-downloads-helpers.js +29 -0
  80. package/dist/overall-render-progress.d.ts +59 -0
  81. package/dist/overall-render-progress.js +180 -0
  82. package/dist/plan-frame-ranges.d.ts +7 -0
  83. package/dist/plan-frame-ranges.js +17 -0
  84. package/dist/print-logging-grep-helper.d.ts +4 -0
  85. package/dist/print-logging-grep-helper.js +12 -0
  86. package/dist/progress.d.ts +16 -0
  87. package/dist/progress.js +254 -0
  88. package/dist/provider-implementation.d.ts +152 -3
  89. package/dist/render-has-audio-video.d.ts +6 -0
  90. package/dist/render-has-audio-video.js +21 -0
  91. package/dist/render-metadata.d.ts +1 -1
  92. package/dist/render-progress.d.ts +51 -0
  93. package/dist/return-values.d.ts +38 -0
  94. package/dist/return-values.js +2 -0
  95. package/dist/stackback.d.ts +6 -0
  96. package/dist/stackback.js +59 -0
  97. package/dist/stream-renderer.d.ts +17 -0
  98. package/dist/stream-renderer.js +148 -0
  99. package/dist/streaming/streaming.d.ts +6 -6
  100. package/dist/streaming/streaming.js +3 -3
  101. package/dist/types.d.ts +55 -0
  102. package/dist/types.js +2 -0
  103. package/dist/validate-composition.d.ts +1 -1
  104. package/dist/validate-composition.js +11 -1
  105. package/dist/validate-download-behavior.d.ts +1 -0
  106. package/dist/validate-download-behavior.js +21 -0
  107. package/dist/validate-frames-per-function.d.ts +4 -0
  108. package/dist/validate-frames-per-function.js +29 -0
  109. package/dist/validate-privacy.d.ts +2 -0
  110. package/dist/validate-privacy.js +14 -0
  111. package/dist/validate.d.ts +4 -0
  112. package/dist/validate.js +8 -0
  113. package/dist/why-is-node-running.d.ts +15 -0
  114. package/dist/why-is-node-running.js +89 -0
  115. package/dist/{write-lambda-error.d.ts → write-error-to-storage.d.ts} +4 -4
  116. package/package.json +6 -5
  117. package/tsconfig.tsbuildinfo +1 -1
  118. package/dist/compositions.d.ts +0 -11
  119. package/dist/compositions.js +0 -82
  120. package/dist/still.d.ts +0 -28
  121. /package/dist/{still.js → render-progress.js} +0 -0
  122. /package/dist/{write-lambda-error.js → write-error-to-storage.js} +0 -0
@@ -0,0 +1,600 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.launchHandler = void 0;
4
+ const renderer_1 = require("@remotion/renderer");
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ const version_1 = require("remotion/version");
8
+ const compress_props_1 = require("../compress-props");
9
+ const constants_1 = require("../constants");
10
+ const docs_url_1 = require("../docs-url");
11
+ const expected_out_name_1 = require("../expected-out-name");
12
+ const invoke_webhook_1 = require("../invoke-webhook");
13
+ const overall_render_progress_1 = require("../overall-render-progress");
14
+ const best_frames_per_function_param_1 = require("../best-frames-per-function-param");
15
+ const cleanup_props_1 = require("../cleanup-props");
16
+ const find_output_file_in_bucket_1 = require("../find-output-file-in-bucket");
17
+ const merge_chunks_1 = require("../merge-chunks");
18
+ const plan_frame_ranges_1 = require("../plan-frame-ranges");
19
+ const stream_renderer_1 = require("../stream-renderer");
20
+ const validate_composition_1 = require("../validate-composition");
21
+ const validate_frames_per_function_1 = require("../validate-frames-per-function");
22
+ const validate_outname_1 = require("../validate-outname");
23
+ const validate_privacy_1 = require("../validate-privacy");
24
+ const write_error_to_storage_1 = require("../write-error-to-storage");
25
+ const innerLaunchHandler = async ({ functionName, params, options, overallProgress, registerCleanupTask, providerSpecifics, insideFunctionSpecifics, }) => {
26
+ var _a, _b, _c, _d, _e, _f, _g, _h;
27
+ if (params.type !== constants_1.ServerlessRoutines.launch) {
28
+ throw new Error('Expected launch type');
29
+ }
30
+ const startedDate = Date.now();
31
+ const browserInstance = insideFunctionSpecifics.getBrowserInstance({
32
+ logLevel: params.logLevel,
33
+ indent: false,
34
+ chromiumOptions: params.chromiumOptions,
35
+ providerSpecifics,
36
+ insideFunctionSpecifics,
37
+ });
38
+ const inputPropsPromise = (0, compress_props_1.decompressInputProps)({
39
+ bucketName: params.bucketName,
40
+ expectedBucketOwner: options.expectedBucketOwner,
41
+ region: providerSpecifics.getCurrentRegionInFunction(),
42
+ serialized: params.inputProps,
43
+ propsType: 'input-props',
44
+ providerSpecifics,
45
+ forcePathStyle: params.forcePathStyle,
46
+ });
47
+ const logOptions = {
48
+ indent: false,
49
+ logLevel: params.logLevel,
50
+ };
51
+ const serializedInputPropsWithCustomSchema = await inputPropsPromise;
52
+ renderer_1.RenderInternals.Log.info(logOptions, 'Waiting for browser to be ready:', serializedInputPropsWithCustomSchema);
53
+ const { instance } = await browserInstance;
54
+ renderer_1.RenderInternals.Log.info(logOptions, 'Validating composition, input props:', serializedInputPropsWithCustomSchema);
55
+ const startTime = Date.now();
56
+ const comp = await (0, validate_composition_1.validateComposition)({
57
+ serveUrl: params.serveUrl,
58
+ composition: params.composition,
59
+ browserInstance: instance,
60
+ serializedInputPropsWithCustomSchema,
61
+ envVariables: (_a = params.envVariables) !== null && _a !== void 0 ? _a : {},
62
+ timeoutInMilliseconds: params.timeoutInMilliseconds,
63
+ chromiumOptions: params.chromiumOptions,
64
+ port: null,
65
+ forceHeight: params.forceHeight,
66
+ forceWidth: params.forceWidth,
67
+ logLevel: params.logLevel,
68
+ server: undefined,
69
+ offthreadVideoCacheSizeInBytes: params.offthreadVideoCacheSizeInBytes,
70
+ onBrowserDownload: () => {
71
+ throw new Error('Should not download a browser in a function');
72
+ },
73
+ onServeUrlVisited: () => {
74
+ overallProgress.setServeUrlOpened(Date.now());
75
+ },
76
+ providerSpecifics,
77
+ });
78
+ overallProgress.setCompositionValidated(Date.now());
79
+ renderer_1.RenderInternals.Log.info(logOptions, 'Composition validated, resolved props', comp.props);
80
+ renderer_1.RenderInternals.validateBitrate(params.audioBitrate, 'audioBitrate');
81
+ renderer_1.RenderInternals.validateBitrate(params.videoBitrate, 'videoBitrate');
82
+ renderer_1.RenderInternals.validateConcurrency({
83
+ value: params.concurrencyPerFunction,
84
+ setting: 'concurrencyPerLambda',
85
+ checkIfValidForCurrentMachine: ((_b = params.rendererFunctionName) !== null && _b !== void 0 ? _b : null) === null,
86
+ });
87
+ const realFrameRange = renderer_1.RenderInternals.getRealFrameRange(comp.durationInFrames, params.frameRange);
88
+ const frameCount = renderer_1.RenderInternals.getFramesToRender(realFrameRange, params.everyNthFrame);
89
+ const framesPerLambda = (_c = params.framesPerFunction) !== null && _c !== void 0 ? _c : (0, best_frames_per_function_param_1.bestFramesPerFunctionParam)(frameCount.length);
90
+ (0, validate_frames_per_function_1.validateFramesPerFunction)({
91
+ framesPerFunction: framesPerLambda,
92
+ durationInFrames: frameCount.length,
93
+ });
94
+ (0, validate_outname_1.validateOutname)({
95
+ outName: params.outName,
96
+ codec: params.codec,
97
+ audioCodecSetting: params.audioCodec,
98
+ separateAudioTo: null,
99
+ });
100
+ (0, validate_privacy_1.validatePrivacy)(params.privacy, true);
101
+ renderer_1.RenderInternals.validatePuppeteerTimeout(params.timeoutInMilliseconds);
102
+ const { chunks } = (0, plan_frame_ranges_1.planFrameRanges)({
103
+ framesPerFunction: framesPerLambda,
104
+ frameRange: realFrameRange,
105
+ everyNthFrame: params.everyNthFrame,
106
+ });
107
+ if (chunks.length > constants_1.MAX_FUNCTIONS_PER_RENDER) {
108
+ throw new Error(`Too many functions: This render would cause ${chunks.length} 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.length}, framesPerLambda=${framesPerLambda}. See ${docs_url_1.DOCS_URL}/docs/lambda/concurrency#too-many-functions for help.`);
109
+ }
110
+ overallProgress.setExpectedChunks(chunks.length);
111
+ const sortedChunks = chunks.slice().sort((a, b) => a[0] - b[0]);
112
+ const serializedResolved = (0, compress_props_1.serializeOrThrow)(comp.props, 'resolved-props');
113
+ const needsToUpload = (0, compress_props_1.getNeedsToUpload)({
114
+ type: 'video-or-audio',
115
+ sizes: [
116
+ serializedResolved.length,
117
+ params.inputProps.type === 'bucket-url'
118
+ ? params.inputProps.hash.length
119
+ : params.inputProps.payload.length,
120
+ JSON.stringify(params.envVariables).length,
121
+ ],
122
+ providerSpecifics,
123
+ });
124
+ const serializedResolvedProps = await (0, compress_props_1.compressInputProps)({
125
+ propsType: 'resolved-props',
126
+ region: providerSpecifics.getCurrentRegionInFunction(),
127
+ stringifiedInputProps: serializedResolved,
128
+ userSpecifiedBucketName: params.bucketName,
129
+ needsToUpload,
130
+ providerSpecifics,
131
+ forcePathStyle: params.forcePathStyle,
132
+ skipPutAcl: false,
133
+ });
134
+ registerCleanupTask(() => {
135
+ return (0, cleanup_props_1.cleanupProps)({
136
+ serializedResolvedProps,
137
+ inputProps: params.inputProps,
138
+ providerSpecifics,
139
+ forcePathStyle: params.forcePathStyle,
140
+ });
141
+ });
142
+ const fps = comp.fps / params.everyNthFrame;
143
+ // If for 150 functions, we stream every frame, we DDos ourselves.
144
+ // Throttling a bit, allowing more progress if there is lower concurrency.
145
+ const progressEveryNthFrame = Math.ceil(chunks.length / 15);
146
+ const lambdaPayloads = chunks.map((chunkPayload) => {
147
+ var _a;
148
+ const payload = {
149
+ type: constants_1.ServerlessRoutines.renderer,
150
+ frameRange: chunkPayload,
151
+ serveUrl: params.serveUrl,
152
+ chunk: sortedChunks.indexOf(chunkPayload),
153
+ composition: params.composition,
154
+ fps: comp.fps,
155
+ height: comp.height,
156
+ width: comp.width,
157
+ durationInFrames: comp.durationInFrames,
158
+ bucketName: params.bucketName,
159
+ retriesLeft: params.maxRetries,
160
+ inputProps: params.inputProps,
161
+ renderId: params.renderId,
162
+ imageFormat: params.imageFormat,
163
+ codec: params.codec,
164
+ crf: params.crf,
165
+ envVariables: params.envVariables,
166
+ pixelFormat: params.pixelFormat,
167
+ proResProfile: params.proResProfile,
168
+ x264Preset: params.x264Preset,
169
+ jpegQuality: params.jpegQuality,
170
+ privacy: params.privacy,
171
+ logLevel: (_a = params.logLevel) !== null && _a !== void 0 ? _a : 'info',
172
+ attempt: 1,
173
+ timeoutInMilliseconds: params.timeoutInMilliseconds,
174
+ chromiumOptions: params.chromiumOptions,
175
+ scale: params.scale,
176
+ everyNthFrame: params.everyNthFrame,
177
+ concurrencyPerLambda: params.concurrencyPerFunction,
178
+ muted: params.muted,
179
+ audioBitrate: params.audioBitrate,
180
+ videoBitrate: params.videoBitrate,
181
+ encodingMaxRate: params.encodingMaxRate,
182
+ encodingBufferSize: params.encodingBufferSize,
183
+ launchFunctionConfig: {
184
+ version: version_1.VERSION,
185
+ },
186
+ resolvedProps: serializedResolvedProps,
187
+ offthreadVideoCacheSizeInBytes: params.offthreadVideoCacheSizeInBytes,
188
+ deleteAfter: params.deleteAfter,
189
+ colorSpace: params.colorSpace,
190
+ preferLossless: params.preferLossless,
191
+ compositionStart: realFrameRange[0],
192
+ framesPerLambda,
193
+ progressEveryNthFrame,
194
+ forcePathStyle: params.forcePathStyle,
195
+ metadata: params.metadata,
196
+ };
197
+ return payload;
198
+ });
199
+ renderer_1.RenderInternals.Log.info(logOptions, 'Render plan: ', chunks.map((c, i) => `Chunk ${i} (Frames ${c[0]} - ${c[1]})`).join(', '));
200
+ const renderMetadata = {
201
+ startedDate,
202
+ totalChunks: chunks.length,
203
+ estimatedTotalLambdaInvokations: [
204
+ // Direct invokations
205
+ chunks.length,
206
+ // This function
207
+ 1,
208
+ ].reduce((a, b) => a + b, 0),
209
+ estimatedRenderLambdaInvokations: chunks.length,
210
+ compositionId: comp.id,
211
+ siteId: params.serveUrl,
212
+ codec: params.codec,
213
+ type: 'video',
214
+ imageFormat: params.imageFormat,
215
+ inputProps: params.inputProps,
216
+ lambdaVersion: version_1.VERSION,
217
+ framesPerLambda,
218
+ memorySizeInMb: insideFunctionSpecifics.getCurrentMemorySizeInMb(),
219
+ region: providerSpecifics.getCurrentRegionInFunction(),
220
+ renderId: params.renderId,
221
+ outName: (_d = params.outName) !== null && _d !== void 0 ? _d : undefined,
222
+ privacy: params.privacy,
223
+ everyNthFrame: params.everyNthFrame,
224
+ frameRange: realFrameRange,
225
+ audioCodec: params.audioCodec,
226
+ deleteAfter: params.deleteAfter,
227
+ numberOfGifLoops: params.numberOfGifLoops,
228
+ downloadBehavior: params.downloadBehavior,
229
+ audioBitrate: params.audioBitrate,
230
+ muted: params.muted,
231
+ metadata: params.metadata,
232
+ functionName: insideFunctionSpecifics.getCurrentFunctionName(),
233
+ dimensions: {
234
+ width: comp.width * ((_e = params.scale) !== null && _e !== void 0 ? _e : 1),
235
+ height: comp.height * ((_f = params.scale) !== null && _f !== void 0 ? _f : 1),
236
+ },
237
+ };
238
+ const { key, renderBucketName, customCredentials } = (0, expected_out_name_1.getExpectedOutName)(renderMetadata, params.bucketName, typeof params.outName === 'string' || typeof params.outName === 'undefined'
239
+ ? null
240
+ : ((_h = (_g = params.outName) === null || _g === void 0 ? void 0 : _g.s3OutputProvider) !== null && _h !== void 0 ? _h : null));
241
+ if (!params.overwrite) {
242
+ const findOutputFile = insideFunctionSpecifics.timer('Checking if output file already exists', params.logLevel);
243
+ const output = await (0, find_output_file_in_bucket_1.findOutputFileInBucket)({
244
+ bucketName: params.bucketName,
245
+ customCredentials,
246
+ renderMetadata,
247
+ region: providerSpecifics.getCurrentRegionInFunction(),
248
+ currentRegion: providerSpecifics.getCurrentRegionInFunction(),
249
+ providerSpecifics,
250
+ forcePathStyle: params.forcePathStyle,
251
+ });
252
+ if (output) {
253
+ throw new TypeError(`Output file "${key}" in bucket "${renderBucketName}" in region "${providerSpecifics.getCurrentRegionInFunction()}" already exists. Delete it before re-rendering, or set the 'overwrite' option in renderMediaOnLambda() to overwrite it."`);
254
+ }
255
+ findOutputFile.end();
256
+ }
257
+ overallProgress.setRenderMetadata(renderMetadata);
258
+ const outdir = (0, path_1.join)(renderer_1.RenderInternals.tmpDir(constants_1.CONCAT_FOLDER_TOKEN), 'bucket');
259
+ if ((0, fs_1.existsSync)(outdir)) {
260
+ (0, fs_1.rmSync)(outdir, {
261
+ recursive: true,
262
+ });
263
+ }
264
+ (0, fs_1.mkdirSync)(outdir);
265
+ const files = [];
266
+ const onArtifact = (artifact) => {
267
+ if (overallProgress
268
+ .getReceivedArtifacts()
269
+ .find((a) => a.filename === artifact.filename)) {
270
+ return { alreadyExisted: true };
271
+ }
272
+ const region = providerSpecifics.getCurrentRegionInFunction();
273
+ const storageKey = (0, constants_1.artifactName)(renderMetadata.renderId, artifact.filename);
274
+ const start = Date.now();
275
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel: params.logLevel }, 'Writing artifact ' + artifact.filename + ' to S3');
276
+ providerSpecifics
277
+ .writeFile({
278
+ bucketName: renderBucketName,
279
+ key: storageKey,
280
+ body: artifact.content,
281
+ region,
282
+ privacy: params.privacy,
283
+ expectedBucketOwner: options.expectedBucketOwner,
284
+ downloadBehavior: params.downloadBehavior,
285
+ customCredentials,
286
+ forcePathStyle: params.forcePathStyle,
287
+ })
288
+ .then(() => {
289
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel: params.logLevel }, `Wrote artifact to S3 in ${Date.now() - start}ms`);
290
+ overallProgress.addReceivedArtifact(providerSpecifics.makeArtifactWithDetails({
291
+ region,
292
+ renderBucketName,
293
+ storageKey,
294
+ artifact,
295
+ }));
296
+ })
297
+ .catch((err) => {
298
+ overallProgress.addErrorWithoutUpload({
299
+ type: 'artifact',
300
+ message: err.message,
301
+ name: err.name,
302
+ stack: err.stack,
303
+ tmpDir: null,
304
+ frame: artifact.frame,
305
+ chunk: null,
306
+ isFatal: false,
307
+ attempt: 1,
308
+ willRetry: false,
309
+ totalAttempts: 1,
310
+ });
311
+ overallProgress.upload();
312
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Failed to write artifact to S3', err);
313
+ });
314
+ return { alreadyExisted: false };
315
+ };
316
+ await Promise.all(lambdaPayloads.map(async (payload) => {
317
+ await (0, stream_renderer_1.streamRendererFunctionWithRetry)({
318
+ files,
319
+ functionName,
320
+ outdir,
321
+ overallProgress,
322
+ payload,
323
+ logLevel: params.logLevel,
324
+ onArtifact,
325
+ providerSpecifics,
326
+ });
327
+ }));
328
+ const postRenderData = await (0, merge_chunks_1.mergeChunksAndFinishRender)({
329
+ bucketName: params.bucketName,
330
+ renderId: params.renderId,
331
+ expectedBucketOwner: options.expectedBucketOwner,
332
+ numberOfFrames: frameCount.length,
333
+ audioCodec: params.audioCodec,
334
+ chunkCount: chunks.length,
335
+ codec: params.codec,
336
+ customCredentials,
337
+ downloadBehavior: params.downloadBehavior,
338
+ fps,
339
+ key,
340
+ numberOfGifLoops: params.numberOfGifLoops,
341
+ privacy: params.privacy,
342
+ renderBucketName,
343
+ inputProps: params.inputProps,
344
+ serializedResolvedProps,
345
+ renderMetadata,
346
+ audioBitrate: params.audioBitrate,
347
+ logLevel: params.logLevel,
348
+ framesPerLambda,
349
+ binariesDirectory: null,
350
+ preferLossless: params.preferLossless,
351
+ compositionStart: realFrameRange[0],
352
+ outdir,
353
+ files: files.sort(),
354
+ overallProgress,
355
+ startTime,
356
+ providerSpecifics,
357
+ forcePathStyle: params.forcePathStyle,
358
+ insideFunctionSpecifics,
359
+ });
360
+ return postRenderData;
361
+ };
362
+ const launchHandler = async ({ params, options, providerSpecifics, client, insideFunctionSpecifics, }) => {
363
+ var _a, _b, _c;
364
+ if (params.type !== constants_1.ServerlessRoutines.launch) {
365
+ throw new Error('Expected launch type');
366
+ }
367
+ const functionName = (_a = params.rendererFunctionName) !== null && _a !== void 0 ? _a : insideFunctionSpecifics.getCurrentFunctionName();
368
+ const logOptions = {
369
+ indent: false,
370
+ logLevel: params.logLevel,
371
+ };
372
+ const cleanupTasks = [];
373
+ const registerCleanupTask = (task) => {
374
+ cleanupTasks.push(task);
375
+ };
376
+ const runCleanupTasks = () => {
377
+ const prom = Promise.all(cleanupTasks)
378
+ .then(() => {
379
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel: params.logLevel }, 'Ran cleanup tasks');
380
+ })
381
+ .catch((err) => {
382
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Failed to run cleanup tasks:', err);
383
+ });
384
+ cleanupTasks.length = 0;
385
+ return prom;
386
+ };
387
+ const onTimeout = async () => {
388
+ var _a;
389
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Function is about to time out. Can not finish render.');
390
+ // @ts-expect-error - We are adding a listener to a global variable
391
+ if (globalThis._dumpUnreleasedBuffers) {
392
+ // @ts-expect-error - We are adding a listener to a global variable
393
+ globalThis._dumpUnreleasedBuffers.emit('dump-unreleased-buffers');
394
+ }
395
+ runCleanupTasks();
396
+ if (!params.webhook) {
397
+ renderer_1.RenderInternals.Log.verbose({
398
+ indent: false,
399
+ logLevel: params.logLevel,
400
+ }, 'No webhook specified.');
401
+ return;
402
+ }
403
+ if (webhookInvoked) {
404
+ renderer_1.RenderInternals.Log.verbose({
405
+ indent: false,
406
+ logLevel: params.logLevel,
407
+ }, 'Webhook already invoked. Not invoking again.');
408
+ return;
409
+ }
410
+ try {
411
+ await (0, invoke_webhook_1.invokeWebhook)({
412
+ url: params.webhook.url,
413
+ secret: params.webhook.secret,
414
+ payload: {
415
+ type: 'timeout',
416
+ renderId: params.renderId,
417
+ expectedBucketOwner: options.expectedBucketOwner,
418
+ bucketName: params.bucketName,
419
+ customData: (_a = params.webhook.customData) !== null && _a !== void 0 ? _a : null,
420
+ },
421
+ redirectsSoFar: 0,
422
+ client,
423
+ }, params.logLevel);
424
+ renderer_1.RenderInternals.Log.verbose({
425
+ indent: false,
426
+ logLevel: params.logLevel,
427
+ }, 'Successfully invoked timeout webhook.', params.webhook.url);
428
+ webhookInvoked = true;
429
+ }
430
+ catch (err) {
431
+ if (process.env.NODE_ENV === 'test') {
432
+ throw err;
433
+ }
434
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Failed to invoke webhook:');
435
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, err);
436
+ overallProgress.addErrorWithoutUpload({
437
+ type: 'webhook',
438
+ message: err.message,
439
+ name: err.name,
440
+ stack: err.stack,
441
+ tmpDir: null,
442
+ frame: 0,
443
+ chunk: 0,
444
+ isFatal: false,
445
+ attempt: 1,
446
+ willRetry: false,
447
+ totalAttempts: 1,
448
+ });
449
+ overallProgress.upload();
450
+ }
451
+ };
452
+ let webhookInvoked = false;
453
+ const webhookDueToTimeout = setTimeout(onTimeout, Math.max(options.getRemainingTimeInMillis() - 1000, 1000));
454
+ renderer_1.RenderInternals.Log.info(logOptions, `Function has ${Math.max(options.getRemainingTimeInMillis() - 1000, 1000)} before it times out`);
455
+ const overallProgress = (0, overall_render_progress_1.makeOverallRenderProgress)({
456
+ renderId: params.renderId,
457
+ bucketName: params.bucketName,
458
+ expectedBucketOwner: options.expectedBucketOwner,
459
+ region: providerSpecifics.getCurrentRegionInFunction(),
460
+ timeoutTimestamp: options.getRemainingTimeInMillis() + Date.now(),
461
+ logLevel: params.logLevel,
462
+ providerSpecifics,
463
+ forcePathStyle: params.forcePathStyle,
464
+ });
465
+ try {
466
+ const postRenderData = await innerLaunchHandler({
467
+ functionName,
468
+ params,
469
+ options,
470
+ overallProgress,
471
+ registerCleanupTask,
472
+ providerSpecifics,
473
+ insideFunctionSpecifics,
474
+ });
475
+ clearTimeout(webhookDueToTimeout);
476
+ if (!params.webhook || webhookInvoked) {
477
+ return {
478
+ type: 'success',
479
+ };
480
+ }
481
+ try {
482
+ await (0, invoke_webhook_1.invokeWebhook)({
483
+ url: params.webhook.url,
484
+ secret: params.webhook.secret,
485
+ payload: {
486
+ type: 'success',
487
+ renderId: params.renderId,
488
+ expectedBucketOwner: options.expectedBucketOwner,
489
+ bucketName: params.bucketName,
490
+ customData: (_b = params.webhook.customData) !== null && _b !== void 0 ? _b : null,
491
+ outputUrl: postRenderData.outputFile,
492
+ lambdaErrors: postRenderData.errors,
493
+ outputFile: postRenderData.outputFile,
494
+ timeToFinish: postRenderData.timeToFinish,
495
+ costs: postRenderData.cost,
496
+ },
497
+ redirectsSoFar: 0,
498
+ client,
499
+ }, params.logLevel);
500
+ webhookInvoked = true;
501
+ }
502
+ catch (err) {
503
+ if (process.env.NODE_ENV === 'test') {
504
+ throw err;
505
+ }
506
+ overallProgress.addErrorWithoutUpload({
507
+ type: 'webhook',
508
+ message: err.message,
509
+ name: err.name,
510
+ stack: err.stack,
511
+ tmpDir: null,
512
+ frame: 0,
513
+ chunk: 0,
514
+ isFatal: false,
515
+ attempt: 1,
516
+ willRetry: false,
517
+ totalAttempts: 1,
518
+ });
519
+ overallProgress.upload();
520
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Failed to invoke webhook:');
521
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, err);
522
+ }
523
+ runCleanupTasks();
524
+ return {
525
+ type: 'success',
526
+ };
527
+ }
528
+ catch (err) {
529
+ if (process.env.NODE_ENV === 'test') {
530
+ throw err;
531
+ }
532
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Error occurred', err);
533
+ overallProgress.addErrorWithoutUpload({
534
+ chunk: null,
535
+ frame: null,
536
+ name: err.name,
537
+ stack: err.stack,
538
+ type: 'stitcher',
539
+ isFatal: true,
540
+ tmpDir: (0, write_error_to_storage_1.getTmpDirStateIfENoSp)(err.stack, providerSpecifics),
541
+ attempt: 1,
542
+ totalAttempts: 1,
543
+ willRetry: false,
544
+ message: err.message,
545
+ });
546
+ await overallProgress.upload();
547
+ runCleanupTasks();
548
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Wrote error to S3');
549
+ clearTimeout(webhookDueToTimeout);
550
+ if (params.webhook && !webhookInvoked) {
551
+ try {
552
+ await (0, invoke_webhook_1.invokeWebhook)({
553
+ url: params.webhook.url,
554
+ secret: params.webhook.secret,
555
+ payload: {
556
+ type: 'error',
557
+ renderId: params.renderId,
558
+ expectedBucketOwner: options.expectedBucketOwner,
559
+ bucketName: params.bucketName,
560
+ customData: (_c = params.webhook.customData) !== null && _c !== void 0 ? _c : null,
561
+ errors: [err].map((e) => ({
562
+ message: e.message,
563
+ name: e.name,
564
+ stack: e.stack,
565
+ })),
566
+ },
567
+ redirectsSoFar: 0,
568
+ client,
569
+ }, params.logLevel);
570
+ webhookInvoked = true;
571
+ }
572
+ catch (error) {
573
+ if (process.env.NODE_ENV === 'test') {
574
+ throw error;
575
+ }
576
+ overallProgress.addErrorWithoutUpload({
577
+ type: 'webhook',
578
+ message: err.message,
579
+ name: err.name,
580
+ stack: err.stack,
581
+ tmpDir: null,
582
+ frame: 0,
583
+ chunk: 0,
584
+ isFatal: false,
585
+ attempt: 1,
586
+ willRetry: false,
587
+ totalAttempts: 1,
588
+ });
589
+ overallProgress.upload();
590
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Failed to invoke webhook:');
591
+ renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, error);
592
+ }
593
+ }
594
+ throw err;
595
+ }
596
+ finally {
597
+ insideFunctionSpecifics.forgetBrowserEventLoop(params.logLevel);
598
+ }
599
+ };
600
+ exports.launchHandler = launchHandler;
@@ -0,0 +1,16 @@
1
+ import type { ServerlessPayload } from '../constants';
2
+ import type { InsideFunctionSpecifics, ProviderSpecifics } from '../provider-implementation';
3
+ import type { GenericRenderProgress } from '../render-progress';
4
+ import type { CloudProvider } from '../types';
5
+ type Options<Provider extends CloudProvider> = {
6
+ expectedBucketOwner: string;
7
+ timeoutInMilliseconds: number;
8
+ retriesRemaining: number;
9
+ providerSpecifics: ProviderSpecifics<Provider>;
10
+ insideFunctionSpecifics: InsideFunctionSpecifics;
11
+ };
12
+ export declare const progressHandler: <Provider extends CloudProvider>({ params, options, }: {
13
+ params: ServerlessPayload<Provider>;
14
+ options: Options<Provider>;
15
+ }) => Promise<GenericRenderProgress<Provider>>;
16
+ export {};
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.progressHandler = void 0;
4
+ const constants_1 = require("../constants");
5
+ const progress_1 = require("../progress");
6
+ const check_version_mismatch_1 = require("./check-version-mismatch");
7
+ const progressHandler = async ({ params, options, }) => {
8
+ var _a;
9
+ if (params.type !== constants_1.ServerlessRoutines.status) {
10
+ throw new TypeError('Expected status type');
11
+ }
12
+ (0, check_version_mismatch_1.checkVersionMismatch)({
13
+ apiName: 'getRenderProgress()',
14
+ insideFunctionSpecifics: options.insideFunctionSpecifics,
15
+ params,
16
+ });
17
+ try {
18
+ const progress = await (0, progress_1.getProgress)({
19
+ bucketName: params.bucketName,
20
+ renderId: params.renderId,
21
+ expectedBucketOwner: options.expectedBucketOwner,
22
+ region: options.providerSpecifics.getCurrentRegionInFunction(),
23
+ memorySizeInMb: options.insideFunctionSpecifics.getCurrentMemorySizeInMb(),
24
+ timeoutInMilliseconds: options.timeoutInMilliseconds,
25
+ customCredentials: (_a = params.s3OutputProvider) !== null && _a !== void 0 ? _a : null,
26
+ providerSpecifics: options.providerSpecifics,
27
+ forcePathStyle: params.forcePathStyle,
28
+ functionName: options.insideFunctionSpecifics.getCurrentFunctionName(),
29
+ });
30
+ return progress;
31
+ }
32
+ catch (err) {
33
+ if (options.retriesRemaining === 0) {
34
+ throw err;
35
+ }
36
+ if (err.message.includes('No render with ID')) {
37
+ await new Promise((resolve) => {
38
+ setTimeout(resolve, 1000);
39
+ });
40
+ return (0, exports.progressHandler)({
41
+ params,
42
+ options: {
43
+ expectedBucketOwner: options.expectedBucketOwner,
44
+ timeoutInMilliseconds: options.timeoutInMilliseconds,
45
+ retriesRemaining: options.retriesRemaining - 1,
46
+ providerSpecifics: options.providerSpecifics,
47
+ insideFunctionSpecifics: options.insideFunctionSpecifics,
48
+ },
49
+ });
50
+ }
51
+ throw err;
52
+ }
53
+ };
54
+ exports.progressHandler = progressHandler;