@remotion/lambda 4.0.0-oops.3 → 4.0.0-prefetch.10
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.
- package/dist/admin/bundle-lambda.js +1 -0
- package/dist/admin/make-layer-public.js +8 -8
- package/dist/api/bucket-exists.d.ts +1 -1
- package/dist/api/clean-items.d.ts +1 -1
- package/dist/api/clean-items.js +2 -5
- package/dist/api/create-bucket.d.ts +1 -1
- package/dist/api/create-function.d.ts +4 -3
- package/dist/api/create-function.js +3 -2
- package/dist/api/delete-function.d.ts +1 -1
- package/dist/api/delete-site.d.ts +1 -1
- package/dist/api/deploy-function.d.ts +3 -2
- package/dist/api/deploy-function.js +7 -2
- package/dist/api/deploy-site.d.ts +3 -3
- package/dist/api/deploy-site.js +2 -3
- package/dist/api/download-media.d.ts +2 -2
- package/dist/api/enable-s3-website.d.ts +1 -1
- package/dist/api/estimate-price.d.ts +2 -2
- package/dist/api/get-aws-client.d.ts +2 -2
- package/dist/api/get-aws-client.js +5 -1
- package/dist/api/get-buckets.d.ts +1 -1
- package/dist/api/get-function-info.d.ts +2 -3
- package/dist/api/get-functions.d.ts +2 -2
- package/dist/api/get-functions.js +2 -1
- package/dist/api/get-or-create-bucket.d.ts +1 -1
- package/dist/api/get-regions.d.ts +1 -1
- package/dist/api/get-render-progress.d.ts +2 -2
- package/dist/api/get-render-progress.js +2 -0
- package/dist/api/get-sites.d.ts +2 -2
- package/dist/api/iam-validation/role-permissions.d.ts +2 -1
- package/dist/api/iam-validation/simulate-rule.d.ts +1 -1
- package/dist/api/iam-validation/simulate.d.ts +2 -2
- package/dist/api/mock-functions.d.ts +6 -7
- package/dist/api/presign-url.d.ts +3 -2
- package/dist/api/presign-url.js +5 -0
- package/dist/api/render-media-on-lambda.d.ts +15 -8
- package/dist/api/render-media-on-lambda.js +58 -32
- package/dist/api/render-still-on-lambda.d.ts +9 -7
- package/dist/api/render-still-on-lambda.js +49 -31
- package/dist/api/upload-dir.d.ts +2 -2
- package/dist/api/upload-dir.js +9 -4
- package/dist/cli/args.d.ts +5 -3
- package/dist/cli/commands/functions/deploy.js +8 -3
- package/dist/cli/commands/render/progress.d.ts +4 -4
- package/dist/cli/commands/render/progress.js +11 -3
- package/dist/cli/commands/render/render.js +15 -10
- package/dist/cli/commands/sites/create.js +2 -3
- package/dist/cli/commands/sites/ls.js +1 -2
- package/dist/cli/commands/sites/rm.js +2 -3
- package/dist/cli/commands/sites/rmall.js +2 -3
- package/dist/cli/commands/still.js +2 -9
- package/dist/cli/get-aws-region.d.ts +1 -1
- package/dist/cli/get-aws-region.js +2 -1
- package/dist/cli/helpers/find-function-name.js +3 -2
- package/dist/cli/helpers/get-cloudwatch-stream-url.d.ts +2 -2
- package/dist/cli/helpers/progress-bar.js +1 -2
- package/dist/cli/index.js +11 -1
- package/dist/defaults.js +5 -1
- package/dist/functions/chunk-optimization/can-use-optimization.d.ts +1 -1
- package/dist/functions/chunk-optimization/can-use-optimization.js +2 -2
- package/dist/functions/chunk-optimization/collect-data.d.ts +1 -1
- package/dist/functions/chunk-optimization/get-frame-ranges-from-profile.d.ts +1 -1
- package/dist/functions/chunk-optimization/get-profile-duration.d.ts +1 -1
- package/dist/functions/chunk-optimization/is-valid-profile.d.ts +1 -1
- package/dist/functions/chunk-optimization/is-valid-profile.js +2 -2
- package/dist/functions/chunk-optimization/optimize-invocation-order.d.ts +1 -1
- package/dist/functions/chunk-optimization/optimize-profile.d.ts +1 -1
- package/dist/functions/chunk-optimization/plan-frame-ranges.d.ts +3 -3
- package/dist/functions/chunk-optimization/plan-frame-ranges.js +7 -6
- package/dist/functions/chunk-optimization/s3-optimization-file.d.ts +2 -2
- package/dist/functions/chunk-optimization/s3-optimization-file.js +1 -0
- package/dist/functions/chunk-optimization/simulate-frame-ranges.d.ts +1 -1
- package/dist/functions/chunk-optimization/sort-by-duration.d.ts +1 -1
- package/dist/functions/chunk-optimization/types.d.ts +2 -2
- package/dist/functions/helpers/calculate-chunk-times.d.ts +1 -1
- package/dist/functions/helpers/calculate-price-from-bucket.d.ts +4 -4
- package/dist/functions/helpers/check-if-render-exists.d.ts +3 -0
- package/dist/functions/helpers/check-if-render-exists.js +14 -0
- package/dist/functions/helpers/concat-videos.d.ts +6 -4
- package/dist/functions/helpers/concat-videos.js +8 -2
- package/dist/functions/helpers/create-post-render-data.d.ts +6 -6
- package/dist/functions/helpers/create-post-render-data.js +12 -7
- package/dist/functions/helpers/delete-chunks.d.ts +3 -3
- package/dist/functions/helpers/expected-out-name.d.ts +1 -1
- package/dist/functions/helpers/find-output-file-in-bucket.d.ts +2 -2
- package/dist/functions/helpers/find-output-file-in-bucket.js +6 -0
- package/dist/functions/helpers/format-costs-info.d.ts +1 -1
- package/dist/functions/helpers/get-browser-instance.d.ts +2 -1
- package/dist/functions/helpers/get-browser-instance.js +3 -1
- package/dist/functions/helpers/get-cleanup-progress.d.ts +2 -2
- package/dist/functions/helpers/get-current-architecture.d.ts +1 -1
- package/dist/functions/helpers/get-encoding-metadata.d.ts +2 -2
- package/dist/functions/helpers/get-files-to-delete.js +3 -3
- package/dist/functions/helpers/get-final-encoding-status.d.ts +2 -2
- package/dist/functions/helpers/get-lambdas-invoked-stats.d.ts +8 -3
- package/dist/functions/helpers/get-lambdas-invoked-stats.js +8 -8
- package/dist/functions/helpers/get-output-url-from-metadata.d.ts +1 -1
- package/dist/functions/helpers/get-post-render-data.d.ts +2 -2
- package/dist/functions/helpers/get-progress.d.ts +2 -2
- package/dist/functions/helpers/get-progress.js +22 -11
- package/dist/functions/helpers/get-render-metadata.d.ts +2 -2
- package/dist/functions/helpers/get-retry-stats.d.ts +1 -1
- package/dist/functions/helpers/get-retry-stats.js +1 -1
- package/dist/functions/helpers/get-time-to-finish.d.ts +1 -1
- package/dist/functions/helpers/inspect-errors.d.ts +3 -3
- package/dist/functions/helpers/io.d.ts +13 -6
- package/dist/functions/helpers/io.js +21 -3
- package/dist/functions/helpers/min-max.d.ts +1 -1
- package/dist/functions/helpers/min-max.js +1 -1
- package/dist/functions/helpers/print-cloudwatch-helper.d.ts +2 -2
- package/dist/functions/helpers/read-with-progress.d.ts +3 -2
- package/dist/functions/helpers/read-with-progress.js +13 -1
- package/dist/functions/helpers/validate-composition.d.ts +10 -4
- package/dist/functions/helpers/validate-composition.js +7 -1
- package/dist/functions/helpers/write-lambda-error.d.ts +1 -1
- package/dist/functions/helpers/write-lambda-error.js +1 -0
- package/dist/functions/helpers/write-post-render-data.d.ts +2 -2
- package/dist/functions/helpers/write-post-render-data.js +1 -0
- package/dist/functions/index.d.ts +3 -2
- package/dist/functions/index.js +14 -7
- package/dist/functions/info.d.ts +2 -2
- package/dist/functions/info.js +2 -1
- package/dist/functions/launch.d.ts +1 -1
- package/dist/functions/launch.js +73 -26
- package/dist/functions/progress.d.ts +1 -1
- package/dist/functions/progress.js +7 -0
- package/dist/functions/renderer.d.ts +1 -1
- package/dist/functions/renderer.js +105 -71
- package/dist/functions/start.d.ts +6 -2
- package/dist/functions/start.js +25 -3
- package/dist/functions/still.d.ts +1 -1
- package/dist/functions/still.js +26 -7
- package/dist/index.d.ts +33 -18
- package/dist/pricing/price-per-1-s.d.ts +1 -1
- package/dist/shared/aws-clients.d.ts +1 -1
- package/dist/shared/bundle-site.d.ts +1 -6
- package/dist/shared/call-lambda.d.ts +3 -3
- package/dist/shared/check-credentials.js +2 -2
- package/dist/shared/constants.d.ts +38 -17
- package/dist/shared/constants.js +8 -7
- package/dist/shared/content-disposition-header.d.ts +7 -0
- package/dist/shared/content-disposition-header.js +19 -0
- package/dist/shared/convert-to-serve-url.d.ts +1 -1
- package/dist/shared/get-account-id.d.ts +1 -1
- package/dist/shared/get-cloudwatch-stream-url.d.ts +8 -0
- package/dist/shared/get-cloudwatch-stream-url.js +7 -0
- package/dist/shared/get-function-version.d.ts +2 -3
- package/dist/shared/get-most-expensive-chunks.d.ts +8 -0
- package/dist/shared/get-most-expensive-chunks.js +25 -0
- package/dist/shared/hosted-layers.d.ts +2 -2
- package/dist/shared/hosted-layers.js +60 -60
- package/dist/shared/is-in-lambda.js +5 -1
- package/dist/shared/lambda-version-string.d.ts +1 -0
- package/dist/shared/lambda-version-string.js +7 -0
- package/dist/shared/make-s3-key.d.ts +1 -0
- package/dist/shared/make-s3-key.js +11 -0
- package/dist/shared/make-s3-url.d.ts +1 -1
- package/dist/shared/p-limit.d.ts +1 -0
- package/dist/shared/p-limit.js +57 -0
- package/dist/shared/random-hash.d.ts +2 -2
- package/dist/shared/random-hash.js +1 -1
- package/dist/shared/return-values.d.ts +7 -7
- package/dist/shared/return-values.js +0 -1
- package/dist/shared/stream-to-string.d.ts +2 -1
- package/dist/shared/truthy.d.ts +3 -0
- package/dist/shared/truthy.js +7 -0
- package/dist/shared/validate-aws-region.d.ts +1 -1
- package/dist/shared/validate-custom-role-arn.d.ts +1 -0
- package/dist/shared/validate-custom-role-arn.js +11 -0
- package/dist/shared/validate-download-behavior.d.ts +1 -0
- package/dist/shared/validate-download-behavior.js +21 -0
- package/dist/shared/validate-frames-per-lambda.js +1 -1
- package/dist/shared/validate-lambda-codec.d.ts +4 -0
- package/dist/shared/validate-lambda-codec.js +30 -0
- package/dist/shared/validate-outname.d.ts +1 -1
- package/dist/shared/validate-presign-expiration.d.ts +0 -2
- package/dist/shared/validate-presign-expiration.js +7 -7
- package/dist/shared/validate-privacy.d.ts +1 -1
- package/dist/shared/validate-privacy.js +2 -2
- package/package.json +13 -14
- package/remotionlambda.zip +0 -0
- package/dist/cli/helpers/format-bytes.d.ts +0 -6
- package/dist/cli/helpers/format-bytes.js +0 -103
- package/dist/shared/chunk.d.ts +0 -1
- package/dist/shared/chunk.js +0 -11
package/dist/functions/launch.js
CHANGED
|
@@ -8,6 +8,7 @@ const client_lambda_1 = require("@aws-sdk/client-lambda");
|
|
|
8
8
|
const renderer_1 = require("@remotion/renderer");
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const remotion_1 = require("remotion");
|
|
11
|
+
const version_1 = require("remotion/version");
|
|
11
12
|
const aws_clients_1 = require("../shared/aws-clients");
|
|
12
13
|
const constants_1 = require("../shared/constants");
|
|
13
14
|
const docs_url_1 = require("../shared/docs-url");
|
|
@@ -39,6 +40,27 @@ const timer_1 = require("./helpers/timer");
|
|
|
39
40
|
const validate_composition_1 = require("./helpers/validate-composition");
|
|
40
41
|
const write_lambda_error_1 = require("./helpers/write-lambda-error");
|
|
41
42
|
const write_post_render_data_1 = require("./helpers/write-post-render-data");
|
|
43
|
+
const callFunctionWithRetry = async (payload, retries = 0) => {
|
|
44
|
+
try {
|
|
45
|
+
await (0, aws_clients_1.getLambdaClient)((0, get_current_region_1.getCurrentRegionInFunction)()).send(new client_lambda_1.InvokeCommand({
|
|
46
|
+
FunctionName: process.env.AWS_LAMBDA_FUNCTION_NAME,
|
|
47
|
+
// @ts-expect-error
|
|
48
|
+
Payload: JSON.stringify(payload),
|
|
49
|
+
InvocationType: 'Event',
|
|
50
|
+
}), {});
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (err.name === 'ResourceConflictException') {
|
|
54
|
+
if (retries > 10) {
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
await new Promise((resolve) => {
|
|
58
|
+
setTimeout(resolve, 1000);
|
|
59
|
+
});
|
|
60
|
+
return callFunctionWithRetry(payload, retries + 1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
42
64
|
const innerLaunchHandler = async (params, options) => {
|
|
43
65
|
var _a, _b;
|
|
44
66
|
if (params.type !== constants_1.LambdaRoutines.launch) {
|
|
@@ -46,7 +68,7 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
46
68
|
}
|
|
47
69
|
const startedDate = Date.now();
|
|
48
70
|
const [browserInstance, optimization] = await Promise.all([
|
|
49
|
-
(0, get_browser_instance_1.getBrowserInstance)(
|
|
71
|
+
(0, get_browser_instance_1.getBrowserInstance)(renderer_1.RenderInternals.isEqualOrBelowLogLevel(params.logLevel, 'verbose'), params.chromiumOptions),
|
|
50
72
|
(0, s3_optimization_file_1.getOptimization)({
|
|
51
73
|
bucketName: params.bucketName,
|
|
52
74
|
siteId: (0, make_s3_url_1.getServeUrlHash)(params.serveUrl),
|
|
@@ -55,22 +77,30 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
55
77
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
56
78
|
}),
|
|
57
79
|
]);
|
|
80
|
+
const downloadMap = renderer_1.RenderInternals.makeDownloadMap();
|
|
58
81
|
const comp = await (0, validate_composition_1.validateComposition)({
|
|
59
82
|
serveUrl: params.serveUrl,
|
|
60
83
|
composition: params.composition,
|
|
61
84
|
browserInstance,
|
|
62
85
|
inputProps: params.inputProps,
|
|
63
86
|
envVariables: params.envVariables,
|
|
87
|
+
ffmpegExecutable: null,
|
|
88
|
+
ffprobeExecutable: null,
|
|
89
|
+
timeoutInMilliseconds: params.timeoutInMilliseconds,
|
|
90
|
+
chromiumOptions: params.chromiumOptions,
|
|
91
|
+
port: null,
|
|
92
|
+
downloadMap,
|
|
64
93
|
});
|
|
65
|
-
remotion_1.Internals.validateDurationInFrames(comp.durationInFrames, 'passed to
|
|
66
|
-
remotion_1.Internals.validateFps(comp.fps, 'passed to
|
|
67
|
-
remotion_1.Internals.validateDimension(comp.height, 'height', 'passed to
|
|
68
|
-
remotion_1.Internals.validateDimension(comp.width, 'width', 'passed to
|
|
94
|
+
remotion_1.Internals.validateDurationInFrames(comp.durationInFrames, 'passed to a Lambda render');
|
|
95
|
+
remotion_1.Internals.validateFps(comp.fps, 'passed to a Lambda render', false);
|
|
96
|
+
remotion_1.Internals.validateDimension(comp.height, 'height', 'passed to a Lambda render');
|
|
97
|
+
remotion_1.Internals.validateDimension(comp.width, 'width', 'passed to a Lambda render');
|
|
98
|
+
renderer_1.RenderInternals.validateConcurrency(params.concurrencyPerLambda, 'concurrencyPerLambda');
|
|
69
99
|
const realFrameRange = renderer_1.RenderInternals.getRealFrameRange(comp.durationInFrames, params.frameRange);
|
|
70
|
-
const frameCount = renderer_1.RenderInternals.
|
|
71
|
-
const framesPerLambda = (_a = params.framesPerLambda) !== null && _a !== void 0 ? _a : (0, best_frames_per_lambda_param_1.bestFramesPerLambdaParam)(frameCount);
|
|
100
|
+
const frameCount = renderer_1.RenderInternals.getFramesToRender(realFrameRange, params.everyNthFrame);
|
|
101
|
+
const framesPerLambda = (_a = params.framesPerLambda) !== null && _a !== void 0 ? _a : (0, best_frames_per_lambda_param_1.bestFramesPerLambdaParam)(frameCount.length);
|
|
72
102
|
(0, validate_frames_per_lambda_1.validateFramesPerLambda)(framesPerLambda);
|
|
73
|
-
const chunkCount = Math.ceil(frameCount / framesPerLambda);
|
|
103
|
+
const chunkCount = Math.ceil(frameCount.length / framesPerLambda);
|
|
74
104
|
if (chunkCount > constants_1.MAX_FUNCTIONS_PER_RENDER) {
|
|
75
105
|
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.`);
|
|
76
106
|
}
|
|
@@ -78,12 +108,12 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
78
108
|
(0, validate_privacy_1.validatePrivacy)(params.privacy);
|
|
79
109
|
renderer_1.RenderInternals.validatePuppeteerTimeout(params.timeoutInMilliseconds);
|
|
80
110
|
const { chunks, didUseOptimization } = (0, plan_frame_ranges_1.planFrameRanges)({
|
|
81
|
-
chunkCount,
|
|
82
111
|
framesPerLambda,
|
|
83
112
|
optimization,
|
|
84
113
|
// TODO: Re-enable chunk optimization later
|
|
85
114
|
shouldUseOptimization: false,
|
|
86
115
|
frameRange: realFrameRange,
|
|
116
|
+
everyNthFrame: params.everyNthFrame,
|
|
87
117
|
});
|
|
88
118
|
const sortedChunks = chunks.slice().sort((a, b) => a[0] - b[0]);
|
|
89
119
|
const invokers = Math.round(Math.sqrt(chunks.length));
|
|
@@ -105,18 +135,21 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
105
135
|
inputProps: params.inputProps,
|
|
106
136
|
renderId: params.renderId,
|
|
107
137
|
imageFormat: params.imageFormat,
|
|
108
|
-
codec: params.codec,
|
|
138
|
+
codec: params.codec === 'h264' ? 'h264-mkv' : params.codec,
|
|
109
139
|
crf: params.crf,
|
|
110
140
|
envVariables: params.envVariables,
|
|
111
141
|
pixelFormat: params.pixelFormat,
|
|
112
142
|
proResProfile: params.proResProfile,
|
|
113
143
|
quality: params.quality,
|
|
114
144
|
privacy: params.privacy,
|
|
115
|
-
logLevel: (_a = params.logLevel) !== null && _a !== void 0 ? _a :
|
|
145
|
+
logLevel: (_a = params.logLevel) !== null && _a !== void 0 ? _a : 'info',
|
|
116
146
|
attempt: 1,
|
|
117
147
|
timeoutInMilliseconds: params.timeoutInMilliseconds,
|
|
118
148
|
chromiumOptions: params.chromiumOptions,
|
|
119
149
|
scale: params.scale,
|
|
150
|
+
everyNthFrame: params.everyNthFrame,
|
|
151
|
+
concurrencyPerLambda: params.concurrencyPerLambda,
|
|
152
|
+
muted: params.muted,
|
|
120
153
|
};
|
|
121
154
|
return payload;
|
|
122
155
|
});
|
|
@@ -139,7 +172,7 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
139
172
|
type: 'video',
|
|
140
173
|
imageFormat: params.imageFormat,
|
|
141
174
|
inputProps: params.inputProps,
|
|
142
|
-
lambdaVersion:
|
|
175
|
+
lambdaVersion: version_1.VERSION,
|
|
143
176
|
framesPerLambda,
|
|
144
177
|
memorySizeInMb: Number(process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE),
|
|
145
178
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
@@ -153,22 +186,18 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
153
186
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
154
187
|
privacy: 'private',
|
|
155
188
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
189
|
+
downloadBehavior: null,
|
|
156
190
|
});
|
|
157
191
|
await Promise.all(lambdaPayloads.map(async (payload, index) => {
|
|
158
192
|
const callingLambdaTimer = (0, timer_1.timer)('Calling chunk ' + index);
|
|
159
|
-
await (
|
|
160
|
-
FunctionName: process.env.AWS_LAMBDA_FUNCTION_NAME,
|
|
161
|
-
// @ts-expect-error
|
|
162
|
-
Payload: JSON.stringify(payload),
|
|
163
|
-
InvocationType: 'Event',
|
|
164
|
-
}), {});
|
|
193
|
+
await callFunctionWithRetry(payload);
|
|
165
194
|
callingLambdaTimer.end();
|
|
166
195
|
}));
|
|
167
196
|
reqSend.end();
|
|
168
197
|
let lastProgressUploaded = 0;
|
|
169
198
|
let encodingStop = null;
|
|
170
199
|
const onProgress = (framesEncoded, start) => {
|
|
171
|
-
const relativeProgress = framesEncoded / frameCount;
|
|
200
|
+
const relativeProgress = framesEncoded / frameCount.length;
|
|
172
201
|
const deltaSinceLastProgressUploaded = relativeProgress - lastProgressUploaded;
|
|
173
202
|
if (relativeProgress === 1) {
|
|
174
203
|
encodingStop = Date.now();
|
|
@@ -179,7 +208,7 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
179
208
|
lastProgressUploaded = relativeProgress;
|
|
180
209
|
const encodingProgress = {
|
|
181
210
|
framesEncoded,
|
|
182
|
-
totalFrames: frameCount,
|
|
211
|
+
totalFrames: frameCount.length,
|
|
183
212
|
doneIn: encodingStop ? encodingStop - start : null,
|
|
184
213
|
timeToInvoke: null,
|
|
185
214
|
};
|
|
@@ -190,6 +219,7 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
190
219
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
191
220
|
privacy: 'private',
|
|
192
221
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
222
|
+
downloadBehavior: null,
|
|
193
223
|
}).catch((err) => {
|
|
194
224
|
(0, write_lambda_error_1.writeLambdaError)({
|
|
195
225
|
bucketName: params.bucketName,
|
|
@@ -211,15 +241,18 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
211
241
|
});
|
|
212
242
|
});
|
|
213
243
|
};
|
|
244
|
+
const fps = comp.fps / params.everyNthFrame;
|
|
214
245
|
const { outfile, cleanupChunksProm, encodingStart } = await (0, concat_videos_1.concatVideosS3)({
|
|
215
246
|
bucket: params.bucketName,
|
|
216
247
|
expectedFiles: chunkCount,
|
|
217
248
|
onProgress,
|
|
218
|
-
numberOfFrames: frameCount,
|
|
249
|
+
numberOfFrames: frameCount.length,
|
|
219
250
|
renderId: params.renderId,
|
|
220
251
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
221
252
|
codec: params.codec,
|
|
222
253
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
254
|
+
fps,
|
|
255
|
+
numberOfGifLoops: params.numberOfGifLoops,
|
|
223
256
|
});
|
|
224
257
|
if (!encodingStop) {
|
|
225
258
|
encodingStop = Date.now();
|
|
@@ -233,6 +266,7 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
233
266
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
234
267
|
privacy: params.privacy,
|
|
235
268
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
269
|
+
downloadBehavior: params.downloadBehavior,
|
|
236
270
|
});
|
|
237
271
|
let chunkProm = Promise.resolve();
|
|
238
272
|
// TODO: Enable in a later release
|
|
@@ -255,8 +289,9 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
255
289
|
newTiming: (0, get_profile_duration_1.getProfileDuration)(optimizedProfile),
|
|
256
290
|
createdFromRenderId: params.renderId,
|
|
257
291
|
framesPerLambda,
|
|
258
|
-
lambdaVersion:
|
|
292
|
+
lambdaVersion: version_1.VERSION,
|
|
259
293
|
frameRange: realFrameRange,
|
|
294
|
+
everyNthFrame: params.everyNthFrame,
|
|
260
295
|
},
|
|
261
296
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
262
297
|
compositionId: params.composition,
|
|
@@ -275,10 +310,16 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
275
310
|
}),
|
|
276
311
|
]);
|
|
277
312
|
const finalEncodingProgress = {
|
|
278
|
-
framesEncoded: frameCount,
|
|
279
|
-
totalFrames: frameCount,
|
|
313
|
+
framesEncoded: frameCount.length,
|
|
314
|
+
totalFrames: frameCount.length,
|
|
280
315
|
doneIn: encodingStop ? encodingStop - encodingStart : null,
|
|
281
|
-
timeToInvoke: (0, get_lambdas_invoked_stats_1.getLambdasInvokedStats)(
|
|
316
|
+
timeToInvoke: (0, get_lambdas_invoked_stats_1.getLambdasInvokedStats)({
|
|
317
|
+
contents,
|
|
318
|
+
renderId: params.renderId,
|
|
319
|
+
estimatedRenderLambdaInvokations: renderMetadata.estimatedRenderLambdaInvokations,
|
|
320
|
+
checkIfAllLambdasWereInvoked: false,
|
|
321
|
+
startDate: renderMetadata.startedDate,
|
|
322
|
+
}).timeToInvokeLambdas,
|
|
282
323
|
};
|
|
283
324
|
const finalEncodingProgressProm = (0, io_1.lambdaWriteFile)({
|
|
284
325
|
bucketName: params.bucketName,
|
|
@@ -287,6 +328,7 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
287
328
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
288
329
|
privacy: 'private',
|
|
289
330
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
331
|
+
downloadBehavior: null,
|
|
290
332
|
});
|
|
291
333
|
const errorExplanationsProm = (0, inspect_errors_1.inspectErrors)({
|
|
292
334
|
contents,
|
|
@@ -305,7 +347,7 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
305
347
|
contents,
|
|
306
348
|
jobs,
|
|
307
349
|
});
|
|
308
|
-
const postRenderData =
|
|
350
|
+
const postRenderData = (0, create_post_render_data_1.createPostRenderData)({
|
|
309
351
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
310
352
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
311
353
|
renderId: params.renderId,
|
|
@@ -329,6 +371,11 @@ const innerLaunchHandler = async (params, options) => {
|
|
|
329
371
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
330
372
|
renderId: params.renderId,
|
|
331
373
|
});
|
|
374
|
+
await (0, io_1.lambdaDeleteFile)({
|
|
375
|
+
bucketName: params.bucketName,
|
|
376
|
+
key: (0, constants_1.initalizedMetadataKey)(params.renderId),
|
|
377
|
+
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
378
|
+
});
|
|
332
379
|
await Promise.all([cleanupChunksProm, fs_1.default.promises.rm(outfile)]);
|
|
333
380
|
};
|
|
334
381
|
const launchHandler = async (params, options) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.progressHandler = void 0;
|
|
4
|
+
const version_1 = require("remotion/version");
|
|
4
5
|
const constants_1 = require("../shared/constants");
|
|
5
6
|
const get_current_region_1 = require("./helpers/get-current-region");
|
|
6
7
|
const get_progress_1 = require("./helpers/get-progress");
|
|
@@ -8,6 +9,12 @@ const progressHandler = (lambdaParams, options) => {
|
|
|
8
9
|
if (lambdaParams.type !== constants_1.LambdaRoutines.status) {
|
|
9
10
|
throw new TypeError('Expected status type');
|
|
10
11
|
}
|
|
12
|
+
if (lambdaParams.version !== version_1.VERSION) {
|
|
13
|
+
if (!lambdaParams.version) {
|
|
14
|
+
throw new Error(`Version mismatch: When calling getRenderProgress(), the deployed Lambda function had version ${version_1.VERSION} but the @remotion/lambda package is an older version. Align the versions.`);
|
|
15
|
+
}
|
|
16
|
+
throw new Error(`Version mismatch: When calling getRenderProgress(), get deployed Lambda function had version ${version_1.VERSION} and the @remotion/lambda package has version ${lambdaParams.version}. Align the versions.`);
|
|
17
|
+
}
|
|
11
18
|
return (0, get_progress_1.getProgress)({
|
|
12
19
|
bucketName: lambdaParams.bucketName,
|
|
13
20
|
renderId: lambdaParams.renderId,
|
|
@@ -8,7 +8,6 @@ const client_lambda_1 = require("@aws-sdk/client-lambda");
|
|
|
8
8
|
const renderer_1 = require("@remotion/renderer");
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
|
-
const remotion_1 = require("remotion");
|
|
12
11
|
const aws_clients_1 = require("../shared/aws-clients");
|
|
13
12
|
const constants_1 = require("../shared/constants");
|
|
14
13
|
const clean_tmpdir_1 = require("./helpers/clean-tmpdir");
|
|
@@ -19,12 +18,11 @@ const get_folder_size_1 = require("./helpers/get-folder-size");
|
|
|
19
18
|
const io_1 = require("./helpers/io");
|
|
20
19
|
const write_lambda_error_1 = require("./helpers/write-lambda-error");
|
|
21
20
|
const renderHandler = async (params, options, logs) => {
|
|
22
|
-
var _a
|
|
21
|
+
var _a;
|
|
23
22
|
if (params.type !== constants_1.LambdaRoutines.renderer) {
|
|
24
23
|
throw new Error('Params must be renderer');
|
|
25
24
|
}
|
|
26
|
-
|
|
27
|
-
const browserInstance = await (0, get_browser_instance_1.getBrowserInstance)(remotion_1.Internals.Logging.isEqualOrBelowLogLevel(params.logLevel, 'verbose'), (_a = params.chromiumOptions) !== null && _a !== void 0 ? _a : {});
|
|
25
|
+
const browserInstance = await (0, get_browser_instance_1.getBrowserInstance)(renderer_1.RenderInternals.isEqualOrBelowLogLevel(params.logLevel, 'verbose'), (_a = params.chromiumOptions) !== null && _a !== void 0 ? _a : {});
|
|
28
26
|
const outputPath = renderer_1.RenderInternals.tmpDir('remotion-render-');
|
|
29
27
|
if (typeof params.chunk !== 'number') {
|
|
30
28
|
throw new Error('must pass chunk');
|
|
@@ -41,73 +39,107 @@ const renderHandler = async (params, options, logs) => {
|
|
|
41
39
|
};
|
|
42
40
|
const outdir = renderer_1.RenderInternals.tmpDir(constants_1.RENDERER_PATH_TOKEN);
|
|
43
41
|
const outputLocation = path_1.default.join(outdir, `localchunk-${String(params.chunk).padStart(8, '0')}.${renderer_1.RenderInternals.getFileExtensionFromCodec(params.codec, 'chunk')}`);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
42
|
+
const chunkCodec = params.codec === 'gif' ? 'h264-mkv' : params.codec;
|
|
43
|
+
const downloadMap = renderer_1.RenderInternals.makeDownloadMap();
|
|
44
|
+
const downloads = {};
|
|
45
|
+
await new Promise((resolve, reject) => {
|
|
46
|
+
var _a;
|
|
47
|
+
(0, renderer_1.renderMedia)({
|
|
48
|
+
composition: {
|
|
49
|
+
id: params.composition,
|
|
50
|
+
durationInFrames: params.durationInFrames,
|
|
51
|
+
fps: params.fps,
|
|
52
|
+
height: params.height,
|
|
53
|
+
width: params.width,
|
|
54
|
+
},
|
|
55
|
+
imageFormat: params.imageFormat,
|
|
56
|
+
inputProps: params.inputProps,
|
|
57
|
+
frameRange: params.frameRange,
|
|
58
|
+
onProgress: ({ renderedFrames, encodedFrames, stitchStage }) => {
|
|
59
|
+
if (renderedFrames % 10 === 0 &&
|
|
60
|
+
renderer_1.RenderInternals.isEqualOrBelowLogLevel(params.logLevel, 'verbose')) {
|
|
61
|
+
console.log(`Rendered ${renderedFrames} frames, encoded ${encodedFrames} frames, stage = ${stitchStage}`);
|
|
62
|
+
}
|
|
63
|
+
const allFrames = renderer_1.RenderInternals.getFramesToRender(params.frameRange, params.everyNthFrame);
|
|
64
|
+
if (renderedFrames === allFrames.length) {
|
|
65
|
+
console.log('Rendered all frames!');
|
|
66
|
+
}
|
|
67
|
+
chunkTimingData.timings[renderedFrames] = Date.now() - start;
|
|
68
|
+
},
|
|
69
|
+
parallelism: params.concurrencyPerLambda,
|
|
70
|
+
onStart: () => {
|
|
71
|
+
(0, io_1.lambdaWriteFile)({
|
|
72
|
+
privacy: 'private',
|
|
73
|
+
bucketName: params.bucketName,
|
|
74
|
+
body: JSON.stringify({
|
|
75
|
+
filesCleaned: clean_tmpdir_1.deletedFilesSize,
|
|
76
|
+
filesInTmp: fs_1.default.readdirSync('/tmp'),
|
|
77
|
+
isWarm: options.isWarm,
|
|
78
|
+
deletedFiles: clean_tmpdir_1.deletedFiles,
|
|
79
|
+
tmpSize: (0, get_folder_size_1.getFolderSizeRecursively)('/tmp'),
|
|
80
|
+
tmpDirFiles: (0, get_files_in_folder_1.getFolderFiles)('/tmp'),
|
|
81
|
+
}),
|
|
82
|
+
key: (0, constants_1.lambdaChunkInitializedKey)({
|
|
83
|
+
renderId: params.renderId,
|
|
84
|
+
chunk: params.chunk,
|
|
85
|
+
attempt: params.attempt,
|
|
86
|
+
}),
|
|
87
|
+
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
88
|
+
expectedBucketOwner: options.expectedBucketOwner,
|
|
89
|
+
downloadBehavior: null,
|
|
90
|
+
}).catch((err) => reject(err));
|
|
91
|
+
},
|
|
92
|
+
puppeteerInstance: browserInstance,
|
|
93
|
+
serveUrl: params.serveUrl,
|
|
94
|
+
quality: params.quality,
|
|
95
|
+
envVariables: params.envVariables,
|
|
96
|
+
dumpBrowserLogs: renderer_1.RenderInternals.isEqualOrBelowLogLevel(params.logLevel, 'verbose'),
|
|
97
|
+
verbose: renderer_1.RenderInternals.isEqualOrBelowLogLevel(params.logLevel, 'verbose'),
|
|
98
|
+
onBrowserLog: (log) => {
|
|
99
|
+
logs.push(log);
|
|
100
|
+
},
|
|
101
|
+
outputLocation,
|
|
102
|
+
codec: chunkCodec,
|
|
103
|
+
crf: (_a = params.crf) !== null && _a !== void 0 ? _a : undefined,
|
|
104
|
+
ffmpegExecutable: process.env.NODE_ENV === 'test' ? null : '/opt/bin/ffmpeg',
|
|
105
|
+
pixelFormat: params.pixelFormat,
|
|
106
|
+
proResProfile: params.proResProfile,
|
|
107
|
+
onDownload: (src) => {
|
|
108
|
+
console.log('Downloading', src);
|
|
109
|
+
downloads[src] = 0;
|
|
110
|
+
return ({ percent, downloaded }) => {
|
|
111
|
+
if (percent === null) {
|
|
112
|
+
console.log(`Download progress (${src}): ${downloaded} bytes. Don't know final size of download, no Content-Length header.`);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (
|
|
116
|
+
// Only report every 10% change
|
|
117
|
+
downloads[src] > percent - 0.1 &&
|
|
118
|
+
percent !== 1) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
downloads[src] = percent;
|
|
122
|
+
console.log(`Download progress (${src}): ${downloaded} bytes, ${(percent * 100).toFixed(1)}%`);
|
|
123
|
+
if (percent === 1) {
|
|
124
|
+
console.log(`Download complete: ${src}`);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
overwrite: false,
|
|
129
|
+
chromiumOptions: params.chromiumOptions,
|
|
130
|
+
scale: params.scale,
|
|
131
|
+
timeoutInMilliseconds: params.timeoutInMilliseconds,
|
|
132
|
+
port: null,
|
|
133
|
+
everyNthFrame: params.everyNthFrame,
|
|
134
|
+
numberOfGifLoops: null,
|
|
135
|
+
downloadMap,
|
|
136
|
+
muted: params.muted,
|
|
137
|
+
enforceAudioTrack: true,
|
|
138
|
+
})
|
|
139
|
+
.then(() => resolve())
|
|
140
|
+
.catch((err) => reject(err));
|
|
108
141
|
});
|
|
109
142
|
const endRendered = Date.now();
|
|
110
|
-
console.log('Adding silent audio, chunk', params.chunk);
|
|
111
143
|
const condensedTimingData = {
|
|
112
144
|
...chunkTimingData,
|
|
113
145
|
timings: Object.values(chunkTimingData.timings),
|
|
@@ -122,6 +154,7 @@ const renderHandler = async (params, options, logs) => {
|
|
|
122
154
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
123
155
|
privacy: params.privacy,
|
|
124
156
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
157
|
+
downloadBehavior: null,
|
|
125
158
|
});
|
|
126
159
|
await Promise.all([
|
|
127
160
|
fs_1.default.promises.rm(outputLocation, { recursive: true }),
|
|
@@ -129,15 +162,16 @@ const renderHandler = async (params, options, logs) => {
|
|
|
129
162
|
(0, io_1.lambdaWriteFile)({
|
|
130
163
|
bucketName: params.bucketName,
|
|
131
164
|
body: JSON.stringify(condensedTimingData, null, 2),
|
|
132
|
-
key:
|
|
165
|
+
key: (0, constants_1.lambdaTimingsKey)({
|
|
133
166
|
renderId: params.renderId,
|
|
134
167
|
chunk: params.chunk,
|
|
135
168
|
rendered: endRendered,
|
|
136
169
|
start,
|
|
137
|
-
})
|
|
170
|
+
}),
|
|
138
171
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
139
172
|
privacy: 'private',
|
|
140
173
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
174
|
+
downloadBehavior: null,
|
|
141
175
|
}),
|
|
142
176
|
]);
|
|
143
177
|
};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import { LambdaPayload } from '../shared/constants';
|
|
2
|
-
|
|
1
|
+
import type { LambdaPayload } from '../shared/constants';
|
|
2
|
+
declare type Options = {
|
|
3
|
+
expectedBucketOwner: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const startHandler: (params: LambdaPayload, options: Options) => Promise<{
|
|
3
6
|
bucketName: string;
|
|
4
7
|
renderId: string;
|
|
5
8
|
}>;
|
|
9
|
+
export {};
|
package/dist/functions/start.js
CHANGED
|
@@ -2,21 +2,37 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.startHandler = void 0;
|
|
4
4
|
const client_lambda_1 = require("@aws-sdk/client-lambda");
|
|
5
|
-
const
|
|
5
|
+
const version_1 = require("remotion/version");
|
|
6
6
|
const get_or_create_bucket_1 = require("../api/get-or-create-bucket");
|
|
7
7
|
const aws_clients_1 = require("../shared/aws-clients");
|
|
8
8
|
const constants_1 = require("../shared/constants");
|
|
9
9
|
const random_hash_1 = require("../shared/random-hash");
|
|
10
10
|
const get_current_region_1 = require("./helpers/get-current-region");
|
|
11
|
-
const
|
|
11
|
+
const io_1 = require("./helpers/io");
|
|
12
|
+
const startHandler = async (params, options) => {
|
|
12
13
|
var _a;
|
|
13
14
|
if (params.type !== constants_1.LambdaRoutines.start) {
|
|
14
15
|
throw new TypeError('Expected type start');
|
|
15
16
|
}
|
|
17
|
+
if (params.version !== version_1.VERSION) {
|
|
18
|
+
if (!params.version) {
|
|
19
|
+
throw new Error(`Version mismatch: When calling renderMediaOnLambda(), the deployed Lambda function had version ${version_1.VERSION} but the @remotion/lambda package is an older version. Align the versions.`);
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`Version mismatch: When calling renderMediaOnLambda(), get deployed Lambda function had version ${version_1.VERSION} and the @remotion/lambda package has version ${params.version}. Align the versions.`);
|
|
22
|
+
}
|
|
16
23
|
const { bucketName } = await (0, get_or_create_bucket_1.getOrCreateBucket)({
|
|
17
24
|
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
18
25
|
});
|
|
19
26
|
const renderId = (0, random_hash_1.randomHash)({ randomInTests: true });
|
|
27
|
+
const initialFile = (0, io_1.lambdaWriteFile)({
|
|
28
|
+
bucketName,
|
|
29
|
+
downloadBehavior: null,
|
|
30
|
+
region: (0, get_current_region_1.getCurrentRegionInFunction)(),
|
|
31
|
+
body: 'Render was initialized',
|
|
32
|
+
expectedBucketOwner: options.expectedBucketOwner,
|
|
33
|
+
key: (0, constants_1.initalizedMetadataKey)(renderId),
|
|
34
|
+
privacy: 'private',
|
|
35
|
+
});
|
|
20
36
|
const payload = {
|
|
21
37
|
type: constants_1.LambdaRoutines.launch,
|
|
22
38
|
framesPerLambda: params.framesPerLambda,
|
|
@@ -34,12 +50,17 @@ const startHandler = async (params) => {
|
|
|
34
50
|
quality: params.quality,
|
|
35
51
|
maxRetries: params.maxRetries,
|
|
36
52
|
privacy: params.privacy,
|
|
37
|
-
logLevel: (_a = params.logLevel) !== null && _a !== void 0 ? _a :
|
|
53
|
+
logLevel: (_a = params.logLevel) !== null && _a !== void 0 ? _a : 'info',
|
|
38
54
|
frameRange: params.frameRange,
|
|
39
55
|
outName: params.outName,
|
|
40
56
|
timeoutInMilliseconds: params.timeoutInMilliseconds,
|
|
41
57
|
chromiumOptions: params.chromiumOptions,
|
|
42
58
|
scale: params.scale,
|
|
59
|
+
numberOfGifLoops: params.numberOfGifLoops,
|
|
60
|
+
everyNthFrame: params.everyNthFrame,
|
|
61
|
+
concurrencyPerLambda: params.concurrencyPerLambda,
|
|
62
|
+
downloadBehavior: params.downloadBehavior,
|
|
63
|
+
muted: params.muted,
|
|
43
64
|
};
|
|
44
65
|
await (0, aws_clients_1.getLambdaClient)((0, get_current_region_1.getCurrentRegionInFunction)()).send(new client_lambda_1.InvokeCommand({
|
|
45
66
|
FunctionName: process.env.AWS_LAMBDA_FUNCTION_NAME,
|
|
@@ -47,6 +68,7 @@ const startHandler = async (params) => {
|
|
|
47
68
|
Payload: JSON.stringify(payload),
|
|
48
69
|
InvocationType: 'Event',
|
|
49
70
|
}));
|
|
71
|
+
await initialFile;
|
|
50
72
|
return {
|
|
51
73
|
bucketName,
|
|
52
74
|
renderId,
|