@remotion/serverless 4.0.514 → 4.0.515
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/cancellation-polling.d.ts +11 -0
- package/dist/cancellation-polling.js +51 -0
- package/dist/handlers/launch.js +32 -9
- package/dist/handlers/renderer.js +23 -3
- package/dist/handlers/start.js +14 -11
- package/dist/handlers/still.js +1 -1
- package/dist/overall-render-progress.d.ts +3 -2
- package/dist/overall-render-progress.js +4 -3
- package/dist/provider-implementation.d.ts +2 -1
- package/dist/stream-renderer.js +34 -4
- package/package.json +6 -6
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CloudProvider, ProviderSpecifics } from '@remotion/serverless-client';
|
|
2
|
+
export declare const startCancellationPolling: <Provider extends CloudProvider<string, Record<string, unknown>, Record<string, unknown>, string, object>>({ bucketName, renderId, region, providerSpecifics, forcePathStyle, intervalInMilliseconds, logLevel, onCancelled, }: {
|
|
3
|
+
bucketName: string;
|
|
4
|
+
renderId: string;
|
|
5
|
+
region: Provider["region"];
|
|
6
|
+
providerSpecifics: ProviderSpecifics<Provider>;
|
|
7
|
+
forcePathStyle: boolean;
|
|
8
|
+
intervalInMilliseconds: number;
|
|
9
|
+
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
10
|
+
onCancelled: () => void;
|
|
11
|
+
}) => () => void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startCancellationPolling = void 0;
|
|
4
|
+
const renderer_1 = require("@remotion/renderer");
|
|
5
|
+
const serverless_client_1 = require("@remotion/serverless-client");
|
|
6
|
+
const isMissingCancellationSignalError = (err) => {
|
|
7
|
+
const error = err;
|
|
8
|
+
return (error.name === 'NoSuchKey' ||
|
|
9
|
+
error.name === 'NotFound' ||
|
|
10
|
+
error.Code === 'NoSuchKey' ||
|
|
11
|
+
error.code === 'NoSuchKey');
|
|
12
|
+
};
|
|
13
|
+
const startCancellationPolling = ({ bucketName, renderId, region, providerSpecifics, forcePathStyle, intervalInMilliseconds, logLevel, onCancelled, }) => {
|
|
14
|
+
let stopped = false;
|
|
15
|
+
let timeout = null;
|
|
16
|
+
const poll = async () => {
|
|
17
|
+
try {
|
|
18
|
+
await providerSpecifics.headFile({
|
|
19
|
+
bucketName,
|
|
20
|
+
key: (0, serverless_client_1.cancellationKey)(renderId),
|
|
21
|
+
region,
|
|
22
|
+
customCredentials: null,
|
|
23
|
+
forcePathStyle,
|
|
24
|
+
requestHandler: null,
|
|
25
|
+
});
|
|
26
|
+
if (!stopped) {
|
|
27
|
+
stopped = true;
|
|
28
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, 'Render cancellation signal received.');
|
|
29
|
+
onCancelled();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
if (!isMissingCancellationSignalError(err)) {
|
|
34
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, 'Could not check for a render cancellation signal. Retrying.', err);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (!stopped) {
|
|
38
|
+
timeout = setTimeout(poll, intervalInMilliseconds);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
poll().catch((err) => {
|
|
42
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, 'Cancellation polling stopped unexpectedly.', err);
|
|
43
|
+
});
|
|
44
|
+
return () => {
|
|
45
|
+
stopped = true;
|
|
46
|
+
if (timeout !== null) {
|
|
47
|
+
clearTimeout(timeout);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
exports.startCancellationPolling = startCancellationPolling;
|
package/dist/handlers/launch.js
CHANGED
|
@@ -164,8 +164,9 @@ const innerLaunchHandler = async ({ params, options, overallProgress, registerCl
|
|
|
164
164
|
// Throttling a bit, allowing more progress if there is lower concurrency.
|
|
165
165
|
const progressEveryNthFrame = Math.ceil(chunks.length / 15);
|
|
166
166
|
const lambdaPayloads = chunks.map((chunkPayload) => {
|
|
167
|
-
var _a, _b, _c;
|
|
167
|
+
var _a, _b, _c, _d;
|
|
168
168
|
const payload = {
|
|
169
|
+
enableCancellation: (_a = params.enableCancellation) !== null && _a !== void 0 ? _a : false,
|
|
169
170
|
type: serverless_client_2.ServerlessRoutines.renderer,
|
|
170
171
|
frameRange: chunkPayload,
|
|
171
172
|
serveUrl: params.serveUrl,
|
|
@@ -186,13 +187,13 @@ const innerLaunchHandler = async ({ params, options, overallProgress, registerCl
|
|
|
186
187
|
pixelFormat: params.pixelFormat,
|
|
187
188
|
proResProfile: params.proResProfile,
|
|
188
189
|
x264Preset: params.x264Preset,
|
|
189
|
-
gopSize: (
|
|
190
|
+
gopSize: (_b = params.gopSize) !== null && _b !== void 0 ? _b : null,
|
|
190
191
|
jpegQuality: params.jpegQuality,
|
|
191
192
|
privacy: params.privacy,
|
|
192
|
-
logLevel: (
|
|
193
|
+
logLevel: (_c = params.logLevel) !== null && _c !== void 0 ? _c : 'info',
|
|
193
194
|
attempt: 1,
|
|
194
195
|
timeoutInMilliseconds: params.timeoutInMilliseconds,
|
|
195
|
-
chromiumOptions: (
|
|
196
|
+
chromiumOptions: (_d = params.chromiumOptions) !== null && _d !== void 0 ? _d : {},
|
|
196
197
|
scale: params.scale,
|
|
197
198
|
everyNthFrame: params.everyNthFrame,
|
|
198
199
|
concurrencyPerLambda: params.concurrencyPerFunction,
|
|
@@ -428,7 +429,7 @@ const innerLaunchHandler = async ({ params, options, overallProgress, registerCl
|
|
|
428
429
|
return postRenderData;
|
|
429
430
|
};
|
|
430
431
|
const launchHandler = async ({ params, options, providerSpecifics, insideFunctionSpecifics, }) => {
|
|
431
|
-
var _a, _b, _c, _d;
|
|
432
|
+
var _a, _b, _c, _d, _e;
|
|
432
433
|
if (params.type !== serverless_client_2.ServerlessRoutines.launch) {
|
|
433
434
|
throw new Error('Expected launch type');
|
|
434
435
|
}
|
|
@@ -452,6 +453,25 @@ const launchHandler = async ({ params, options, providerSpecifics, insideFunctio
|
|
|
452
453
|
cleanupTasks.length = 0;
|
|
453
454
|
return prom;
|
|
454
455
|
};
|
|
456
|
+
const cancelOtherRenderers = async () => {
|
|
457
|
+
if (!params.enableCancellation) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
try {
|
|
461
|
+
await (0, serverless_client_2.writeCancellationSignal)({
|
|
462
|
+
bucketName: params.bucketName,
|
|
463
|
+
renderId: params.renderId,
|
|
464
|
+
region: insideFunctionSpecifics.getCurrentRegionInFunction(),
|
|
465
|
+
expectedBucketOwner: options.expectedBucketOwner,
|
|
466
|
+
providerSpecifics,
|
|
467
|
+
forcePathStyle: params.forcePathStyle,
|
|
468
|
+
requestHandler: null,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
catch (err) {
|
|
472
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel: params.logLevel }, 'Could not signal other renderers to stop.', err);
|
|
473
|
+
}
|
|
474
|
+
};
|
|
455
475
|
const onTimeout = async () => {
|
|
456
476
|
var _a;
|
|
457
477
|
renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Function is about to time out. Can not finish render.');
|
|
@@ -461,6 +481,7 @@ const launchHandler = async ({ params, options, providerSpecifics, insideFunctio
|
|
|
461
481
|
globalThis._dumpUnreleasedBuffers.emit('dump-unreleased-buffers');
|
|
462
482
|
}
|
|
463
483
|
runCleanupTasks();
|
|
484
|
+
await cancelOtherRenderers();
|
|
464
485
|
if (!params.webhook) {
|
|
465
486
|
renderer_1.RenderInternals.Log.verbose({
|
|
466
487
|
indent: false,
|
|
@@ -522,6 +543,7 @@ const launchHandler = async ({ params, options, providerSpecifics, insideFunctio
|
|
|
522
543
|
const webhookDueToTimeout = setTimeout(onTimeout, Math.max(options.getRemainingTimeInMillis() - 1000, 1000));
|
|
523
544
|
renderer_1.RenderInternals.Log.info(logOptions, `Function has ${Math.max(options.getRemainingTimeInMillis() - 1000, 1000)} before it times out`);
|
|
524
545
|
const overallProgress = (0, overall_render_progress_1.makeOverallRenderProgress)({
|
|
546
|
+
cancellationEnabled: (_a = params.enableCancellation) !== null && _a !== void 0 ? _a : false,
|
|
525
547
|
renderId: params.renderId,
|
|
526
548
|
bucketName: params.bucketName,
|
|
527
549
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
@@ -545,10 +567,10 @@ const launchHandler = async ({ params, options, providerSpecifics, insideFunctio
|
|
|
545
567
|
});
|
|
546
568
|
clearTimeout(webhookDueToTimeout);
|
|
547
569
|
(0, send_telemetry_event_1.sendTelemetryEvent)({
|
|
548
|
-
licenseKey: (
|
|
570
|
+
licenseKey: (_b = params.licenseKey) !== null && _b !== void 0 ? _b : null,
|
|
549
571
|
logLevel: params.logLevel,
|
|
550
572
|
isStill: false,
|
|
551
|
-
isProduction: (
|
|
573
|
+
isProduction: (_c = params.isProduction) !== null && _c !== void 0 ? _c : true,
|
|
552
574
|
});
|
|
553
575
|
if (!params.webhook || webhookInvoked) {
|
|
554
576
|
return;
|
|
@@ -563,7 +585,7 @@ const launchHandler = async ({ params, options, providerSpecifics, insideFunctio
|
|
|
563
585
|
renderId: params.renderId,
|
|
564
586
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
565
587
|
bucketName: params.bucketName,
|
|
566
|
-
customData: (
|
|
588
|
+
customData: (_d = params.webhook.customData) !== null && _d !== void 0 ? _d : null,
|
|
567
589
|
outputUrl: postRenderData.outputFile,
|
|
568
590
|
lambdaErrors: postRenderData.errors,
|
|
569
591
|
outputFile: postRenderData.outputFile,
|
|
@@ -602,6 +624,7 @@ const launchHandler = async ({ params, options, providerSpecifics, insideFunctio
|
|
|
602
624
|
if (process.env.NODE_ENV === 'test') {
|
|
603
625
|
throw err;
|
|
604
626
|
}
|
|
627
|
+
await cancelOtherRenderers();
|
|
605
628
|
renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Error occurred', err);
|
|
606
629
|
overallProgress.addErrorWithoutUpload({
|
|
607
630
|
chunk: null,
|
|
@@ -631,7 +654,7 @@ const launchHandler = async ({ params, options, providerSpecifics, insideFunctio
|
|
|
631
654
|
renderId: params.renderId,
|
|
632
655
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
633
656
|
bucketName: params.bucketName,
|
|
634
|
-
customData: (
|
|
657
|
+
customData: (_e = params.webhook.customData) !== null && _e !== void 0 ? _e : null,
|
|
635
658
|
errors: [err].map((e) => ({
|
|
636
659
|
message: e.message,
|
|
637
660
|
name: e.name,
|
|
@@ -9,11 +9,12 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
9
9
|
const renderer_1 = require("@remotion/renderer");
|
|
10
10
|
const pure_1 = require("@remotion/renderer/pure");
|
|
11
11
|
const serverless_client_1 = require("@remotion/serverless-client");
|
|
12
|
+
const cancellation_polling_1 = require("../cancellation-polling");
|
|
12
13
|
const get_tmp_dir_1 = require("../get-tmp-dir");
|
|
13
14
|
const leak_detection_1 = require("../leak-detection");
|
|
14
15
|
const on_downloads_helpers_1 = require("../on-downloads-helpers");
|
|
15
16
|
const why_is_node_running_1 = require("../why-is-node-running");
|
|
16
|
-
const renderHandler = async ({ params, options, logs, onStream, providerSpecifics, insideFunctionSpecifics, onBrowserInstance, onMediaFiles, }) => {
|
|
17
|
+
const renderHandler = async ({ params, options, logs, onStream, providerSpecifics, insideFunctionSpecifics, onBrowserInstance, onMediaFiles, cancelSignal, }) => {
|
|
17
18
|
if (params.type !== serverless_client_1.ServerlessRoutines.renderer) {
|
|
18
19
|
throw new Error('Params must be renderer');
|
|
19
20
|
}
|
|
@@ -209,7 +210,7 @@ const renderHandler = async ({ params, options, logs, onStream, providerSpecific
|
|
|
209
210
|
audioCodec,
|
|
210
211
|
preferLossless: params.preferLossless,
|
|
211
212
|
browserExecutable: providerSpecifics.getChromiumPath(),
|
|
212
|
-
cancelSignal: undefined,
|
|
213
|
+
cancelSignal: cancelSignal !== null && cancelSignal !== void 0 ? cancelSignal : undefined,
|
|
213
214
|
disallowParallelEncoding: false,
|
|
214
215
|
ffmpegOverride: ({ args }) => args,
|
|
215
216
|
indent: false,
|
|
@@ -302,6 +303,23 @@ const rendererHandler = async ({ onStream, options, params, providerSpecifics, r
|
|
|
302
303
|
const leakDetection = (0, why_is_node_running_1.enableNodeIntrospection)(ENABLE_SLOW_LEAK_DETECTION);
|
|
303
304
|
let shouldKeepBrowserOpen = true;
|
|
304
305
|
let instance;
|
|
306
|
+
let cancellationRequested = false;
|
|
307
|
+
const { cancel, cancelSignal } = (0, renderer_1.makeCancelSignal)();
|
|
308
|
+
const stopCancellationPolling = params.enableCancellation
|
|
309
|
+
? (0, cancellation_polling_1.startCancellationPolling)({
|
|
310
|
+
bucketName: params.bucketName,
|
|
311
|
+
renderId: params.renderId,
|
|
312
|
+
region: insideFunctionSpecifics.getCurrentRegionInFunction(),
|
|
313
|
+
providerSpecifics,
|
|
314
|
+
forcePathStyle: params.forcePathStyle,
|
|
315
|
+
intervalInMilliseconds: 1000,
|
|
316
|
+
logLevel: params.logLevel,
|
|
317
|
+
onCancelled: () => {
|
|
318
|
+
cancellationRequested = true;
|
|
319
|
+
cancel();
|
|
320
|
+
},
|
|
321
|
+
})
|
|
322
|
+
: () => undefined;
|
|
305
323
|
try {
|
|
306
324
|
await renderHandler({
|
|
307
325
|
params,
|
|
@@ -314,6 +332,7 @@ const rendererHandler = async ({ onStream, options, params, providerSpecifics, r
|
|
|
314
332
|
instance = browserInstance;
|
|
315
333
|
},
|
|
316
334
|
onMediaFiles,
|
|
335
|
+
cancelSignal: params.enableCancellation ? cancelSignal : null,
|
|
317
336
|
});
|
|
318
337
|
}
|
|
319
338
|
catch (err) {
|
|
@@ -328,7 +347,7 @@ const rendererHandler = async ({ onStream, options, params, providerSpecifics, r
|
|
|
328
347
|
if (isRetryableError) {
|
|
329
348
|
shouldKeepBrowserOpen = false;
|
|
330
349
|
}
|
|
331
|
-
const shouldNotRetry = err.name === 'CancelledError';
|
|
350
|
+
const shouldNotRetry = cancellationRequested || err.name === 'CancelledError';
|
|
332
351
|
const shouldRetry = isRetryableError && params.retriesLeft > 0 && !shouldNotRetry;
|
|
333
352
|
renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, `Error occurred (will retry = ${String(shouldRetry)})`);
|
|
334
353
|
renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, err.stack);
|
|
@@ -354,6 +373,7 @@ const rendererHandler = async ({ onStream, options, params, providerSpecifics, r
|
|
|
354
373
|
});
|
|
355
374
|
}
|
|
356
375
|
finally {
|
|
376
|
+
stopCancellationPolling();
|
|
357
377
|
if (shouldKeepBrowserOpen && instance) {
|
|
358
378
|
insideFunctionSpecifics.forgetBrowserEventLoop({
|
|
359
379
|
logLevel: params.logLevel,
|
package/dist/handlers/start.js
CHANGED
|
@@ -5,7 +5,7 @@ const serverless_client_1 = require("@remotion/serverless-client");
|
|
|
5
5
|
const overall_render_progress_1 = require("../overall-render-progress");
|
|
6
6
|
const check_version_mismatch_1 = require("./check-version-mismatch");
|
|
7
7
|
const startHandler = async ({ params, options, providerSpecifics, insideFunctionSpecifics, }) => {
|
|
8
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
8
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
9
9
|
if (params.type !== serverless_client_1.ServerlessRoutines.start) {
|
|
10
10
|
throw new TypeError('Expected type start');
|
|
11
11
|
}
|
|
@@ -35,7 +35,7 @@ const startHandler = async ({ params, options, providerSpecifics, insideFunction
|
|
|
35
35
|
bucketName,
|
|
36
36
|
downloadBehavior: null,
|
|
37
37
|
region,
|
|
38
|
-
body: JSON.stringify((0, overall_render_progress_1.makeInitialOverallRenderProgress)(options.timeoutInMilliseconds + Date.now())),
|
|
38
|
+
body: JSON.stringify((0, overall_render_progress_1.makeInitialOverallRenderProgress)(options.timeoutInMilliseconds + Date.now(), (_b = params.enableCancellation) !== null && _b !== void 0 ? _b : false)),
|
|
39
39
|
expectedBucketOwner: options.expectedBucketOwner,
|
|
40
40
|
key: (0, serverless_client_1.overallProgressKey)(options.renderId),
|
|
41
41
|
privacy: 'private',
|
|
@@ -45,6 +45,7 @@ const startHandler = async ({ params, options, providerSpecifics, insideFunction
|
|
|
45
45
|
requestHandler: null,
|
|
46
46
|
});
|
|
47
47
|
const payload = {
|
|
48
|
+
enableCancellation: (_c = params.enableCancellation) !== null && _c !== void 0 ? _c : false,
|
|
48
49
|
type: serverless_client_1.ServerlessRoutines.launch,
|
|
49
50
|
framesPerFunction: params.framesPerLambda,
|
|
50
51
|
concurrency: params.concurrency,
|
|
@@ -55,12 +56,14 @@ const startHandler = async ({ params, options, providerSpecifics, insideFunction
|
|
|
55
56
|
renderId: options.renderId,
|
|
56
57
|
codec: params.codec,
|
|
57
58
|
imageFormat: params.imageFormat,
|
|
58
|
-
crf: (
|
|
59
|
+
crf: (_d = params.crf) !== null && _d !== void 0 ? _d : null,
|
|
59
60
|
envVariables: params.envVariables,
|
|
60
|
-
pixelFormat: (
|
|
61
|
-
proResProfile: (
|
|
62
|
-
x264Preset: params.x264Preset
|
|
63
|
-
|
|
61
|
+
pixelFormat: (_e = params.pixelFormat) !== null && _e !== void 0 ? _e : null,
|
|
62
|
+
proResProfile: (_f = params.proResProfile) !== null && _f !== void 0 ? _f : null,
|
|
63
|
+
x264Preset: (_g = params.x264Preset) !== null && _g !== void 0 ? _g : (params.codec === 'h264'
|
|
64
|
+
? insideFunctionSpecifics.defaultX264Preset
|
|
65
|
+
: null),
|
|
66
|
+
gopSize: (_h = params.gopSize) !== null && _h !== void 0 ? _h : null,
|
|
64
67
|
jpegQuality: params.jpegQuality,
|
|
65
68
|
maxRetries: params.maxRetries,
|
|
66
69
|
privacy: params.privacy,
|
|
@@ -83,8 +86,8 @@ const startHandler = async ({ params, options, providerSpecifics, insideFunction
|
|
|
83
86
|
encodingMaxRate: params.encodingMaxRate,
|
|
84
87
|
forceHeight: params.forceHeight,
|
|
85
88
|
forceWidth: params.forceWidth,
|
|
86
|
-
forceFps: (
|
|
87
|
-
forceDurationInFrames: (
|
|
89
|
+
forceFps: (_j = params.forceFps) !== null && _j !== void 0 ? _j : null,
|
|
90
|
+
forceDurationInFrames: (_k = params.forceDurationInFrames) !== null && _k !== void 0 ? _k : null,
|
|
88
91
|
rendererFunctionName: params.rendererFunctionName,
|
|
89
92
|
audioCodec: params.audioCodec,
|
|
90
93
|
offthreadVideoCacheSizeInBytes: params.offthreadVideoCacheSizeInBytes,
|
|
@@ -97,8 +100,8 @@ const startHandler = async ({ params, options, providerSpecifics, insideFunction
|
|
|
97
100
|
offthreadVideoThreads: params.offthreadVideoThreads,
|
|
98
101
|
storageClass: params.storageClass,
|
|
99
102
|
mediaCacheSizeInBytes: params.mediaCacheSizeInBytes,
|
|
100
|
-
isProduction: (
|
|
101
|
-
sampleRate: (
|
|
103
|
+
isProduction: (_l = params.isProduction) !== null && _l !== void 0 ? _l : true,
|
|
104
|
+
sampleRate: (_m = params.sampleRate) !== null && _m !== void 0 ? _m : 48000,
|
|
102
105
|
};
|
|
103
106
|
await providerSpecifics.callFunctionAsync({
|
|
104
107
|
functionName: insideFunctionSpecifics.getCurrentFunctionName(),
|
package/dist/handlers/still.js
CHANGED
|
@@ -153,7 +153,7 @@ const innerStillHandler = async ({ params, expectedBucketOwner, renderId, onStre
|
|
|
153
153
|
},
|
|
154
154
|
scale: params.scale,
|
|
155
155
|
};
|
|
156
|
-
const still = (0, overall_render_progress_1.makeInitialOverallRenderProgress)(timeoutInMilliseconds);
|
|
156
|
+
const still = (0, overall_render_progress_1.makeInitialOverallRenderProgress)(timeoutInMilliseconds, false);
|
|
157
157
|
still.renderMetadata = renderMetadata;
|
|
158
158
|
await providerSpecifics.writeFile({
|
|
159
159
|
bucketName,
|
|
@@ -21,8 +21,8 @@ export type OverallProgressHelper<Provider extends CloudProvider> = {
|
|
|
21
21
|
addReceivedArtifact: (asset: ReceivedArtifact<Provider>) => void;
|
|
22
22
|
getReceivedArtifacts: () => ReceivedArtifact<Provider>[];
|
|
23
23
|
};
|
|
24
|
-
export declare const makeInitialOverallRenderProgress: <Provider extends CloudProvider<string, Record<string, unknown>, Record<string, unknown>, string, object>>(timeoutTimestamp: number) => OverallRenderProgress<Provider>;
|
|
25
|
-
export declare const makeOverallRenderProgress: <Provider extends CloudProvider<string, Record<string, unknown>, Record<string, unknown>, string, object>>({ renderId, bucketName, expectedBucketOwner, region, timeoutTimestamp, logLevel, providerSpecifics, forcePathStyle, }: {
|
|
24
|
+
export declare const makeInitialOverallRenderProgress: <Provider extends CloudProvider<string, Record<string, unknown>, Record<string, unknown>, string, object>>(timeoutTimestamp: number, cancellationEnabled: boolean) => OverallRenderProgress<Provider>;
|
|
25
|
+
export declare const makeOverallRenderProgress: <Provider extends CloudProvider<string, Record<string, unknown>, Record<string, unknown>, string, object>>({ renderId, bucketName, expectedBucketOwner, region, timeoutTimestamp, logLevel, providerSpecifics, forcePathStyle, cancellationEnabled, }: {
|
|
26
26
|
renderId: string;
|
|
27
27
|
bucketName: string;
|
|
28
28
|
expectedBucketOwner: string;
|
|
@@ -31,4 +31,5 @@ export declare const makeOverallRenderProgress: <Provider extends CloudProvider<
|
|
|
31
31
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
32
32
|
providerSpecifics: ProviderSpecifics<Provider>;
|
|
33
33
|
forcePathStyle: boolean;
|
|
34
|
+
cancellationEnabled: boolean;
|
|
34
35
|
}) => OverallProgressHelper<Provider>;
|
|
@@ -9,8 +9,9 @@ const wait = (duration) => {
|
|
|
9
9
|
setTimeout(resolve, duration);
|
|
10
10
|
});
|
|
11
11
|
};
|
|
12
|
-
const makeInitialOverallRenderProgress = (timeoutTimestamp) => {
|
|
12
|
+
const makeInitialOverallRenderProgress = (timeoutTimestamp, cancellationEnabled) => {
|
|
13
13
|
return {
|
|
14
|
+
cancellationEnabled,
|
|
14
15
|
chunks: [],
|
|
15
16
|
framesRendered: 0,
|
|
16
17
|
framesEncoded: 0,
|
|
@@ -33,11 +34,11 @@ const makeInitialOverallRenderProgress = (timeoutTimestamp) => {
|
|
|
33
34
|
};
|
|
34
35
|
};
|
|
35
36
|
exports.makeInitialOverallRenderProgress = makeInitialOverallRenderProgress;
|
|
36
|
-
const makeOverallRenderProgress = ({ renderId, bucketName, expectedBucketOwner, region, timeoutTimestamp, logLevel, providerSpecifics, forcePathStyle, }) => {
|
|
37
|
+
const makeOverallRenderProgress = ({ renderId, bucketName, expectedBucketOwner, region, timeoutTimestamp, logLevel, providerSpecifics, forcePathStyle, cancellationEnabled, }) => {
|
|
37
38
|
let framesRendered = [];
|
|
38
39
|
let framesEncoded = [];
|
|
39
40
|
let lambdasInvoked = [];
|
|
40
|
-
const renderProgress = (0, exports.makeInitialOverallRenderProgress)(timeoutTimestamp);
|
|
41
|
+
const renderProgress = (0, exports.makeInitialOverallRenderProgress)(timeoutTimestamp, cancellationEnabled);
|
|
41
42
|
let dirty = false;
|
|
42
43
|
let dirtyReasons = [];
|
|
43
44
|
let uploadLoopPromise = null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BundlerInternals } from '@remotion/bundler';
|
|
2
|
-
import type { ChromiumOptions, EmittedArtifact, LogLevel } from '@remotion/renderer';
|
|
2
|
+
import type { ChromiumOptions, EmittedArtifact, LogLevel, X264Preset } from '@remotion/renderer';
|
|
3
3
|
import type { CloudProvider, DeleteAfter, GetFolderFiles, Privacy, ProviderSpecifics, ReceivedArtifact, WebhookPayload } from '@remotion/serverless-client';
|
|
4
4
|
import type { LaunchedBrowser } from './get-browser-instance';
|
|
5
5
|
export type MakeArtifactWithDetails<Provider extends CloudProvider> = (params: {
|
|
@@ -79,6 +79,7 @@ export type InvokeWebhookParams = {
|
|
|
79
79
|
};
|
|
80
80
|
export type InvokeWebhook = (params: InvokeWebhookParams) => Promise<void>;
|
|
81
81
|
export type InsideFunctionSpecifics<Provider extends CloudProvider> = {
|
|
82
|
+
defaultX264Preset: X264Preset | null;
|
|
82
83
|
getBrowserInstance: GetBrowserInstance;
|
|
83
84
|
forgetBrowserEventLoop: ForgetBrowserEventLoop;
|
|
84
85
|
timer: DebuggingTimer;
|
package/dist/stream-renderer.js
CHANGED
|
@@ -12,6 +12,29 @@ const streamRenderer = ({ payload, functionName, outdir, overallProgress, files,
|
|
|
12
12
|
throw new Error('Expected renderer type');
|
|
13
13
|
}
|
|
14
14
|
return new Promise((resolve) => {
|
|
15
|
+
const chunkFilename = (type) => (0, path_1.join)(outdir, `chunk:${String(payload.chunk).padStart(8, '0')}:${type}`);
|
|
16
|
+
// Stream the chunks to disk as they arrive instead of buffering them
|
|
17
|
+
// in memory. With many chunks arriving concurrently, buffering can
|
|
18
|
+
// exhaust the memory of the main function.
|
|
19
|
+
const getBinaryPayloadSink = ({ messageType }) => {
|
|
20
|
+
const filename = chunkFilename(messageType === 'video-chunk-rendered' ? 'video' : 'audio');
|
|
21
|
+
const writeStream = (0, fs_1.createWriteStream)(filename);
|
|
22
|
+
return {
|
|
23
|
+
write: (data) => new Promise((resolve_, reject) => {
|
|
24
|
+
writeStream.write(data, (err) => {
|
|
25
|
+
if (err) {
|
|
26
|
+
reject(err);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
resolve_();
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}),
|
|
33
|
+
end: () => new Promise((resolve_) => {
|
|
34
|
+
writeStream.end(resolve_);
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
};
|
|
15
38
|
const receivedStreamingPayload = ({ message }) => {
|
|
16
39
|
if (message.type === 'lambda-invoked') {
|
|
17
40
|
overallProgress.setLambdaInvoked(payload.chunk);
|
|
@@ -26,15 +49,21 @@ const streamRenderer = ({ payload, functionName, outdir, overallProgress, files,
|
|
|
26
49
|
return;
|
|
27
50
|
}
|
|
28
51
|
if (message.type === 'video-chunk-rendered') {
|
|
29
|
-
const filename = (
|
|
30
|
-
|
|
52
|
+
const filename = chunkFilename('video');
|
|
53
|
+
// An empty payload means the chunk was already streamed to disk
|
|
54
|
+
if (message.payload.length > 0) {
|
|
55
|
+
(0, fs_1.writeFileSync)(filename, message.payload);
|
|
56
|
+
}
|
|
31
57
|
files.push(filename);
|
|
32
58
|
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `Received video chunk for chunk ${payload.chunk}`);
|
|
33
59
|
return;
|
|
34
60
|
}
|
|
35
61
|
if (message.type === 'audio-chunk-rendered') {
|
|
36
|
-
const filename = (
|
|
37
|
-
|
|
62
|
+
const filename = chunkFilename('audio');
|
|
63
|
+
// An empty payload means the chunk was already streamed to disk
|
|
64
|
+
if (message.payload.length > 0) {
|
|
65
|
+
(0, fs_1.writeFileSync)(filename, message.payload);
|
|
66
|
+
}
|
|
38
67
|
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `Received audio chunk for chunk ${payload.chunk}`);
|
|
39
68
|
files.push(filename);
|
|
40
69
|
return;
|
|
@@ -91,6 +120,7 @@ const streamRenderer = ({ payload, functionName, outdir, overallProgress, files,
|
|
|
91
120
|
type: serverless_client_1.ServerlessRoutines.renderer,
|
|
92
121
|
receivedStreamingPayload,
|
|
93
122
|
requestHandler,
|
|
123
|
+
getBinaryPayloadSink,
|
|
94
124
|
})
|
|
95
125
|
.then(() => {
|
|
96
126
|
resolve({
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/serverless"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/serverless",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.515",
|
|
7
7
|
"description": "A runtime for distributed rendering",
|
|
8
8
|
"main": "dist",
|
|
9
9
|
"scripts": {
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@remotion/renderer": "4.0.
|
|
27
|
-
"@remotion/bundler": "4.0.
|
|
28
|
-
"@remotion/licensing": "4.0.
|
|
29
|
-
"@remotion/serverless-client": "4.0.
|
|
26
|
+
"@remotion/renderer": "4.0.515",
|
|
27
|
+
"@remotion/bundler": "4.0.515",
|
|
28
|
+
"@remotion/licensing": "4.0.515",
|
|
29
|
+
"@remotion/serverless-client": "4.0.515"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
32
|
+
"@remotion/eslint-config-internal": "4.0.515",
|
|
33
33
|
"eslint": "9.19.0",
|
|
34
34
|
"@typescript/native-preview": "7.0.0-dev.20260217.1"
|
|
35
35
|
},
|