@remotion/renderer 4.0.0-alpha.217 → 4.0.0-alpha10

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 (126) hide show
  1. package/README.md +5 -37
  2. package/dist/assets/download-and-map-assets-to-file.js +6 -6
  3. package/dist/assets/download-file.d.ts +3 -2
  4. package/dist/assets/download-file.js +18 -3
  5. package/dist/assets/download-map.d.ts +0 -26
  6. package/dist/assets/download-map.js +7 -12
  7. package/dist/assets/get-video-stream-duration.d.ts +5 -2
  8. package/dist/assets/get-video-stream-duration.js +12 -6
  9. package/dist/assets/read-file.d.ts +1 -1
  10. package/dist/assets/read-file.js +2 -2
  11. package/dist/assets/sanitize-filepath.js +2 -2
  12. package/dist/browser/Browser.d.ts +4 -4
  13. package/dist/browser/Browser.js +38 -38
  14. package/dist/browser/BrowserFetcher.d.ts +15 -63
  15. package/dist/browser/BrowserFetcher.js +138 -226
  16. package/dist/browser/BrowserPage.d.ts +4 -4
  17. package/dist/browser/BrowserRunner.d.ts +1 -1
  18. package/dist/browser/BrowserRunner.js +9 -22
  19. package/dist/browser/DOMWorld.d.ts +3 -3
  20. package/dist/browser/LaunchOptions.d.ts +1 -2
  21. package/dist/browser/Launcher.d.ts +3 -3
  22. package/dist/browser/Launcher.js +10 -23
  23. package/dist/browser/NodeWebSocketTransport.js +4 -4
  24. package/dist/browser/PuppeteerNode.d.ts +2 -5
  25. package/dist/browser/PuppeteerNode.js +0 -5
  26. package/dist/browser/Target.d.ts +2 -2
  27. package/dist/browser/create-browser-fetcher.js +34 -48
  28. package/dist/browser/get-download-destination.js +8 -8
  29. package/dist/browser/util.d.ts +2 -2
  30. package/dist/call-ffmpeg.d.ts +4 -7
  31. package/dist/call-ffmpeg.js +24 -16
  32. package/dist/chalk/index.d.ts +54 -0
  33. package/dist/chalk/index.js +135 -0
  34. package/dist/chalk/is-color-supported.d.ts +1 -0
  35. package/dist/chalk/is-color-supported.js +37 -0
  36. package/dist/client.d.ts +1 -0
  37. package/dist/client.js +1 -0
  38. package/dist/codec-supports-media.d.ts +1 -0
  39. package/dist/codec-supports-media.js +20 -5
  40. package/dist/combine-videos.js +6 -6
  41. package/dist/compositor/compose.d.ts +6 -2
  42. package/dist/compositor/compose.js +43 -20
  43. package/dist/compositor/compositor.d.ts +4 -8
  44. package/dist/compositor/compositor.js +67 -53
  45. package/dist/compositor/get-executable-path.js +3 -0
  46. package/dist/compositor/payloads.d.ts +34 -7
  47. package/dist/crf.js +8 -2
  48. package/dist/delete-directory.js +3 -3
  49. package/dist/does-have-m2-bug.js +2 -2
  50. package/dist/ensure-output-directory.js +5 -5
  51. package/dist/ensure-presentation-timestamp.d.ts +9 -2
  52. package/dist/ensure-presentation-timestamp.js +13 -5
  53. package/dist/extract-frame-from-video.d.ts +3 -1
  54. package/dist/extract-frame-from-video.js +29 -7
  55. package/dist/ffmpeg-filter-file.js +7 -7
  56. package/dist/find-closest-package-json.js +6 -6
  57. package/dist/get-browser-instance.d.ts +2 -2
  58. package/dist/get-can-extract-frames-fast.d.ts +4 -1
  59. package/dist/get-can-extract-frames-fast.js +12 -1
  60. package/dist/get-compositions.d.ts +8 -3
  61. package/dist/get-compositions.js +6 -2
  62. package/dist/get-concurrency.js +3 -3
  63. package/dist/get-extension-of-filename.js +2 -2
  64. package/dist/get-frame-of-video-slow.d.ts +8 -3
  65. package/dist/get-frame-of-video-slow.js +11 -3
  66. package/dist/get-local-browser-executable.js +6 -15
  67. package/dist/get-video-info.d.ts +5 -2
  68. package/dist/get-video-info.js +12 -6
  69. package/dist/get-video-threads-flag.js +3 -3
  70. package/dist/index.d.ts +92 -16
  71. package/dist/index.js +15 -6
  72. package/dist/last-frame-from-video-cache.d.ts +4 -1
  73. package/dist/last-frame-from-video-cache.js +1 -0
  74. package/dist/logger.d.ts +22 -0
  75. package/dist/logger.js +61 -0
  76. package/dist/merge-audio-track.js +2 -2
  77. package/dist/mime-types.js +2 -2
  78. package/dist/offthread-video-server.d.ts +12 -6
  79. package/dist/offthread-video-server.js +66 -56
  80. package/dist/open-browser.d.ts +3 -3
  81. package/dist/open-browser.js +1 -1
  82. package/dist/options/jpeg-quality.js +1 -1
  83. package/dist/options/video-codec.js +1 -1
  84. package/dist/prepare-server.d.ts +6 -1
  85. package/dist/prepare-server.js +15 -7
  86. package/dist/prespawn-ffmpeg.d.ts +1 -0
  87. package/dist/prespawn-ffmpeg.js +37 -14
  88. package/dist/prestitcher-memory-usage.js +2 -2
  89. package/dist/puppeteer-evaluate.js +2 -2
  90. package/dist/puppeteer-screenshot.js +1 -1
  91. package/dist/render-frames.d.ts +9 -4
  92. package/dist/render-frames.js +28 -12
  93. package/dist/render-media.d.ts +7 -4
  94. package/dist/render-media.js +49 -26
  95. package/dist/render-still.d.ts +10 -3
  96. package/dist/render-still.js +26 -9
  97. package/dist/replace-browser.d.ts +4 -4
  98. package/dist/resolve-asset-src.js +2 -2
  99. package/dist/screenshot-task.js +2 -2
  100. package/dist/select-composition.d.ts +33 -0
  101. package/dist/select-composition.js +119 -0
  102. package/dist/serve-handler/index.d.ts +1 -1
  103. package/dist/serve-handler/index.js +15 -15
  104. package/dist/serve-handler/is-path-inside.js +3 -3
  105. package/dist/serve-static.d.ts +5 -0
  106. package/dist/serve-static.js +25 -20
  107. package/dist/set-props-and-env.d.ts +5 -3
  108. package/dist/set-props-and-env.js +13 -3
  109. package/dist/stitch-frames-to-video.d.ts +1 -0
  110. package/dist/stitch-frames-to-video.js +76 -53
  111. package/dist/take-frame-and-compose.d.ts +3 -1
  112. package/dist/take-frame-and-compose.js +8 -7
  113. package/dist/tmp-dir.js +7 -7
  114. package/dist/try-to-extract-frame-of-video-fast.d.ts +4 -2
  115. package/dist/try-to-extract-frame-of-video-fast.js +7 -3
  116. package/install-toolchain.mjs +3 -9
  117. package/package.json +70 -71
  118. package/types/ws/index.d.ts +5 -5
  119. package/ffmpeg/SOURCE.md +0 -1
  120. package/ffmpeg/linux-arm-musl.gz +0 -0
  121. package/ffmpeg/linux-arm.gz +0 -0
  122. package/ffmpeg/linux-x64-musl.gz +0 -0
  123. package/ffmpeg/linux-x64.gz +0 -0
  124. package/ffmpeg/macos-arm.gz +0 -0
  125. package/ffmpeg/macos-x64.gz +0 -0
  126. package/ffmpeg/windows.gz +0 -0
@@ -2,8 +2,8 @@
2
2
  // Combine multiple video chunks, useful for decentralized rendering
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.combineVideos = void 0;
5
- const fs_1 = require("fs");
6
- const path_1 = require("path");
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
7
  const audio_codec_1 = require("./audio-codec");
8
8
  const call_ffmpeg_1 = require("./call-ffmpeg");
9
9
  const is_audio_codec_1 = require("./is-audio-codec");
@@ -13,8 +13,8 @@ const combineVideos = async (options) => {
13
13
  var _a;
14
14
  const { files, filelistDir, output, onProgress, numberOfFrames, codec, fps, numberOfGifLoops, audioCodec, } = options;
15
15
  const fileList = files.map((p) => `file '${p}'`).join('\n');
16
- const fileListTxt = (0, path_1.join)(filelistDir, 'files.txt');
17
- (0, fs_1.writeFileSync)(fileListTxt, fileList);
16
+ const fileListTxt = (0, node_path_1.join)(filelistDir, 'files.txt');
17
+ (0, node_fs_1.writeFileSync)(fileListTxt, fileList);
18
18
  const resolvedAudioCodec = audioCodec !== null && audioCodec !== void 0 ? audioCodec : (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless: false });
19
19
  try {
20
20
  const task = (0, call_ffmpeg_1.callFf)('ffmpeg', [
@@ -56,10 +56,10 @@ const combineVideos = async (options) => {
56
56
  });
57
57
  await task;
58
58
  onProgress(numberOfFrames);
59
- (0, fs_1.rmSync)(filelistDir, { recursive: true });
59
+ (0, node_fs_1.rmSync)(filelistDir, { recursive: true });
60
60
  }
61
61
  catch (err) {
62
- (0, fs_1.rmSync)(filelistDir, { recursive: true });
62
+ (0, node_fs_1.rmSync)(filelistDir, { recursive: true });
63
63
  throw err;
64
64
  }
65
65
  };
@@ -1,13 +1,17 @@
1
1
  import type { DownloadMap } from '../assets/download-map';
2
- import type { CompositorImageFormat, Layer } from './payloads';
2
+ import type { Compositor } from './compositor';
3
+ import type { CompositorCommand, CompositorCommandSerialized, CompositorImageFormat, Layer } from './payloads';
3
4
  declare type CompositorInput = {
4
5
  height: number;
5
6
  width: number;
6
7
  layers: Layer[];
7
8
  imageFormat: CompositorImageFormat;
8
9
  };
9
- export declare const compose: ({ height, width, layers, output, downloadMap, imageFormat, }: CompositorInput & {
10
+ export declare const serializeCommand: <Type extends keyof CompositorCommand>(command: Type, params: CompositorCommand[Type]) => CompositorCommandSerialized<Type>;
11
+ export declare const compose: ({ height, width, layers, output, downloadMap, imageFormat, compositor, }: CompositorInput & {
10
12
  downloadMap: DownloadMap;
11
13
  output: string;
14
+ compositor: Compositor;
12
15
  }) => Promise<void>;
16
+ export declare const callCompositor: (payload: string) => Promise<void>;
13
17
  export {};
@@ -1,33 +1,49 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.compose = void 0;
4
- const child_process_1 = require("child_process");
5
- const crypto_1 = require("crypto");
6
- const promises_1 = require("fs/promises");
3
+ exports.callCompositor = exports.compose = exports.serializeCommand = void 0;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const node_crypto_1 = require("node:crypto");
6
+ const node_fs_1 = require("node:fs");
7
+ const promises_1 = require("node:fs/promises");
7
8
  const call_ffmpeg_1 = require("../call-ffmpeg");
8
9
  const get_executable_path_1 = require("./get-executable-path");
10
+ const make_nonce_1 = require("./make-nonce");
9
11
  const getCompositorHash = ({ ...input }) => {
10
- return (0, crypto_1.createHash)('sha256').update(JSON.stringify(input)).digest('base64');
12
+ return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(input)).digest('base64');
11
13
  };
12
- const compose = async ({ height, width, layers, output, downloadMap, imageFormat, }) => {
13
- const bin = (0, get_executable_path_1.getExecutablePath)('compositor');
14
+ const serializeCommand = (command, params) => {
15
+ return {
16
+ nonce: (0, make_nonce_1.makeNonce)(),
17
+ payload: {
18
+ type: command,
19
+ params,
20
+ },
21
+ };
22
+ };
23
+ exports.serializeCommand = serializeCommand;
24
+ const compose = async ({ height, width, layers, output, downloadMap, imageFormat, compositor, }) => {
14
25
  const hash = getCompositorHash({ height, width, layers, imageFormat });
15
26
  if (downloadMap.compositorCache[hash]) {
16
27
  await (0, promises_1.copyFile)(downloadMap.compositorCache[hash], output);
17
28
  return;
18
29
  }
19
- const payload = {
20
- v: 1,
30
+ await compositor.executeCommand('Compose', {
21
31
  height,
22
32
  width,
23
33
  layers,
24
34
  output,
25
35
  output_format: imageFormat,
26
- };
27
- await new Promise((resolve, reject) => {
28
- const child = (0, child_process_1.spawn)(bin, { ...(0, call_ffmpeg_1.callFfExtraOptions)() });
29
- child.stdin.write(JSON.stringify(payload));
30
- child.stdin.end();
36
+ });
37
+ downloadMap.compositorCache[hash] = output;
38
+ };
39
+ exports.compose = compose;
40
+ const callCompositor = (payload) => {
41
+ return new Promise((resolve, reject) => {
42
+ const execPath = (0, get_executable_path_1.getExecutablePath)('compositor');
43
+ if (!process.env.READ_ONLY_FS) {
44
+ (0, node_fs_1.chmodSync)(execPath, 0o755);
45
+ }
46
+ const child = (0, node_child_process_1.spawn)(execPath, [payload], (0, call_ffmpeg_1.dynamicLibraryPathOptions)());
31
47
  const stderrChunks = [];
32
48
  child.stderr.on('data', (d) => stderrChunks.push(d));
33
49
  child.on('close', (code) => {
@@ -36,13 +52,20 @@ const compose = async ({ height, width, layers, output, downloadMap, imageFormat
36
52
  }
37
53
  else {
38
54
  const message = Buffer.concat(stderrChunks).toString('utf-8');
39
- const parsed = JSON.parse(message);
40
- const err = new Error(parsed.error);
41
- err.stack = parsed.error + '\n' + parsed.backtrace;
42
- reject(err);
55
+ try {
56
+ // Try to see if the error is a JSON
57
+ const parsed = JSON.parse(message);
58
+ const msg = `Compositor error: ${parsed.error}`;
59
+ const err = new Error(`${msg}\n${parsed.backtrace}`);
60
+ reject(err);
61
+ }
62
+ catch (err) {
63
+ reject(new Error(`Compositor panicked: ${message}`));
64
+ }
43
65
  }
44
66
  });
67
+ child.stdin.write(payload);
68
+ child.stdin.end();
45
69
  });
46
- downloadMap.compositorCache[hash] = output;
47
70
  };
48
- exports.compose = compose;
71
+ exports.callCompositor = callCompositor;
@@ -4,12 +4,8 @@ export declare type Compositor = {
4
4
  finishCommands: () => void;
5
5
  executeCommand: <T extends keyof CompositorCommand>(type: T, payload: CompositorCommand[T]) => Promise<Buffer>;
6
6
  waitForDone: () => Promise<void>;
7
+ pid: number | null;
7
8
  };
8
- export declare const spawnCompositorOrReuse: <T extends keyof CompositorCommand>({ initiatePayload, renderId, type, }: {
9
- type: T;
10
- initiatePayload: CompositorCommand[T];
11
- renderId: string;
12
- }) => Compositor;
13
- export declare const releaseCompositorWithId: (renderId: string) => void;
14
- export declare const waitForCompositorWithIdToQuit: (renderId: string) => Promise<void>;
15
- export declare const startCompositor: <T extends keyof CompositorCommand>(type: T, payload: CompositorCommand[T]) => Compositor;
9
+ export declare const getIdealMaximumFrameCacheItems: () => number;
10
+ export declare const startLongRunningCompositor: (maximumFrameCacheItems: number, verbose: boolean, indent: boolean) => Compositor;
11
+ export declare const startCompositor: <T extends keyof CompositorCommand>(type: T, payload: CompositorCommand[T], indent: boolean) => Compositor;
@@ -1,54 +1,57 @@
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
- exports.startCompositor = exports.waitForCompositorWithIdToQuit = exports.releaseCompositorWithId = exports.spawnCompositorOrReuse = void 0;
4
- const child_process_1 = require("child_process");
6
+ exports.startCompositor = exports.startLongRunningCompositor = exports.getIdealMaximumFrameCacheItems = void 0;
7
+ const node_child_process_1 = require("node:child_process");
8
+ const node_fs_1 = require("node:fs");
9
+ const node_os_1 = __importDefault(require("node:os"));
5
10
  const call_ffmpeg_1 = require("../call-ffmpeg");
11
+ const get_concurrency_1 = require("../get-concurrency");
12
+ const logger_1 = require("../logger");
13
+ const compose_1 = require("./compose");
6
14
  const get_executable_path_1 = require("./get-executable-path");
7
15
  const make_nonce_1 = require("./make-nonce");
8
- const compositorMap = {};
9
- const spawnCompositorOrReuse = ({ initiatePayload, renderId, type, }) => {
10
- if (!compositorMap[renderId]) {
11
- compositorMap[renderId] = (0, exports.startCompositor)(type, initiatePayload);
12
- }
13
- return compositorMap[renderId];
14
- };
15
- exports.spawnCompositorOrReuse = spawnCompositorOrReuse;
16
- const releaseCompositorWithId = (renderId) => {
17
- if (compositorMap[renderId]) {
18
- compositorMap[renderId].finishCommands();
19
- }
16
+ const getIdealMaximumFrameCacheItems = () => {
17
+ const freeMemory = node_os_1.default.freemem();
18
+ // Assuming 1 frame is approximately 6MB
19
+ // Assuming only half the available memory should be used
20
+ const max = Math.floor(freeMemory / (1024 * 1024 * 6));
21
+ // Never store more than 1000 frames
22
+ // But 100 is needed even if it's going to swap
23
+ return Math.max(100, Math.min(max, 1000));
20
24
  };
21
- exports.releaseCompositorWithId = releaseCompositorWithId;
22
- const waitForCompositorWithIdToQuit = (renderId) => {
23
- if (!compositorMap[renderId]) {
24
- throw new TypeError('No compositor with that id');
25
- }
26
- return compositorMap[renderId].waitForDone();
25
+ exports.getIdealMaximumFrameCacheItems = getIdealMaximumFrameCacheItems;
26
+ const startLongRunningCompositor = (maximumFrameCacheItems, verbose, indent) => {
27
+ return (0, exports.startCompositor)('StartLongRunningProcess', {
28
+ concurrency: (0, get_concurrency_1.getActualConcurrency)(null),
29
+ maximum_frame_cache_items: maximumFrameCacheItems,
30
+ verbose,
31
+ }, indent);
27
32
  };
28
- exports.waitForCompositorWithIdToQuit = waitForCompositorWithIdToQuit;
29
- const startCompositor = (type, payload) => {
33
+ exports.startLongRunningCompositor = startLongRunningCompositor;
34
+ const startCompositor = (type, payload, indent) => {
35
+ var _a;
30
36
  const bin = (0, get_executable_path_1.getExecutablePath)('compositor');
31
- const fullCommand = {
32
- nonce: (0, make_nonce_1.makeNonce)(),
33
- payload: {
34
- type,
35
- params: payload,
36
- },
37
- };
38
- const child = (0, child_process_1.spawn)(bin, [JSON.stringify(fullCommand)], (0, call_ffmpeg_1.dynamicLibraryPathOptions)());
37
+ if (!process.env.READ_ONLY_FS) {
38
+ (0, node_fs_1.chmodSync)(bin, 0o755);
39
+ }
40
+ const fullCommand = (0, compose_1.serializeCommand)(type, payload);
41
+ const child = (0, node_child_process_1.spawn)(bin, [JSON.stringify(fullCommand)], (0, call_ffmpeg_1.dynamicLibraryPathOptions)());
39
42
  const stderrChunks = [];
40
43
  let outputBuffer = Buffer.from('');
41
44
  const separator = Buffer.from('remotion_buffer:');
42
45
  const waiters = new Map();
43
46
  const onMessage = (statusType, nonce, data) => {
44
47
  if (nonce === '0') {
45
- console.log(data.toString('utf8'));
48
+ logger_1.Log.verboseAdvanced({ indent, logLevel: (0, logger_1.getLogLevel)(), tag: 'COMPOSITOR' }, data.toString('utf8'));
46
49
  }
47
50
  if (waiters.has(nonce)) {
48
51
  if (statusType === 'error') {
49
52
  try {
50
53
  const parsed = JSON.parse(data.toString('utf8'));
51
- waiters.get(nonce).reject(new Error(`Compositor error: ${parsed.error}`));
54
+ waiters.get(nonce).reject(new Error(`Compositor error: ${parsed.error}\n${parsed.backtrace}`));
52
55
  }
53
56
  catch (err) {
54
57
  waiters.get(nonce).reject(new Error(data.toString('utf8')));
@@ -137,28 +140,38 @@ const startCompositor = (type, payload) => {
137
140
  processInput();
138
141
  });
139
142
  child.stderr.on('data', (data) => {
140
- if (data.toString('utf-8').includes('No accelerated colorspace conversion')) {
141
- return;
143
+ stderrChunks.push(data);
144
+ });
145
+ let resolve = null;
146
+ let reject = null;
147
+ child.on('close', (code) => {
148
+ quit = true;
149
+ const waitersToKill = Array.from(waiters.values());
150
+ if (code === 0) {
151
+ resolve === null || resolve === void 0 ? void 0 : resolve();
152
+ for (const waiter of waitersToKill) {
153
+ waiter.reject(new Error(`Compositor already quit`));
154
+ }
155
+ waiters.clear();
156
+ }
157
+ else {
158
+ const error = new Error(`Compositor panicked: ${Buffer.concat(stderrChunks).toString('utf-8')}`);
159
+ for (const waiter of waitersToKill) {
160
+ waiter.reject(error);
161
+ }
162
+ waiters.clear();
163
+ reject === null || reject === void 0 ? void 0 : reject(error);
142
164
  }
143
- console.log(data.toString('utf-8'));
144
165
  });
145
166
  return {
146
167
  waitForDone: () => {
147
- return new Promise((resolve, reject) => {
148
- child.on('close', (code) => {
149
- quit = true;
150
- const waitersToKill = Array.from(waiters.values());
151
- for (const waiter of waitersToKill) {
152
- waiter.reject(new Error(`Compositor quit with code ${code}`));
153
- }
154
- waiters.clear();
155
- if (code === 0) {
156
- resolve();
157
- }
158
- else {
159
- reject(Buffer.concat(stderrChunks).toString('utf-8'));
160
- }
161
- });
168
+ return new Promise((res, rej) => {
169
+ if (quit) {
170
+ rej(new Error('Compositor already quit'));
171
+ return;
172
+ }
173
+ resolve = res;
174
+ reject = rej;
162
175
  });
163
176
  },
164
177
  finishCommands: () => {
@@ -171,7 +184,7 @@ const startCompositor = (type, payload) => {
171
184
  if (quit) {
172
185
  throw new Error('Compositor already quit');
173
186
  }
174
- return new Promise((resolve, reject) => {
187
+ return new Promise((_resolve, _reject) => {
175
188
  const nonce = (0, make_nonce_1.makeNonce)();
176
189
  const composed = {
177
190
  nonce,
@@ -183,11 +196,12 @@ const startCompositor = (type, payload) => {
183
196
  // TODO: Should have a way to error out a single task
184
197
  child.stdin.write(JSON.stringify(composed) + '\n');
185
198
  waiters.set(nonce, {
186
- resolve,
187
- reject,
199
+ resolve: _resolve,
200
+ reject: _reject,
188
201
  });
189
202
  });
190
203
  },
204
+ pid: (_a = child.pid) !== null && _a !== void 0 ? _a : null,
191
205
  };
192
206
  };
193
207
  exports.startCompositor = startCompositor;
@@ -8,6 +8,9 @@ function isMusl() {
8
8
  return !glibcVersionRuntime;
9
9
  }
10
10
  const getExecutablePath = (type) => {
11
+ if (type === 'compositor' && process.env.COMPOSITOR_PATH) {
12
+ return process.env.COMPOSITOR_PATH;
13
+ }
11
14
  const key = type === 'compositor'
12
15
  ? 'binaryPath'
13
16
  : type === 'ffmpeg'
@@ -27,13 +27,40 @@ export declare type Layer = {
27
27
  };
28
28
  };
29
29
  export declare type CompositorImageFormat = 'Png' | 'Jpeg';
30
- export declare type CliInput = {
31
- v: number;
32
- output: string;
33
- width: number;
34
- height: number;
35
- layers: Layer[];
36
- output_format: CompositorImageFormat;
30
+ export declare type CompositorCommand = {
31
+ Compose: {
32
+ output: string;
33
+ width: number;
34
+ height: number;
35
+ layers: Layer[];
36
+ output_format: CompositorImageFormat;
37
+ };
38
+ ExtractFrame: {
39
+ input: string;
40
+ time: number;
41
+ transparent: boolean;
42
+ };
43
+ Echo: {
44
+ message: string;
45
+ };
46
+ StartLongRunningProcess: {
47
+ concurrency: number;
48
+ maximum_frame_cache_items: number;
49
+ verbose: boolean;
50
+ };
51
+ GetOpenVideoStats: {};
52
+ DeliberatePanic: {};
53
+ CloseAllVideos: {};
54
+ FreeUpMemory: {
55
+ percent_of_memory: number;
56
+ };
57
+ };
58
+ export declare type CompositorCommandSerialized<T extends keyof CompositorCommand> = {
59
+ nonce: string;
60
+ payload: {
61
+ type: T;
62
+ params: CompositorCommand[T];
63
+ };
37
64
  };
38
65
  export declare type ErrorPayload = {
39
66
  error: string;
package/dist/crf.js CHANGED
@@ -9,7 +9,7 @@ const getDefaultCrfForCodec = (codec) => {
9
9
  if (codec === 'h264' || codec === 'h264-mkv') {
10
10
  return 18; // FFMPEG default 23
11
11
  }
12
- if (codec === 'h265' || codec === 'gif') {
12
+ if (codec === 'h265') {
13
13
  return 23; // FFMPEG default 28
14
14
  }
15
15
  if (codec === 'vp8') {
@@ -21,6 +21,9 @@ const getDefaultCrfForCodec = (codec) => {
21
21
  if (codec === 'prores') {
22
22
  return 0;
23
23
  }
24
+ if (codec === 'gif') {
25
+ return 0;
26
+ }
24
27
  throw new TypeError(`Got unexpected codec "${codec}"`);
25
28
  };
26
29
  exports.getDefaultCrfForCodec = getDefaultCrfForCodec;
@@ -31,10 +34,13 @@ const getValidCrfRanges = (codec) => {
31
34
  if (codec === 'prores') {
32
35
  return [0, 0];
33
36
  }
37
+ if (codec === 'gif') {
38
+ return [0, 0];
39
+ }
34
40
  if (codec === 'h264' || codec === 'h264-mkv') {
35
41
  return [1, 51];
36
42
  }
37
- if (codec === 'h265' || codec === 'gif') {
43
+ if (codec === 'h265') {
38
44
  return [0, 51];
39
45
  }
40
46
  if (codec === 'vp8') {
@@ -24,13 +24,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.deleteDirectory = void 0;
27
- const fs_1 = __importStar(require("fs"));
27
+ const node_fs_1 = __importStar(require("node:fs"));
28
28
  const is_serve_url_1 = require("./is-serve-url");
29
29
  const deleteDirectory = (directory) => {
30
30
  if ((0, is_serve_url_1.isServeUrl)(directory)) {
31
31
  return;
32
32
  }
33
- if (!(0, fs_1.existsSync)(directory)) {
33
+ if (!(0, node_fs_1.existsSync)(directory)) {
34
34
  return;
35
35
  }
36
36
  // Working around a bug with NodeJS 16 on Windows:
@@ -41,7 +41,7 @@ const deleteDirectory = (directory) => {
41
41
  let retries = 2;
42
42
  while (retries >= 0) {
43
43
  try {
44
- fs_1.default.rmSync(directory, {
44
+ node_fs_1.default.rmSync(directory, {
45
45
  maxRetries: 2,
46
46
  recursive: true,
47
47
  force: true,
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.warnAboutM2Bug = void 0;
4
- const os_1 = require("os");
4
+ const node_os_1 = require("node:os");
5
5
  const warnAboutM2Bug = (codec, pixelFormat) => {
6
- const isM2 = (0, os_1.cpus)().find((c) => c.model.includes('Apple M2'));
6
+ const isM2 = (0, node_os_1.cpus)().find((c) => c.model.includes('Apple M2'));
7
7
  if (codec === 'prores' && pixelFormat === 'yuv422p10le' && isM2) {
8
8
  console.warn();
9
9
  console.warn('⚠️ Known issue: Apple M2 CPUs currently suffer from a bug where transparent ProRes videos have flickering. https://github.com/remotion-dev/remotion/issues/1929');
@@ -4,12 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ensureOutputDirectory = void 0;
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
9
  const ensureOutputDirectory = (outputLocation) => {
10
- const dirName = path_1.default.dirname(outputLocation);
11
- if (!fs_1.default.existsSync(dirName)) {
12
- fs_1.default.mkdirSync(dirName, {
10
+ const dirName = node_path_1.default.dirname(outputLocation);
11
+ if (!node_fs_1.default.existsSync(dirName)) {
12
+ node_fs_1.default.mkdirSync(dirName, {
13
13
  recursive: true,
14
14
  });
15
15
  }
@@ -1,8 +1,15 @@
1
1
  import type { DownloadMap } from './assets/download-map';
2
- export declare const ensurePresentationTimestampWithoutCache: ({ src, }: {
2
+ import type { FfmpegExecutable } from './ffmpeg-executable';
3
+ export declare const ensurePresentationTimestampWithoutCache: ({ src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }: {
3
4
  src: string;
5
+ remotionRoot: string;
6
+ ffmpegExecutable: FfmpegExecutable;
7
+ ffprobeExecutable: FfmpegExecutable;
4
8
  }) => Promise<string>;
5
- export declare const ensurePresentationTimestamps: ({ downloadMap, src, }: {
9
+ export declare const ensurePresentationTimestamps: ({ downloadMap, src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }: {
6
10
  downloadMap: DownloadMap;
7
11
  src: string;
12
+ remotionRoot: string;
13
+ ffmpegExecutable: FfmpegExecutable;
14
+ ffprobeExecutable: FfmpegExecutable;
8
15
  }) => Promise<string>;
@@ -4,12 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ensurePresentationTimestamps = exports.ensurePresentationTimestampWithoutCache = void 0;
7
+ const execa_1 = __importDefault(require("execa"));
7
8
  const path_1 = __importDefault(require("path"));
8
- const call_ffmpeg_1 = require("./call-ffmpeg");
9
+ const ffmpeg_flags_1 = require("./ffmpeg-flags");
9
10
  const guess_extension_for_media_1 = require("./guess-extension-for-media");
10
11
  const truthy_1 = require("./truthy");
11
12
  let callbacks = [];
12
- const getTemporaryOutputName = async ({ src }) => {
13
+ const getTemporaryOutputName = async ({ src, remotionRoot, ffprobeBinary, }) => {
13
14
  const parts = src.split(path_1.default.sep);
14
15
  // If there is no file extension for the video, then we need to temporarily add an extension
15
16
  const lastPart = parts[parts.length - 1];
@@ -17,6 +18,8 @@ const getTemporaryOutputName = async ({ src }) => {
17
18
  ? null
18
19
  : await (0, guess_extension_for_media_1.guessExtensionForVideo)({
19
20
  src,
21
+ remotionRoot,
22
+ ffprobeBinary,
20
23
  });
21
24
  return parts
22
25
  .map((p, i) => {
@@ -27,12 +30,14 @@ const getTemporaryOutputName = async ({ src }) => {
27
30
  })
28
31
  .join(path_1.default.sep);
29
32
  };
30
- const ensurePresentationTimestampWithoutCache = async ({ src, }) => {
33
+ const ensurePresentationTimestampWithoutCache = async ({ src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }) => {
31
34
  // If there is no file extension for the video, then we need to tempoa
32
35
  const output = await getTemporaryOutputName({
33
36
  src,
37
+ remotionRoot,
38
+ ffprobeBinary: ffprobeExecutable,
34
39
  });
35
- await (0, call_ffmpeg_1.callFf)('ffmpeg', [
40
+ await (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffmpegExecutable, remotionRoot, 'ffmpeg'), [
36
41
  '-i',
37
42
  src,
38
43
  '-fflags',
@@ -47,7 +52,7 @@ const ensurePresentationTimestampWithoutCache = async ({ src, }) => {
47
52
  return output;
48
53
  };
49
54
  exports.ensurePresentationTimestampWithoutCache = ensurePresentationTimestampWithoutCache;
50
- const ensurePresentationTimestamps = async ({ downloadMap, src, }) => {
55
+ const ensurePresentationTimestamps = async ({ downloadMap, src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }) => {
51
56
  const elem = downloadMap.ensureFileHasPresentationTimestamp[src];
52
57
  if ((elem === null || elem === void 0 ? void 0 : elem.type) === 'encoding') {
53
58
  return new Promise((resolve) => {
@@ -62,6 +67,9 @@ const ensurePresentationTimestamps = async ({ downloadMap, src, }) => {
62
67
  }
63
68
  downloadMap.ensureFileHasPresentationTimestamp[src] = { type: 'encoding' };
64
69
  const output = await (0, exports.ensurePresentationTimestampWithoutCache)({
70
+ ffmpegExecutable,
71
+ ffprobeExecutable,
72
+ remotionRoot,
65
73
  src,
66
74
  });
67
75
  callbacks = callbacks.filter((c) => {
@@ -1,11 +1,13 @@
1
- /// <reference types="node" />
2
1
  import type { OffthreadVideoImageFormat } from 'remotion';
3
2
  import type { DownloadMap } from './assets/download-map';
3
+ import type { FfmpegExecutable } from './ffmpeg-executable';
4
4
  import type { LastFrameOptions } from './last-frame-from-video-cache';
5
5
  export declare const getLastFrameOfVideo: (options: LastFrameOptions) => Promise<Buffer>;
6
6
  declare type Options = {
7
7
  time: number;
8
8
  src: string;
9
+ ffmpegExecutable: FfmpegExecutable;
10
+ ffprobeExecutable: FfmpegExecutable;
9
11
  imageFormat: OffthreadVideoImageFormat;
10
12
  downloadMap: DownloadMap;
11
13
  remotionRoot: string;