@remotion/renderer 3.3.27 → 3.3.31

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 (41) hide show
  1. package/dist/browser/BrowserPage.js +1 -1
  2. package/dist/compositor/compositor.d.ts +9 -0
  3. package/dist/compositor/compositor.js +112 -0
  4. package/dist/determine-vcodec-ffmpeg-flags.d.ts +2 -0
  5. package/dist/determine-vcodec-ffmpeg-flags.js +13 -0
  6. package/dist/extract-frame-from-video.js +2 -2
  7. package/dist/get-compositions-from-bundle.d.ts +7 -0
  8. package/dist/get-compositions-from-bundle.js +55 -0
  9. package/dist/get-compositions-on-server.d.ts +3 -0
  10. package/dist/get-compositions-on-server.js +18 -0
  11. package/dist/get-compositions.js +9 -2
  12. package/dist/get-concurrency.d.ts +1 -1
  13. package/dist/get-concurrency.js +8 -1
  14. package/dist/get-extension-of-filename.js +5 -1
  15. package/dist/get-frame-of-video-slow.js +2 -2
  16. package/dist/index.d.ts +1 -1
  17. package/dist/make-cancel-signal.d.ts +7 -0
  18. package/dist/make-cancel-signal.js +20 -1
  19. package/dist/make-comp-manager-context.d.ts +2 -0
  20. package/dist/make-comp-manager-context.js +45 -0
  21. package/dist/prepare-server.d.ts +1 -1
  22. package/dist/prepare-server.js +5 -2
  23. package/dist/puppeteer-screenshot.d.ts +1 -1
  24. package/dist/render-frames.d.ts +1 -1
  25. package/dist/render-frames.js +6 -2
  26. package/dist/render-media.d.ts +1 -1
  27. package/dist/render-media.js +1 -1
  28. package/dist/render-on-server.d.ts +3 -0
  29. package/dist/render-on-server.js +82 -0
  30. package/dist/render-still.js +3 -2
  31. package/dist/render-svg.d.ts +8 -0
  32. package/dist/render-svg.js +28 -0
  33. package/dist/render-web-frame.d.ts +77 -0
  34. package/dist/render-web-frame.js +290 -0
  35. package/dist/screenshot-dom-element.js +5 -1
  36. package/dist/stitch-frames-to-video.js +8 -5
  37. package/dist/try-to-extract-frame-of-video-fast.js +2 -2
  38. package/dist/validate-concurrency.js +14 -9
  39. package/package.json +10 -10
  40. package/dist/compositor/payload.d.ts +0 -39
  41. package/dist/compositor/payload.js +0 -2
@@ -244,7 +244,7 @@ _Page_client = new WeakMap(), _Page_target = new WeakMap(), _Page_timeoutSetting
244
244
  expression = (0, util_1.pageBindingDeliverErrorValueString)(name, seq, _error);
245
245
  }
246
246
  }
247
- __classPrivateFieldGet(this, _Page_client, "f").send('Runtime.evaluate', {
247
+ await __classPrivateFieldGet(this, _Page_client, "f").send('Runtime.evaluate', {
248
248
  expression,
249
249
  contextId: event.executionContextId,
250
250
  });
@@ -0,0 +1,9 @@
1
+ import type { CliInput } from './payloads';
2
+ export declare type Compositor = {
3
+ finishCommands: () => void;
4
+ executeCommand: (payload: Omit<CliInput, 'nonce'>) => Promise<void>;
5
+ waitForDone: () => Promise<void>;
6
+ };
7
+ export declare const spawnCompositorOrReuse: (renderId: string) => Compositor;
8
+ export declare const releaseCompositorWithId: (renderId: string) => void;
9
+ export declare const waitForCompositorWithIdToQuit: (renderId: string) => Promise<void>;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.waitForCompositorWithIdToQuit = exports.releaseCompositorWithId = exports.spawnCompositorOrReuse = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const truthy_1 = require("../truthy");
6
+ const get_executable_path_1 = require("./get-executable-path");
7
+ const compositorMap = {};
8
+ const spawnCompositorOrReuse = (renderId) => {
9
+ if (!compositorMap[renderId]) {
10
+ compositorMap[renderId] = startCompositor();
11
+ }
12
+ return compositorMap[renderId];
13
+ };
14
+ exports.spawnCompositorOrReuse = spawnCompositorOrReuse;
15
+ const releaseCompositorWithId = (renderId) => {
16
+ if (compositorMap[renderId]) {
17
+ compositorMap[renderId].finishCommands();
18
+ }
19
+ };
20
+ exports.releaseCompositorWithId = releaseCompositorWithId;
21
+ const waitForCompositorWithIdToQuit = (renderId) => {
22
+ if (!compositorMap[renderId]) {
23
+ throw new TypeError('No compositor with that id');
24
+ }
25
+ return compositorMap[renderId].waitForDone();
26
+ };
27
+ exports.waitForCompositorWithIdToQuit = waitForCompositorWithIdToQuit;
28
+ const startCompositor = () => {
29
+ const bin = (0, get_executable_path_1.getExecutablePath)();
30
+ const child = (0, child_process_1.spawn)(bin);
31
+ const _stderrChunks = [];
32
+ const stdoutChunks = [];
33
+ child.stderr.on('data', (d) => {
34
+ _stderrChunks.push(d);
35
+ });
36
+ child.stdout.on('data', (d) => {
37
+ stdoutChunks.push(d);
38
+ });
39
+ let nonce = 0;
40
+ return {
41
+ waitForDone: () => {
42
+ return new Promise((resolve, reject) => {
43
+ child.on('exit', (code) => {
44
+ console.log({ code });
45
+ if (code === 0) {
46
+ resolve();
47
+ }
48
+ else {
49
+ reject(Buffer.concat(_stderrChunks).toString('utf-8'));
50
+ }
51
+ });
52
+ });
53
+ },
54
+ finishCommands: () => {
55
+ child.stdin.write('EOF\n');
56
+ },
57
+ executeCommand: (payload) => {
58
+ const actualPayload = {
59
+ ...payload,
60
+ nonce,
61
+ };
62
+ nonce++;
63
+ return new Promise((resolve, reject) => {
64
+ child.stdin.write(JSON.stringify(actualPayload) + '\n');
65
+ const stderrChunks = [];
66
+ const onStderr = (d) => {
67
+ stderrChunks.push(d);
68
+ const message = Buffer.concat(stderrChunks).toString('utf-8');
69
+ let parsed = null;
70
+ try {
71
+ const content = JSON.parse(message);
72
+ if (content.msg_type === 'error') {
73
+ parsed = content;
74
+ }
75
+ }
76
+ catch (error) {
77
+ // TODO: Obviously bad, does not handle panics
78
+ console.log('Rust debug err:', message);
79
+ }
80
+ if (parsed) {
81
+ const err = new Error(parsed.error);
82
+ err.stack = parsed.error + '\n' + parsed.backtrace;
83
+ reject(err);
84
+ child.stderr.off('data', onStderr);
85
+ child.stdout.off('data', onStdout);
86
+ }
87
+ };
88
+ const onStdout = (d) => {
89
+ const str = d.toString('utf-8');
90
+ const lineSplit = str.split('\n');
91
+ for (const line of lineSplit.filter(truthy_1.truthy)) {
92
+ let parsed = null;
93
+ try {
94
+ const p = JSON.parse(line);
95
+ if (p.msg_type === 'finish') {
96
+ parsed = p;
97
+ }
98
+ }
99
+ catch (e) { }
100
+ if (parsed && parsed.nonce === actualPayload.nonce) {
101
+ resolve();
102
+ child.stderr.off('data', onStderr);
103
+ child.stdout.off('data', onStdout);
104
+ }
105
+ }
106
+ };
107
+ child.stderr.on('data', onStderr);
108
+ child.stdout.on('data', onStdout);
109
+ });
110
+ },
111
+ };
112
+ };
@@ -0,0 +1,2 @@
1
+ import type { SpecialVCodecForTransparency } from './assets/download-map';
2
+ export declare const determineVcodecFfmpegFlags: (vcodecFlag: SpecialVCodecForTransparency) => string[];
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.determineVcodecFfmpegFlags = void 0;
4
+ const truthy_1 = require("./truthy");
5
+ const determineVcodecFfmpegFlags = (vcodecFlag) => {
6
+ return [
7
+ vcodecFlag === 'vp9' ? '-vcodec' : null,
8
+ vcodecFlag === 'vp9' ? 'libvpx-vp9' : null,
9
+ vcodecFlag === 'vp8' ? '-vcodec' : null,
10
+ vcodecFlag === 'vp8' ? 'libvpx' : null,
11
+ ].filter(truthy_1.truthy);
12
+ };
13
+ exports.determineVcodecFfmpegFlags = determineVcodecFfmpegFlags;
@@ -7,7 +7,7 @@ exports.extractFrameFromVideo = exports.getLastFrameOfVideo = void 0;
7
7
  const execa_1 = __importDefault(require("execa"));
8
8
  const get_video_stream_duration_1 = require("./assets/get-video-stream-duration");
9
9
  const determine_resize_params_1 = require("./determine-resize-params");
10
- const determine_vcodec_ffmepg_flags_1 = require("./determine-vcodec-ffmepg-flags");
10
+ const determine_vcodec_ffmpeg_flags_1 = require("./determine-vcodec-ffmpeg-flags");
11
11
  const ensure_presentation_timestamp_1 = require("./ensure-presentation-timestamp");
12
12
  const ffmpeg_flags_1 = require("./ffmpeg-flags");
13
13
  const frame_to_ffmpeg_timestamp_1 = require("./frame-to-ffmpeg-timestamp");
@@ -124,7 +124,7 @@ const extractFrameFromVideoFn = async ({ time, ffmpegExecutable, ffprobeExecutab
124
124
  const { stdout, stderr } = (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffmpegExecutable, remotionRoot, 'ffmpeg'), [
125
125
  '-ss',
126
126
  ffmpegTimestamp,
127
- ...(0, determine_vcodec_ffmepg_flags_1.determineVcodecFfmepgFlags)(specialVcodec),
127
+ ...(0, determine_vcodec_ffmpeg_flags_1.determineVcodecFfmpegFlags)(specialVcodec),
128
128
  '-i',
129
129
  src,
130
130
  '-frames:v',
@@ -0,0 +1,7 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { TCompMetadata } from 'remotion';
3
+ import type { GetCompositionsConfig } from './get-compositions';
4
+ export declare const getCompositionsFromBundle: (bundle: string, options: GetCompositionsConfig) => {
5
+ compositions: TCompMetadata[];
6
+ root: ComponentType;
7
+ };
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getCompositionsFromBundle = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const remotion_1 = require("remotion");
10
+ const vm_1 = __importDefault(require("vm"));
11
+ const is_serve_url_1 = require("./is-serve-url");
12
+ const getCompositionsFromBundle = (bundle, options) => {
13
+ const bundleFile = path_1.default.join(bundle, 'bundle.js');
14
+ if ((0, is_serve_url_1.isServeUrl)(bundle)) {
15
+ throw new Error('Can only use getCompositionFromBundle from a local file');
16
+ }
17
+ const content = fs_1.default.readFileSync(bundleFile, 'utf-8');
18
+ // @ts-éxpect-error
19
+ process.env.REMOTION_SERVER_RENDERING = 'true';
20
+ const context = {
21
+ window: {
22
+ remotion_envVariables: options.envVariables,
23
+ },
24
+ clearTimeout: () => {
25
+ console.trace('clearTimeout() called inside a server-side bundle. This is not supported.');
26
+ },
27
+ setTimeout: () => {
28
+ console.trace('setTimeout() called inside a server-side bundle. This is not supported.');
29
+ },
30
+ process: {
31
+ env: {
32
+ REMOTION_SERVER_RENDERING: true,
33
+ },
34
+ },
35
+ require,
36
+ Buffer,
37
+ console,
38
+ };
39
+ const vmContext = vm_1.default.createContext(context);
40
+ // TODO: Set props and env
41
+ const code = content;
42
+ vm_1.default.runInContext(code, vmContext, {
43
+ filename: bundleFile,
44
+ breakOnSigint: true,
45
+ });
46
+ const theRoot = remotion_1.Internals.getRoot();
47
+ if (!theRoot) {
48
+ throw new Error('Did not call getRoot() in the bundle. Delaying the calling of getRoot() is not supported in server-side-rendering.');
49
+ }
50
+ const Comp = theRoot;
51
+ const comps = (0, remotion_1.getCompositionsFromMarkup)(Comp);
52
+ remotion_1.Internals.clearRoot();
53
+ return { compositions: comps, root: Comp };
54
+ };
55
+ exports.getCompositionsFromBundle = getCompositionsFromBundle;
@@ -0,0 +1,3 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { TCompMetadata } from 'remotion';
3
+ export declare const getCompositionsFromMarkup: (Comp: ComponentType) => TCompMetadata[];
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCompositionsFromMarkup = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const server_1 = require("react-dom/server");
6
+ const getCompositionsFromMarkup = (Comp) => {
7
+ process.env.REMOTION_SERVER_RENDERING = 'true';
8
+ const str = (0, server_1.renderToString)((0, jsx_runtime_1.jsx)(Comp, {}));
9
+ console.log({ str }, (0, jsx_runtime_1.jsx)(Comp, {}));
10
+ const matches = str.matchAll(/<div>(.*?)<\/div>/g);
11
+ const metadata = [];
12
+ for (const match of matches) {
13
+ const json = JSON.parse(match[1]);
14
+ metadata.push(json);
15
+ }
16
+ return metadata;
17
+ };
18
+ exports.getCompositionsFromMarkup = getCompositionsFromMarkup;
@@ -89,13 +89,20 @@ const getCompositions = async (serveUrlOrWebpackUrl, config) => {
89
89
  close = closeServer;
90
90
  return innerGetCompositions(serveUrl, page, config !== null && config !== void 0 ? config : {}, offthreadPort);
91
91
  })
92
- .then((comp) => resolve(comp))
92
+ .then((comp) => {
93
+ if (close) {
94
+ return Promise.all([comp, close(true)]);
95
+ }
96
+ return Promise.resolve([comp, null]);
97
+ })
98
+ .then(([comp]) => {
99
+ return resolve(comp);
100
+ })
93
101
  .catch((err) => {
94
102
  reject(err);
95
103
  })
96
104
  .finally(() => {
97
105
  cleanup();
98
- close === null || close === void 0 ? void 0 : close();
99
106
  cleanupPageError();
100
107
  // Clean download map if it was not passed in
101
108
  if (!(config === null || config === void 0 ? void 0 : config.downloadMap)) {
@@ -1 +1 @@
1
- export declare const getActualConcurrency: (userPreference: number | null) => number;
1
+ export declare const getActualConcurrency: (userPreference: number | string | null) => number;
@@ -9,9 +9,16 @@ const getActualConcurrency = (userPreference) => {
9
9
  if (userPreference === null) {
10
10
  return Math.round(Math.min(8, Math.max(1, os_1.default.cpus().length / 2)));
11
11
  }
12
- const rounded = Math.floor(userPreference);
13
12
  const max = os_1.default.cpus().length;
14
13
  const min = 1;
14
+ let rounded;
15
+ if (typeof userPreference === 'string') {
16
+ const percentage = parseInt(userPreference.slice(0, -1), 10);
17
+ rounded = Math.floor((percentage / 100) * max);
18
+ }
19
+ else {
20
+ rounded = Math.floor(userPreference);
21
+ }
15
22
  if (rounded > max) {
16
23
  throw new Error(`Maximum for --concurrency is ${max} (number of cores on this system)`);
17
24
  }
@@ -1,11 +1,15 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.getExtensionOfFilename = void 0;
7
+ const path_1 = __importDefault(require("path"));
4
8
  const getExtensionOfFilename = (filename) => {
5
9
  if (filename === null) {
6
10
  return null;
7
11
  }
8
- const filenameArr = filename.split('.');
12
+ const filenameArr = path_1.default.normalize(filename).split('.');
9
13
  const hasExtension = filenameArr.length >= 2;
10
14
  const filenameArrLength = filenameArr.length;
11
15
  const extension = hasExtension ? filenameArr[filenameArrLength - 1] : null;
@@ -8,7 +8,7 @@ exports.getFrameOfVideoSlow = void 0;
8
8
  // if the video is corrupted
9
9
  const execa_1 = __importDefault(require("execa"));
10
10
  const determine_resize_params_1 = require("./determine-resize-params");
11
- const determine_vcodec_ffmepg_flags_1 = require("./determine-vcodec-ffmepg-flags");
11
+ const determine_vcodec_ffmpeg_flags_1 = require("./determine-vcodec-ffmpeg-flags");
12
12
  const ffmpeg_flags_1 = require("./ffmpeg-flags");
13
13
  const truthy_1 = require("./truthy");
14
14
  const getFrameOfVideoSlow = async ({ src, duration, ffmpegExecutable, imageFormat, specialVCodecForTransparency, needsResize, offset, fps, remotionRoot, }) => {
@@ -17,7 +17,7 @@ const getFrameOfVideoSlow = async ({ src, duration, ffmpegExecutable, imageForma
17
17
  const command = [
18
18
  '-itsoffset',
19
19
  actualOffset,
20
- ...(0, determine_vcodec_ffmepg_flags_1.determineVcodecFfmepgFlags)(specialVCodecForTransparency),
20
+ ...(0, determine_vcodec_ffmpeg_flags_1.determineVcodecFfmpegFlags)(specialVCodecForTransparency),
21
21
  '-i',
22
22
  src,
23
23
  '-frames:v',
package/dist/index.d.ts CHANGED
@@ -41,7 +41,7 @@ export declare const RenderInternals: {
41
41
  feature: "enable-gpl" | "enable-libx265" | "enable-libvpx";
42
42
  remotionRoot: string;
43
43
  }) => Promise<boolean>;
44
- getActualConcurrency: (userPreference: number | null) => number;
44
+ getActualConcurrency: (userPreference: string | number | null) => number;
45
45
  validateFfmpeg: (customFfmpegBinary: string | null, remotionRoot: string, binary: "ffmpeg" | "ffprobe") => Promise<void>;
46
46
  serveStatic: (path: string | null, options: {
47
47
  port: number | null;
@@ -4,4 +4,11 @@ export declare const makeCancelSignal: () => {
4
4
  cancelSignal: CancelSignal;
5
5
  cancel: () => void;
6
6
  };
7
+ export declare const cancelErrorMessages: {
8
+ renderMedia: string;
9
+ renderFrames: string;
10
+ renderStill: string;
11
+ stitchFramesToVideo: string;
12
+ };
13
+ export declare const isUserCancelledRender: (err: unknown) => boolean;
7
14
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.makeCancelSignal = void 0;
3
+ exports.isUserCancelledRender = exports.cancelErrorMessages = exports.makeCancelSignal = void 0;
4
4
  const makeCancelSignal = () => {
5
5
  const callbacks = [];
6
6
  let cancelled = false;
@@ -23,3 +23,22 @@ const makeCancelSignal = () => {
23
23
  };
24
24
  };
25
25
  exports.makeCancelSignal = makeCancelSignal;
26
+ exports.cancelErrorMessages = {
27
+ renderMedia: 'renderMedia() got cancelled',
28
+ renderFrames: 'renderFrames() got cancelled',
29
+ renderStill: 'renderStill() got cancelled',
30
+ stitchFramesToVideo: 'stitchFramesToVideo() got cancelled',
31
+ };
32
+ const isUserCancelledRender = (err) => {
33
+ if (typeof err === 'object' &&
34
+ err !== null &&
35
+ 'message' in err &&
36
+ typeof err.message === 'string') {
37
+ return (err.message.includes(exports.cancelErrorMessages.renderMedia) ||
38
+ err.message.includes(exports.cancelErrorMessages.renderFrames) ||
39
+ err.message.includes(exports.cancelErrorMessages.renderStill) ||
40
+ err.message.includes(exports.cancelErrorMessages.stitchFramesToVideo));
41
+ }
42
+ return false;
43
+ };
44
+ exports.isUserCancelledRender = isUserCancelledRender;
@@ -0,0 +1,2 @@
1
+ import type { CompositionManagerContext, TCompMetadata } from 'remotion';
2
+ export declare const makeCompManagerContext: (composition: TCompMetadata) => CompositionManagerContext;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeCompManagerContext = void 0;
4
+ const makeCompManagerContext = (composition) => {
5
+ const memo = {
6
+ assets: [],
7
+ compositions: [composition],
8
+ currentComposition: composition.id,
9
+ currentCompositionMetadata: composition,
10
+ folders: [],
11
+ registerAsset: () => {
12
+ throw new Error('Not implemented');
13
+ },
14
+ registerComposition: () => {
15
+ throw new Error('Not implemented');
16
+ },
17
+ registerFolder: () => {
18
+ throw new Error('Not implemented');
19
+ },
20
+ setCurrentComposition: () => {
21
+ throw new Error('Not implemented');
22
+ },
23
+ registerSequence() {
24
+ throw new Error('Not implemented');
25
+ },
26
+ sequences: [],
27
+ setCurrentCompositionMetadata: () => {
28
+ throw new Error('Not implemented');
29
+ },
30
+ unregisterAsset: () => {
31
+ throw new Error('Not implemented');
32
+ },
33
+ unregisterComposition: () => {
34
+ throw new Error('Not implemented');
35
+ },
36
+ unregisterFolder: () => {
37
+ throw new Error('Not implemented');
38
+ },
39
+ unregisterSequence: () => {
40
+ throw new Error('Not implemented');
41
+ },
42
+ };
43
+ return memo;
44
+ };
45
+ exports.makeCompManagerContext = makeCompManagerContext;
@@ -12,6 +12,6 @@ export declare const prepareServer: ({ ffmpegExecutable, ffprobeExecutable, onDo
12
12
  remotionRoot: string;
13
13
  }) => Promise<{
14
14
  serveUrl: string;
15
- closeServer: () => Promise<unknown>;
15
+ closeServer: (force: boolean) => Promise<unknown>;
16
16
  offthreadPort: number;
17
17
  }>;
@@ -44,8 +44,11 @@ const prepareServer = async ({ ffmpegExecutable, ffprobeExecutable, onDownload,
44
44
  remotionRoot,
45
45
  });
46
46
  return Promise.resolve({
47
- closeServer: () => {
48
- return (0, wait_for_symbolication_error_to_be_done_1.waitForSymbolicationToBeDone)().then(() => close());
47
+ closeServer: async (force) => {
48
+ if (!force) {
49
+ await (0, wait_for_symbolication_error_to_be_done_1.waitForSymbolicationToBeDone)();
50
+ }
51
+ return close();
49
52
  },
50
53
  serveUrl: `http://localhost:${serverPort}`,
51
54
  offthreadPort: serverPort,
@@ -10,4 +10,4 @@ export declare const screenshot: (options: {
10
10
  width: number;
11
11
  height: number;
12
12
  clipRegion: ClipRegion | null;
13
- }) => Promise<Buffer | string | void>;
13
+ }) => Promise<Buffer | string>;
@@ -21,7 +21,7 @@ declare type ConfigOrComposition = {
21
21
  composition: SmallTCompMetadata;
22
22
  };
23
23
  declare type ConcurrencyOrParallelism = {
24
- concurrency?: number | null;
24
+ concurrency?: number | string | null;
25
25
  } | {
26
26
  /**
27
27
  * @deprecated This field has been renamed to `concurrency`
@@ -21,6 +21,7 @@ const get_frame_padded_index_1 = require("./get-frame-padded-index");
21
21
  const get_frame_to_render_1 = require("./get-frame-to-render");
22
22
  const image_format_1 = require("./image-format");
23
23
  const legacy_webpack_config_1 = require("./legacy-webpack-config");
24
+ const make_cancel_signal_1 = require("./make-cancel-signal");
24
25
  const open_browser_1 = require("./open-browser");
25
26
  const perf_1 = require("./perf");
26
27
  const pool_1 = require("./pool");
@@ -241,6 +242,9 @@ const innerRenderFrames = ({ onFrameUpdate, outputDir, onStart, inputProps, qual
241
242
  !((_b = err === null || err === void 0 ? void 0 : err.message) === null || _b === void 0 ? void 0 : _b.includes('Session closed'))) {
242
243
  throw err;
243
244
  }
245
+ if ((0, make_cancel_signal_1.isUserCancelledRender)(err)) {
246
+ throw err;
247
+ }
244
248
  if (retriesLeft === 0) {
245
249
  console.warn(err, `The browser crashed ${attempt} times while rendering frame ${frame}. Not retrying anymore. Learn more about this error under https://www.remotion.dev/docs/target-closed`);
246
250
  throw err;
@@ -320,7 +324,7 @@ const renderFrames = (options) => {
320
324
  new Promise((_, rej) => {
321
325
  var _a;
322
326
  (_a = options.cancelSignal) === null || _a === void 0 ? void 0 : _a.call(options, () => {
323
- rej(new Error('renderFrames() got cancelled'));
327
+ rej(new Error(make_cancel_signal_1.cancelErrorMessages.renderFrames));
324
328
  });
325
329
  }),
326
330
  Promise.all([
@@ -339,7 +343,7 @@ const renderFrames = (options) => {
339
343
  const browserReplacer = (0, replace_browser_1.handleBrowserCrash)(puppeteerInstance);
340
344
  const { stopCycling } = (0, cycle_browser_tabs_1.cycleBrowserTabs)(browserReplacer, actualConcurrency);
341
345
  cleanup.push(stopCycling);
342
- cleanup.push(closeServer);
346
+ cleanup.push(() => closeServer(false));
343
347
  return innerRenderFrames({
344
348
  ...options,
345
349
  puppeteerInstance,
@@ -72,7 +72,7 @@ export declare type RenderMediaOptions = {
72
72
  disallowParallelEncoding?: boolean;
73
73
  } & ServeUrlOrWebpackBundle & ConcurrencyOrParallelism;
74
74
  declare type ConcurrencyOrParallelism = {
75
- concurrency?: number | null;
75
+ concurrency?: number | string | null;
76
76
  } | {
77
77
  /**
78
78
  * @deprecated This field has been renamed to `concurrency`
@@ -362,7 +362,7 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
362
362
  happyPath,
363
363
  new Promise((_resolve, reject) => {
364
364
  cancelSignal === null || cancelSignal === void 0 ? void 0 : cancelSignal(() => {
365
- reject(new Error('renderMedia() got cancelled'));
365
+ reject(new Error(make_cancel_signal_1.cancelErrorMessages.renderMedia));
366
366
  });
367
367
  }),
368
368
  ]);
@@ -0,0 +1,3 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { TCompMetadata } from 'remotion';
3
+ export declare const renderOnServer: (Comp: ComponentType, composition: TCompMetadata) => Promise<void>;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.renderOnServer = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const execa_1 = __importDefault(require("execa"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const server_1 = require("react-dom/server");
11
+ const remotion_1 = require("remotion");
12
+ const download_map_1 = require("./assets/download-map");
13
+ const compose_1 = require("./compositor/compose");
14
+ const compositor_1 = require("./compositor/compositor");
15
+ const get_frame_padded_index_1 = require("./get-frame-padded-index");
16
+ const make_comp_manager_context_1 = require("./make-comp-manager-context");
17
+ const pool_1 = require("./pool");
18
+ const renderOnServer = async (Comp, composition) => {
19
+ console.time('total');
20
+ console.time('frames');
21
+ process.env.REMOTION_SERVER_RENDERING = 'true';
22
+ // eslint-disable-next-line react/jsx-no-constructed-context-values
23
+ const memo = (0, make_comp_manager_context_1.makeCompManagerContext)(composition);
24
+ const pool = new pool_1.Pool(new Array(4).fill(true).map((_, i) => i));
25
+ const downloadMap = (0, download_map_1.makeDownloadMap)();
26
+ const renderId = 'abc';
27
+ await Promise.all(new Array(composition.durationInFrames).fill(true).map(async (_, i) => {
28
+ const frame = await pool.acquire();
29
+ // eslint-disable-next-line react/jsx-no-constructed-context-values
30
+ const value = {
31
+ audioAndVideoTags: { current: [] },
32
+ rootId: composition.id,
33
+ playing: false,
34
+ playbackRate: 1,
35
+ imperativePlaying: {
36
+ current: false,
37
+ },
38
+ frame: i,
39
+ setPlaybackRate: () => {
40
+ throw new Error('Not implemented');
41
+ },
42
+ };
43
+ const svg = (0, server_1.renderToStaticMarkup)((0, jsx_runtime_1.jsx)(remotion_1.Internals.SelectCompositionMode, { layer: 0, id: composition.id, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.Timeline.TimelineContext.Provider, { value: value, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.CompositionManager.Provider, { value: memo, children: (0, jsx_runtime_1.jsx)(Comp, {}) }) }) }));
44
+ const out = path_1.default.join(downloadMap.compositingDir, (0, get_frame_padded_index_1.getFrameOutputFileName)({
45
+ frame: i,
46
+ imageFormat: 'tiff',
47
+ index: i,
48
+ countType: 'from-zero',
49
+ lastFrame: composition.durationInFrames - 1,
50
+ totalFrames: composition.durationInFrames,
51
+ }));
52
+ await (0, compose_1.compose)({
53
+ height: composition.height,
54
+ width: composition.width,
55
+ downloadMap,
56
+ imageFormat: 'AddToH264',
57
+ layers: [
58
+ {
59
+ type: 'SvgImage',
60
+ params: {
61
+ height: composition.height,
62
+ width: composition.width,
63
+ markup: svg,
64
+ x: 0,
65
+ y: 0,
66
+ },
67
+ },
68
+ ],
69
+ output: out,
70
+ renderId,
71
+ });
72
+ pool.release(frame);
73
+ }));
74
+ (0, compositor_1.releaseCompositorWithId)(renderId);
75
+ console.timeEnd('frames');
76
+ await (0, compositor_1.waitForCompositorWithIdToQuit)(renderId);
77
+ console.time('convert');
78
+ await (0, execa_1.default)('ffmpeg', ['-i', 'fade.h264', '-c', 'copy', 'fade.mp4', '-y']);
79
+ console.timeEnd('convert');
80
+ console.timeEnd('total');
81
+ };
82
+ exports.renderOnServer = renderOnServer;
@@ -38,6 +38,7 @@ const handle_javascript_exception_1 = require("./error-handling/handle-javascrip
38
38
  const find_closest_package_json_1 = require("./find-closest-package-json");
39
39
  const image_format_1 = require("./image-format");
40
40
  const legacy_webpack_config_1 = require("./legacy-webpack-config");
41
+ const make_cancel_signal_1 = require("./make-cancel-signal");
41
42
  const open_browser_1 = require("./open-browser");
42
43
  const prepare_server_1 = require("./prepare-server");
43
44
  const puppeteer_evaluate_1 = require("./puppeteer-evaluate");
@@ -207,7 +208,7 @@ const renderStill = (options) => {
207
208
  if (!(options === null || options === void 0 ? void 0 : options.downloadMap)) {
208
209
  (0, download_map_1.cleanDownloadMap)(downloadMap);
209
210
  }
210
- return close === null || close === void 0 ? void 0 : close();
211
+ return close === null || close === void 0 ? void 0 : close(false);
211
212
  });
212
213
  });
213
214
  return Promise.race([
@@ -215,7 +216,7 @@ const renderStill = (options) => {
215
216
  new Promise((_resolve, reject) => {
216
217
  var _a;
217
218
  (_a = options.cancelSignal) === null || _a === void 0 ? void 0 : _a.call(options, () => {
218
- reject(new Error('renderStill() got cancelled'));
219
+ reject(new Error(make_cancel_signal_1.cancelErrorMessages.renderStill));
219
220
  });
220
221
  }),
221
222
  ]);
@@ -0,0 +1,8 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { TCompMetadata } from 'remotion';
3
+ export declare const renderSvg: ({ composition, Comp, frame, layer, }: {
4
+ composition: TCompMetadata;
5
+ Comp: ComponentType;
6
+ frame: number;
7
+ layer: number;
8
+ }) => string;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderSvg = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const server_1 = require("react-dom/server");
6
+ const remotion_1 = require("remotion");
7
+ const make_comp_manager_context_1 = require("./make-comp-manager-context");
8
+ const makeTimelineContextValue = (composition, frame) => {
9
+ const value = {
10
+ audioAndVideoTags: { current: [] },
11
+ rootId: composition.id,
12
+ playing: false,
13
+ playbackRate: 1,
14
+ imperativePlaying: {
15
+ current: false,
16
+ },
17
+ frame,
18
+ setPlaybackRate: () => {
19
+ throw new Error('Not implemented');
20
+ },
21
+ };
22
+ return value;
23
+ };
24
+ const renderSvg = ({ composition, Comp, frame, layer, }) => {
25
+ const svg = (0, server_1.renderToStaticMarkup)((0, jsx_runtime_1.jsx)(remotion_1.Internals.SelectCompositionMode, { layer: layer, id: composition.id, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.Timeline.TimelineContext.Provider, { value: makeTimelineContextValue(composition, frame), children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.CompositionManager.Provider, { value: (0, make_comp_manager_context_1.makeCompManagerContext)(composition), children: (0, jsx_runtime_1.jsx)(Comp, {}) }) }) }));
26
+ return svg;
27
+ };
28
+ exports.renderSvg = renderSvg;
@@ -0,0 +1,77 @@
1
+ import type { SmallTCompMetadata, TAsset } from 'remotion';
2
+ import type { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
3
+ import type { DownloadMap } from './assets/download-map';
4
+ import type { BrowserExecutable } from './browser-executable';
5
+ import type { BrowserLog } from './browser-log';
6
+ import type { Page } from './browser/BrowserPage';
7
+ import type { CompositorLayer } from './compositor/payloads';
8
+ import type { CountType } from './get-frame-padded-index';
9
+ import type { ServeUrl } from './legacy-webpack-config';
10
+ import type { ChromiumOptions } from './open-browser';
11
+ import type { Pool } from './pool';
12
+ import type { BrowserReplacer } from './replace-browser';
13
+ export declare const renderWebFrameAndRetryTargetClose: ({ frame, index, retriesLeft, attempt, actualConcurrency, browserReplacer, poolPromise, composition, downloadMap, imageFormat, onFrameBuffer, onFrameUpdate, outputDir, stopState, assets, countType, scale, quality, framesToRender, lastFrame, framesRendered, browserExecutable, chromiumOptions, dumpBrowserLogs, pagesArray, onBrowserLog, inputProps, envVariables, muted, proxyPort, realFrameRange, serveUrl, timeoutInMilliseconds, onDownload, onError, }: {
14
+ frame: number;
15
+ index: number;
16
+ retriesLeft: number;
17
+ attempt: number;
18
+ actualConcurrency: number;
19
+ browserReplacer: BrowserReplacer | null;
20
+ poolPromise: Promise<Pool<Page>>;
21
+ composition: SmallTCompMetadata;
22
+ downloadMap: DownloadMap;
23
+ imageFormat: 'png' | 'jpeg' | 'none';
24
+ onFrameBuffer: ((buffer: Buffer, frame: number) => void) | undefined;
25
+ onFrameUpdate: (framesRendered: number, frameIndex: number, timeToRenderInMilliseconds: number) => void;
26
+ outputDir: string | null;
27
+ stopState: {
28
+ isStopped: boolean;
29
+ };
30
+ assets: TAsset[][];
31
+ countType: CountType;
32
+ scale: number;
33
+ quality: number | undefined;
34
+ framesToRender: number[];
35
+ lastFrame: number;
36
+ framesRendered: {
37
+ frames: number;
38
+ };
39
+ browserExecutable?: BrowserExecutable | undefined;
40
+ chromiumOptions?: ChromiumOptions | undefined;
41
+ dumpBrowserLogs?: boolean | undefined;
42
+ pagesArray: Page[];
43
+ onBrowserLog?: ((log: BrowserLog) => void) | undefined;
44
+ inputProps: unknown;
45
+ envVariables?: Record<string, string> | undefined;
46
+ muted: boolean;
47
+ proxyPort: number;
48
+ realFrameRange: [number, number];
49
+ serveUrl: ServeUrl;
50
+ timeoutInMilliseconds: number;
51
+ onDownload: RenderMediaOnDownload;
52
+ onError: (err: Error) => void;
53
+ }) => Promise<{
54
+ layer: CompositorLayer | null;
55
+ buffer: Buffer | null;
56
+ }>;
57
+ export declare const makePage: ({ browserReplacer, pagesArray, composition, scale, onBrowserLog, inputProps, envVariables, serveUrl, realFrameRange, timeoutInMilliseconds, proxyPort, imageFormat, muted, }: {
58
+ browserReplacer: BrowserReplacer;
59
+ pagesArray: Page[];
60
+ composition: SmallTCompMetadata;
61
+ scale?: number | undefined;
62
+ onBrowserLog?: ((log: BrowserLog) => void) | undefined;
63
+ inputProps: unknown;
64
+ envVariables?: Record<string, string> | undefined;
65
+ serveUrl: ServeUrl;
66
+ realFrameRange: [number, number];
67
+ timeoutInMilliseconds: number | undefined;
68
+ proxyPort: number;
69
+ imageFormat: 'png' | 'jpeg' | 'none';
70
+ muted: boolean;
71
+ }) => Promise<Page>;
72
+ export declare const makeBrowser: ({ dumpBrowserLogs, browserExecutable, chromiumOptions, scale, }: {
73
+ dumpBrowserLogs?: boolean | undefined;
74
+ browserExecutable?: BrowserExecutable | undefined;
75
+ chromiumOptions?: ChromiumOptions | undefined;
76
+ scale?: number | undefined;
77
+ }) => Promise<import("./browser/Browser").Browser>;
@@ -0,0 +1,290 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.makeBrowser = exports.makePage = exports.renderWebFrameAndRetryTargetClose = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const download_and_map_assets_to_file_1 = require("./assets/download-and-map-assets-to-file");
9
+ const browser_1 = require("./browser");
10
+ const compress_assets_1 = require("./compress-assets");
11
+ const handle_javascript_exception_1 = require("./error-handling/handle-javascript-exception");
12
+ const make_cancel_signal_1 = require("./make-cancel-signal");
13
+ const open_browser_1 = require("./open-browser");
14
+ const perf_1 = require("./perf");
15
+ const puppeteer_evaluate_1 = require("./puppeteer-evaluate");
16
+ const seek_to_frame_1 = require("./seek-to-frame");
17
+ const set_props_and_env_1 = require("./set-props-and-env");
18
+ const take_frame_and_compose_1 = require("./take-frame-and-compose");
19
+ const truthy_1 = require("./truthy");
20
+ const renderFrameWithOptionToReject = async ({ frame, index, reject, width, height, poolPromise, stopState, imageFormat, downloadMap, onFrameUpdate, scale, assets, quality, framesRendered, onDownload, onError, }) => {
21
+ const pool = await poolPromise;
22
+ const freePage = await pool.acquire();
23
+ if (stopState.isStopped) {
24
+ reject(new Error('Render was stopped'));
25
+ throw new Error('stopped');
26
+ }
27
+ const startTime = performance.now();
28
+ const errorCallbackOnFrame = (err) => {
29
+ reject(err);
30
+ };
31
+ const cleanupPageError = (0, handle_javascript_exception_1.handleJavascriptException)({
32
+ page: freePage,
33
+ onError: errorCallbackOnFrame,
34
+ frame,
35
+ });
36
+ freePage.on('error', errorCallbackOnFrame);
37
+ await (0, seek_to_frame_1.seekToFrame)({ frame, page: freePage });
38
+ const id = (0, perf_1.startPerfMeasure)('save');
39
+ const output = path_1.default.join(downloadMap.compositingDir, `preframe-${index}.${imageFormat}`);
40
+ const { buffer, collectedAssets, clipRegion } = await (0, take_frame_and_compose_1.takeFrame)({
41
+ frame,
42
+ freePage,
43
+ height,
44
+ imageFormat,
45
+ quality,
46
+ width,
47
+ });
48
+ const needsComposing = clipRegion === null
49
+ ? null
50
+ : {
51
+ tmpFile: path_1.default.join(downloadMap.compositingDir, `${frame}.${imageFormat}`),
52
+ finalOutfie: output !== null && output !== void 0 ? output : path_1.default.join(downloadMap.compositingDir, `${frame}-final.${imageFormat}`),
53
+ clipRegion: clipRegion,
54
+ };
55
+ const compositionLayer = !needsComposing || needsComposing.clipRegion === 'hide'
56
+ ? null
57
+ : {
58
+ type: imageFormat === 'jpeg'
59
+ ? 'JpgImage'
60
+ : 'PngImage',
61
+ params: {
62
+ height: needsComposing.clipRegion.height * scale,
63
+ width: needsComposing.clipRegion.width * scale,
64
+ src: needsComposing.tmpFile,
65
+ x: needsComposing.clipRegion.x * scale,
66
+ y: needsComposing.clipRegion.y * scale,
67
+ },
68
+ };
69
+ // TODO: Always return buffer
70
+ (0, perf_1.stopPerfMeasure)(id);
71
+ const compressedAssets = collectedAssets.map((asset) => (0, compress_assets_1.compressAsset)(assets.filter(truthy_1.truthy).flat(1), asset));
72
+ assets[index] = compressedAssets;
73
+ compressedAssets.forEach((asset) => {
74
+ (0, download_and_map_assets_to_file_1.downloadAndMapAssetsToFileUrl)({
75
+ asset,
76
+ onDownload,
77
+ downloadMap,
78
+ }).catch((err) => {
79
+ onError(new Error(`Error while downloading asset: ${err.stack}`));
80
+ });
81
+ });
82
+ framesRendered.frames++;
83
+ onFrameUpdate(framesRendered.frames, frame, performance.now() - startTime);
84
+ cleanupPageError();
85
+ freePage.off('error', errorCallbackOnFrame);
86
+ pool.release(freePage);
87
+ return { layer: compositionLayer, buffer };
88
+ };
89
+ const renderWebFrame = ({ frame, index, downloadMap, imageFormat, onFrameUpdate, poolPromise, stopState, composition, assets, scale, quality, framesRendered, onDownload, onError, }) => {
90
+ return new Promise((resolve, reject) => {
91
+ renderFrameWithOptionToReject({
92
+ frame,
93
+ index,
94
+ reject,
95
+ width: composition.width,
96
+ height: composition.height,
97
+ downloadMap,
98
+ imageFormat,
99
+ onFrameUpdate,
100
+ poolPromise,
101
+ stopState,
102
+ assets,
103
+ scale,
104
+ quality,
105
+ framesRendered,
106
+ onDownload,
107
+ onError,
108
+ })
109
+ .then((res) => {
110
+ resolve(res);
111
+ })
112
+ .catch((err) => {
113
+ reject(err);
114
+ });
115
+ });
116
+ };
117
+ const renderWebFrameAndRetryTargetClose = async ({ frame, index, retriesLeft, attempt, actualConcurrency, browserReplacer, poolPromise, composition, downloadMap, imageFormat, onFrameBuffer, onFrameUpdate, outputDir, stopState, assets, countType, scale, quality, framesToRender, lastFrame, framesRendered, browserExecutable, chromiumOptions, dumpBrowserLogs, pagesArray, onBrowserLog, inputProps, envVariables, muted, proxyPort, realFrameRange, serveUrl, timeoutInMilliseconds, onDownload, onError, }) => {
118
+ var _a, _b;
119
+ try {
120
+ const returnval = await renderWebFrame({
121
+ frame,
122
+ index,
123
+ poolPromise,
124
+ composition,
125
+ downloadMap,
126
+ imageFormat,
127
+ onFrameUpdate,
128
+ stopState,
129
+ assets,
130
+ scale,
131
+ quality,
132
+ framesRendered,
133
+ onDownload,
134
+ onError,
135
+ });
136
+ return returnval;
137
+ }
138
+ catch (err) {
139
+ if (!((_a = err === null || err === void 0 ? void 0 : err.message) === null || _a === void 0 ? void 0 : _a.includes('Target closed')) &&
140
+ !((_b = err === null || err === void 0 ? void 0 : err.message) === null || _b === void 0 ? void 0 : _b.includes('Session closed'))) {
141
+ throw err;
142
+ }
143
+ if ((0, make_cancel_signal_1.isUserCancelledRender)(err)) {
144
+ throw err;
145
+ }
146
+ if (retriesLeft === 0) {
147
+ console.warn(err, `The browser crashed ${attempt} times while rendering frame ${frame}. Not retrying anymore. Learn more about this error under https://www.remotion.dev/docs/target-closed`);
148
+ throw err;
149
+ }
150
+ console.warn(`The browser crashed while rendering frame ${frame}, retrying ${retriesLeft} more times. Learn more about this error under https://www.remotion.dev/docs/target-closed`);
151
+ if (!browserReplacer) {
152
+ throw new Error('Did not have browser replacer for web frame');
153
+ }
154
+ await browserReplacer.replaceBrowser(() => (0, exports.makeBrowser)({
155
+ browserExecutable,
156
+ chromiumOptions,
157
+ dumpBrowserLogs,
158
+ scale,
159
+ }), async () => {
160
+ const pages = new Array(actualConcurrency).fill(true).map(() => (0, exports.makePage)({
161
+ browserReplacer,
162
+ composition,
163
+ pagesArray,
164
+ onBrowserLog,
165
+ scale,
166
+ inputProps,
167
+ envVariables,
168
+ imageFormat,
169
+ muted,
170
+ proxyPort,
171
+ realFrameRange,
172
+ serveUrl,
173
+ timeoutInMilliseconds,
174
+ }));
175
+ const puppeteerPages = await Promise.all(pages);
176
+ const pool = await poolPromise;
177
+ for (const newPage of puppeteerPages) {
178
+ pool.release(newPage);
179
+ }
180
+ });
181
+ const fram = await (0, exports.renderWebFrameAndRetryTargetClose)({
182
+ frame,
183
+ index,
184
+ retriesLeft: retriesLeft - 1,
185
+ attempt: attempt + 1,
186
+ actualConcurrency,
187
+ browserReplacer,
188
+ composition,
189
+ downloadMap,
190
+ imageFormat,
191
+ onFrameBuffer,
192
+ onFrameUpdate,
193
+ outputDir,
194
+ poolPromise,
195
+ stopState,
196
+ assets,
197
+ countType,
198
+ scale,
199
+ quality,
200
+ framesToRender,
201
+ lastFrame,
202
+ framesRendered,
203
+ inputProps,
204
+ pagesArray,
205
+ browserExecutable,
206
+ chromiumOptions,
207
+ dumpBrowserLogs,
208
+ envVariables,
209
+ muted,
210
+ onBrowserLog,
211
+ proxyPort,
212
+ realFrameRange,
213
+ serveUrl,
214
+ timeoutInMilliseconds,
215
+ onDownload,
216
+ onError,
217
+ });
218
+ return fram;
219
+ }
220
+ };
221
+ exports.renderWebFrameAndRetryTargetClose = renderWebFrameAndRetryTargetClose;
222
+ const makePage = async ({ browserReplacer, pagesArray, composition, scale, onBrowserLog, inputProps, envVariables, serveUrl, realFrameRange, timeoutInMilliseconds, proxyPort, imageFormat, muted, }) => {
223
+ if (!browserReplacer) {
224
+ throw new Error('canonot make page without browser replacer');
225
+ }
226
+ const page = await browserReplacer.getBrowser().newPage();
227
+ pagesArray.push(page);
228
+ await page.setViewport({
229
+ width: composition.width,
230
+ height: composition.height,
231
+ deviceScaleFactor: scale !== null && scale !== void 0 ? scale : 1,
232
+ });
233
+ const logCallback = (log) => {
234
+ onBrowserLog === null || onBrowserLog === void 0 ? void 0 : onBrowserLog({
235
+ stackTrace: log.stackTrace(),
236
+ text: log.text,
237
+ type: log.type,
238
+ });
239
+ };
240
+ if (onBrowserLog) {
241
+ page.on('console', logCallback);
242
+ }
243
+ const initialFrame = realFrameRange[0];
244
+ await (0, set_props_and_env_1.setPropsAndEnv)({
245
+ inputProps,
246
+ envVariables,
247
+ page,
248
+ serveUrl,
249
+ initialFrame,
250
+ timeoutInMilliseconds,
251
+ proxyPort,
252
+ retriesRemaining: 2,
253
+ audioEnabled: !muted,
254
+ videoEnabled: imageFormat !== 'none',
255
+ });
256
+ await (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatch)({
257
+ // eslint-disable-next-line max-params
258
+ pageFunction: (id, defaultProps, durationInFrames, fps, height, width) => {
259
+ window.setBundleMode({
260
+ type: 'composition',
261
+ compositionName: id,
262
+ compositionDefaultProps: defaultProps,
263
+ compositionDurationInFrames: durationInFrames,
264
+ compositionFps: fps,
265
+ compositionHeight: height,
266
+ compositionWidth: width,
267
+ });
268
+ },
269
+ args: [
270
+ composition.id,
271
+ composition.defaultProps,
272
+ composition.durationInFrames,
273
+ composition.fps,
274
+ composition.height,
275
+ composition.width,
276
+ ],
277
+ frame: null,
278
+ page,
279
+ });
280
+ page.off('console', logCallback);
281
+ return page;
282
+ };
283
+ exports.makePage = makePage;
284
+ const makeBrowser = ({ dumpBrowserLogs, browserExecutable, chromiumOptions, scale, }) => (0, open_browser_1.openBrowser)(browser_1.DEFAULT_BROWSER, {
285
+ shouldDumpIo: dumpBrowserLogs,
286
+ browserExecutable,
287
+ chromiumOptions,
288
+ forceDeviceScaleFactor: scale !== null && scale !== void 0 ? scale : 1,
289
+ });
290
+ exports.makeBrowser = makeBrowser;
@@ -28,7 +28,7 @@ const screenshotDOMElement = async ({ page, imageFormat, quality, opts, height,
28
28
  if (imageFormat === 'none') {
29
29
  throw new TypeError('Tried to make a screenshot with format "none"');
30
30
  }
31
- return (0, puppeteer_screenshot_1.screenshot)({
31
+ const buf = await (0, puppeteer_screenshot_1.screenshot)({
32
32
  page,
33
33
  omitBackground: imageFormat === 'png',
34
34
  path: path !== null && path !== void 0 ? path : undefined,
@@ -38,5 +38,9 @@ const screenshotDOMElement = async ({ page, imageFormat, quality, opts, height,
38
38
  height,
39
39
  clipRegion,
40
40
  });
41
+ if (typeof buf === 'string') {
42
+ throw new TypeError('Expected a buffer');
43
+ }
44
+ return buf;
41
45
  };
42
46
  exports.screenshotDOMElement = screenshotDOMElement;
@@ -45,6 +45,7 @@ const get_audio_codec_name_1 = require("./get-audio-codec-name");
45
45
  const get_codec_name_1 = require("./get-codec-name");
46
46
  const get_extension_from_codec_1 = require("./get-extension-from-codec");
47
47
  const get_prores_profile_name_1 = require("./get-prores-profile-name");
48
+ const make_cancel_signal_1 = require("./make-cancel-signal");
48
49
  const merge_audio_track_1 = require("./merge-audio-track");
49
50
  const parse_ffmpeg_progress_1 = require("./parse-ffmpeg-progress");
50
51
  const pixel_format_1 = require("./pixel-format");
@@ -98,11 +99,13 @@ const getAssetsData = async ({ assets, onDownload, fps, expectedFrames, verbose,
98
99
  downloadMap,
99
100
  remotionRoot,
100
101
  });
101
- (0, delete_directory_1.deleteDirectory)(downloadMap.audioMixing);
102
102
  onProgress(1);
103
- preprocessed.forEach((p) => {
104
- (0, delete_directory_1.deleteDirectory)(p);
105
- });
103
+ await Promise.all([
104
+ (0, delete_directory_1.deleteDirectory)(downloadMap.audioMixing),
105
+ ...preprocessed.map((p) => {
106
+ return (0, delete_directory_1.deleteDirectory)(p);
107
+ }),
108
+ ]);
106
109
  return outName;
107
110
  };
108
111
  const spawnFfmpeg = async (options, remotionRoot) => {
@@ -344,7 +347,7 @@ const stitchFramesToVideo = async (options) => {
344
347
  new Promise((_resolve, reject) => {
345
348
  var _a;
346
349
  (_a = options.cancelSignal) === null || _a === void 0 ? void 0 : _a.call(options, () => {
347
- reject(new Error('stitchFramesToVideo() got cancelled'));
350
+ reject(new Error(make_cancel_signal_1.cancelErrorMessages.stitchFramesToVideo));
348
351
  });
349
352
  }),
350
353
  ]);
@@ -6,14 +6,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.tryToExtractFrameOfVideoFast = void 0;
7
7
  const execa_1 = __importDefault(require("execa"));
8
8
  const determine_resize_params_1 = require("./determine-resize-params");
9
- const determine_vcodec_ffmepg_flags_1 = require("./determine-vcodec-ffmepg-flags");
9
+ const determine_vcodec_ffmpeg_flags_1 = require("./determine-vcodec-ffmpeg-flags");
10
10
  const ffmpeg_flags_1 = require("./ffmpeg-flags");
11
11
  const truthy_1 = require("./truthy");
12
12
  const tryToExtractFrameOfVideoFast = async ({ ffmpegExecutable, remotionRoot, specialVCodecForTransparency, imageFormat, needsResize, src, actualOffset, }) => {
13
13
  const { stdout, stderr } = (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffmpegExecutable, remotionRoot, 'ffmpeg'), [
14
14
  '-ss',
15
15
  actualOffset,
16
- ...(0, determine_vcodec_ffmepg_flags_1.determineVcodecFfmepgFlags)(specialVCodecForTransparency),
16
+ ...(0, determine_vcodec_ffmpeg_flags_1.determineVcodecFfmpegFlags)(specialVCodecForTransparency),
17
17
  '-i',
18
18
  src,
19
19
  '-frames:v',
@@ -8,17 +8,22 @@ const validateConcurrency = (value, setting) => {
8
8
  if (value === null) {
9
9
  return;
10
10
  }
11
- if (typeof value !== 'number') {
12
- throw new Error(setting + ' must be a number but is ' + value);
11
+ if (typeof value !== 'number' && typeof value !== 'string') {
12
+ throw new Error(setting + ' must a number or a string but is ' + value);
13
13
  }
14
- if (value % 1 !== 0) {
15
- throw new Error(setting + ' must be an integer, but is ' + value);
14
+ if (typeof value === 'number') {
15
+ if (value % 1 !== 0) {
16
+ throw new Error(setting + ' must be an integer, but is ' + value);
17
+ }
18
+ if (value < 1) {
19
+ throw new Error(setting + ' must be at least 1, but is ' + value);
20
+ }
21
+ if (value > require('os').cpus().length) {
22
+ throw new Error(`${setting} is set higher than the amount of CPU cores available. Available CPU cores: ${require('os').cpus().length}, value set: ${value}`);
23
+ }
16
24
  }
17
- if (value < 1) {
18
- throw new Error(setting + ' must be at least 1, but is ' + value);
19
- }
20
- if (value > require('os').cpus().length) {
21
- throw new Error(`${setting} is set higher than the amount of CPU cores available. Available CPU cores: ${require('os').cpus().length}, value set: ${value}`);
25
+ else if (!/^\d+(\.\d+)?%$/.test(value)) {
26
+ throw new Error(`${setting} must be a number or percentage, but is ${JSON.stringify(value)}`);
22
27
  }
23
28
  };
24
29
  exports.validateConcurrency = validateConcurrency;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/renderer",
3
- "version": "3.3.27",
3
+ "version": "3.3.31",
4
4
  "description": "Renderer for Remotion",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "execa": "5.1.1",
26
26
  "extract-zip": "2.0.1",
27
- "remotion": "3.3.27",
27
+ "remotion": "3.3.31",
28
28
  "source-map": "^0.8.0-beta.0",
29
29
  "ws": "8.7.0"
30
30
  },
@@ -49,13 +49,13 @@
49
49
  "vitest": "0.24.3"
50
50
  },
51
51
  "optionalDependencies": {
52
- "@remotion/compositor-darwin-arm64": "3.3.27",
53
- "@remotion/compositor-darwin-x64": "3.3.27",
54
- "@remotion/compositor-linux-arm64-gnu": "3.3.27",
55
- "@remotion/compositor-linux-arm64-musl": "3.3.27",
56
- "@remotion/compositor-linux-x64-gnu": "3.3.27",
57
- "@remotion/compositor-linux-x64-musl": "3.3.27",
58
- "@remotion/compositor-win32-x64-msvc": "3.3.27"
52
+ "@remotion/compositor-darwin-arm64": "3.3.31",
53
+ "@remotion/compositor-darwin-x64": "3.3.31",
54
+ "@remotion/compositor-linux-arm64-gnu": "3.3.31",
55
+ "@remotion/compositor-linux-arm64-musl": "3.3.31",
56
+ "@remotion/compositor-linux-x64-gnu": "3.3.31",
57
+ "@remotion/compositor-linux-x64-musl": "3.3.31",
58
+ "@remotion/compositor-win32-x64-msvc": "3.3.31"
59
59
  },
60
60
  "keywords": [
61
61
  "remotion",
@@ -67,5 +67,5 @@
67
67
  "publishConfig": {
68
68
  "access": "public"
69
69
  },
70
- "gitHead": "5dfc0dfa0df9592a358127a9aea9219244e6807a"
70
+ "gitHead": "4b89462c98236d59641272bd0649d880514e685f"
71
71
  }
@@ -1,39 +0,0 @@
1
- export declare type Layer = {
2
- type: 'PngImage';
3
- params: {
4
- src: string;
5
- x: number;
6
- y: number;
7
- width: number;
8
- height: number;
9
- };
10
- } | {
11
- type: 'JpgImage';
12
- params: {
13
- src: string;
14
- x: number;
15
- y: number;
16
- width: number;
17
- height: number;
18
- };
19
- } | {
20
- type: 'Solid';
21
- params: {
22
- fill: [number, number, number, number];
23
- x: number;
24
- y: number;
25
- width: number;
26
- height: number;
27
- };
28
- };
29
- export declare type CliInput = {
30
- v: number;
31
- output: string;
32
- width: number;
33
- height: number;
34
- layers: Layer[];
35
- };
36
- export declare type ErrorPayload = {
37
- error: string;
38
- backtrace: string;
39
- };
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });