@remotion/renderer 4.0.22 → 4.0.24

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 (109) hide show
  1. package/.prettierignore +2 -0
  2. package/dist/assets/get-video-stream-duration.d.ts +9 -0
  3. package/dist/assets/get-video-stream-duration.js +71 -0
  4. package/dist/audio-codec.d.ts +3 -3
  5. package/dist/calculate-sar-dar-pixels.d.ts +9 -0
  6. package/dist/calculate-sar-dar-pixels.js +19 -0
  7. package/dist/client.d.ts +154 -8
  8. package/dist/client.js +4 -0
  9. package/dist/codec.d.ts +1 -1
  10. package/dist/compositor/compositor.d.ts +2 -2
  11. package/dist/compositor/compositor.js +22 -19
  12. package/dist/compositor/payloads.d.ts +2 -2
  13. package/dist/copy-to-clipboard.js +1 -1
  14. package/dist/create-ffmpeg-complex-filter.d.ts +4 -1
  15. package/dist/determine-resize-params.d.ts +4 -0
  16. package/dist/determine-resize-params.js +10 -0
  17. package/dist/determine-vcodec-ffmpeg-flags.d.ts +2 -0
  18. package/dist/determine-vcodec-ffmpeg-flags.js +13 -0
  19. package/dist/ensure-ffmpeg.d.ts +18 -0
  20. package/dist/ensure-ffmpeg.js +58 -0
  21. package/dist/ensure-presentation-timestamp.d.ts +15 -0
  22. package/dist/ensure-presentation-timestamp.js +88 -0
  23. package/dist/extract-frame-from-video.d.ts +16 -0
  24. package/dist/extract-frame-from-video.js +191 -0
  25. package/dist/ffmpeg-executable.d.ts +1 -0
  26. package/dist/ffmpeg-executable.js +2 -0
  27. package/dist/ffmpeg-flags.d.ts +31 -0
  28. package/dist/ffmpeg-flags.js +245 -0
  29. package/dist/file-extensions.d.ts +1 -1
  30. package/dist/format-logs.js +3 -1
  31. package/dist/frame-to-ffmpeg-timestamp.d.ts +1 -0
  32. package/dist/frame-to-ffmpeg-timestamp.js +8 -0
  33. package/dist/get-can-extract-frames-fast.d.ts +14 -0
  34. package/dist/get-can-extract-frames-fast.js +71 -0
  35. package/dist/get-compositions.d.ts +5 -2
  36. package/dist/get-compositions.js +4 -1
  37. package/dist/get-extension-from-codec.js +1 -2
  38. package/dist/get-frame-of-video-slow.d.ts +17 -0
  39. package/dist/get-frame-of-video-slow.js +72 -0
  40. package/dist/get-silent-parts.js +1 -1
  41. package/dist/get-video-info.d.ts +8 -0
  42. package/dist/get-video-info.js +59 -0
  43. package/dist/get-video-metadata.js +1 -1
  44. package/dist/image-format.d.ts +2 -2
  45. package/dist/index.d.ts +38 -14
  46. package/dist/is-beyond-last-frame.d.ts +3 -0
  47. package/dist/is-beyond-last-frame.js +12 -0
  48. package/dist/last-frame-from-video-cache.d.ts +17 -0
  49. package/dist/last-frame-from-video-cache.js +55 -0
  50. package/dist/legacy-webpack-config.d.ts +9 -0
  51. package/dist/legacy-webpack-config.js +13 -0
  52. package/dist/log-level.d.ts +1 -1
  53. package/dist/offthread-video-server.d.ts +2 -1
  54. package/dist/offthread-video-server.js +4 -2
  55. package/dist/open-browser.d.ts +1 -1
  56. package/dist/options/audio-bitrate.d.ts +8 -2
  57. package/dist/options/audio-bitrate.js +1 -0
  58. package/dist/options/crf.d.ts +8 -2
  59. package/dist/options/crf.js +1 -0
  60. package/dist/options/enforce-audio.d.ts +8 -2
  61. package/dist/options/enforce-audio.js +1 -0
  62. package/dist/options/jpeg-quality.d.ts +8 -2
  63. package/dist/options/jpeg-quality.js +1 -0
  64. package/dist/options/mute.d.ts +8 -2
  65. package/dist/options/mute.js +1 -0
  66. package/dist/options/offthreadvideo-cache-size.d.ts +9 -0
  67. package/dist/options/offthreadvideo-cache-size.js +33 -0
  68. package/dist/options/option.d.ts +7 -2
  69. package/dist/options/options-map.d.ts +82 -0
  70. package/dist/options/options-map.js +16 -0
  71. package/dist/options/scale.d.ts +8 -2
  72. package/dist/options/scale.js +1 -0
  73. package/dist/options/video-bitrate.d.ts +8 -2
  74. package/dist/options/video-bitrate.js +1 -0
  75. package/dist/options/video-codec.d.ts +8 -2
  76. package/dist/options/video-codec.js +1 -0
  77. package/dist/pixel-format.d.ts +1 -1
  78. package/dist/prepare-server.d.ts +2 -1
  79. package/dist/prepare-server.js +3 -1
  80. package/dist/prores-profile.d.ts +1 -1
  81. package/dist/provide-screenshot.d.ts +0 -1
  82. package/dist/puppeteer-screenshot.d.ts +0 -1
  83. package/dist/quality.d.ts +1 -0
  84. package/dist/quality.js +21 -0
  85. package/dist/render-frames.d.ts +5 -2
  86. package/dist/render-frames.js +4 -2
  87. package/dist/render-media.d.ts +6 -3
  88. package/dist/render-media.js +5 -2
  89. package/dist/render-still.d.ts +5 -1
  90. package/dist/render-still.js +3 -1
  91. package/dist/screenshot-dom-element.d.ts +0 -1
  92. package/dist/screenshot-task.d.ts +0 -1
  93. package/dist/select-composition.d.ts +4 -1
  94. package/dist/select-composition.js +5 -1
  95. package/dist/serve-static.d.ts +1 -0
  96. package/dist/serve-static.js +1 -0
  97. package/dist/stitch-frames-to-video.d.ts +0 -1
  98. package/dist/take-frame-and-compose.d.ts +0 -1
  99. package/dist/try-to-extract-frame-of-video-fast.d.ts +12 -0
  100. package/dist/try-to-extract-frame-of-video-fast.js +55 -0
  101. package/dist/validate-ffmpeg.d.ts +7 -0
  102. package/dist/validate-ffmpeg.js +77 -0
  103. package/dist/validate-opengl-renderer.d.ts +1 -1
  104. package/dist/warn-about-ffmpeg-version.d.ts +5 -0
  105. package/dist/warn-about-ffmpeg-version.js +37 -0
  106. package/dist/x264-preset.d.ts +1 -1
  107. package/package.json +11 -12
  108. package/dist/presets-profile.d.ts +0 -7
  109. package/dist/presets-profile.js +0 -27
@@ -0,0 +1,2 @@
1
+ # Has error in CI even though is formatted
2
+ src/compositor/compositor.ts
@@ -0,0 +1,9 @@
1
+ import type { FfmpegExecutable } from '../ffmpeg-executable';
2
+ import type { DownloadMap, VideoDurationResult } from './download-map';
3
+ export declare const parseVideoStreamDuration: (stdout: string) => VideoDurationResult;
4
+ export declare function getVideoStreamDurationwithoutCache({ src, ffprobeExecutable, remotionRoot, }: {
5
+ src: string;
6
+ ffprobeExecutable: FfmpegExecutable;
7
+ remotionRoot: string;
8
+ }): Promise<VideoDurationResult>;
9
+ export declare const getVideoStreamDuration: (downloadMap: DownloadMap, src: string, ffprobeExecutable: FfmpegExecutable, remotionRoot: string) => Promise<VideoDurationResult>;
@@ -0,0 +1,71 @@
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.getVideoStreamDuration = exports.getVideoStreamDurationwithoutCache = exports.parseVideoStreamDuration = void 0;
7
+ const execa_1 = __importDefault(require("execa"));
8
+ const ffmpeg_flags_1 = require("../ffmpeg-flags");
9
+ const p_limit_1 = require("../p-limit");
10
+ const limit = (0, p_limit_1.pLimit)(1);
11
+ const parseAlternativeDuration = (stdout) => {
12
+ const webmDuration = stdout.match(/TAG:DURATION=([0-9.]+):([0-9.]+):([0-9.]+)/);
13
+ if (!webmDuration) {
14
+ return null;
15
+ }
16
+ const [, hours, minutes, seconds] = webmDuration;
17
+ const hoursAsNumber = Number(hours);
18
+ if (Number.isNaN(hoursAsNumber)) {
19
+ return null;
20
+ }
21
+ const minutesAsNumber = Number(minutes);
22
+ if (Number.isNaN(minutesAsNumber)) {
23
+ return null;
24
+ }
25
+ const secondsAsNumber = Number(seconds);
26
+ if (Number.isNaN(secondsAsNumber)) {
27
+ return null;
28
+ }
29
+ return secondsAsNumber + minutesAsNumber * 60 + hoursAsNumber * 3600;
30
+ };
31
+ const parseVideoStreamDuration = (stdout) => {
32
+ const duration = stdout.match(/duration=([0-9.]+)/);
33
+ const alternativeDuration = parseAlternativeDuration(stdout);
34
+ const fps = stdout.match(/r_frame_rate=([0-9.]+)\/([0-9.]+)/);
35
+ const result = {
36
+ duration: duration ? parseFloat(duration[1]) : alternativeDuration,
37
+ fps: fps ? parseInt(fps[1], 10) / parseInt(fps[2], 10) : null,
38
+ };
39
+ return result;
40
+ };
41
+ exports.parseVideoStreamDuration = parseVideoStreamDuration;
42
+ async function getVideoStreamDurationwithoutCache({ src, ffprobeExecutable, remotionRoot, }) {
43
+ const args = [
44
+ ['-v', 'error'],
45
+ ['-select_streams', 'v:0'],
46
+ ['-show_entries', 'stream'],
47
+ [src],
48
+ ]
49
+ .reduce((acc, val) => acc.concat(val), [])
50
+ .filter(Boolean);
51
+ const task = await (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffprobeExecutable, remotionRoot, 'ffprobe'), args);
52
+ const result = (0, exports.parseVideoStreamDuration)(task.stdout);
53
+ return result;
54
+ }
55
+ exports.getVideoStreamDurationwithoutCache = getVideoStreamDurationwithoutCache;
56
+ async function getVideoStreamDurationUnlimited(downloadMap, src, ffprobeExecutable, remotionRoot) {
57
+ if (downloadMap.videoDurationResultCache[src]) {
58
+ return downloadMap.videoDurationResultCache[src];
59
+ }
60
+ const result = await getVideoStreamDurationwithoutCache({
61
+ src,
62
+ ffprobeExecutable,
63
+ remotionRoot,
64
+ });
65
+ downloadMap.videoDurationResultCache[src] = result;
66
+ return result;
67
+ }
68
+ const getVideoStreamDuration = (downloadMap, src, ffprobeExecutable, remotionRoot) => {
69
+ return limit(() => getVideoStreamDurationUnlimited(downloadMap, src, ffprobeExecutable, remotionRoot));
70
+ };
71
+ exports.getVideoStreamDuration = getVideoStreamDuration;
@@ -1,6 +1,6 @@
1
1
  import type { Codec } from './codec';
2
2
  export declare const validAudioCodecs: readonly ["pcm-16", "aac", "mp3", "opus"];
3
- export type AudioCodec = typeof validAudioCodecs[number];
3
+ export type AudioCodec = (typeof validAudioCodecs)[number];
4
4
  export declare const supportedAudioCodecs: {
5
5
  readonly h264: readonly ["aac", "pcm-16", "mp3"];
6
6
  readonly 'h264-mkv': readonly ["pcm-16", "mp3"];
@@ -14,11 +14,11 @@ export declare const supportedAudioCodecs: {
14
14
  readonly wav: readonly ["pcm-16"];
15
15
  };
16
16
  declare const audioCodecNames: readonly ["pcm_s16le", "aac", "libmp3lame", "libopus"];
17
- type FfmpegAudioCodecName = typeof audioCodecNames[number];
17
+ type FfmpegAudioCodecName = (typeof audioCodecNames)[number];
18
18
  export declare const mapAudioCodecToFfmpegAudioCodecName: (audioCodec: AudioCodec) => FfmpegAudioCodecName;
19
19
  export declare const defaultAudioCodecs: {
20
20
  [key in Codec]: {
21
- [k in 'compressed' | 'lossless']: typeof supportedAudioCodecs[key][number] | null;
21
+ [k in 'compressed' | 'lossless']: (typeof supportedAudioCodecs)[key][number] | null;
22
22
  };
23
23
  };
24
24
  export declare const getDefaultAudioCodec: ({ codec, preferLossless, }: {
@@ -0,0 +1,9 @@
1
+ export declare const calculateDisplayVideoSize: ({ darX, darY, x, y, }: {
2
+ x: number;
3
+ y: number;
4
+ darX: number;
5
+ darY: number;
6
+ }) => {
7
+ width: number;
8
+ height: number;
9
+ };
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ // https://superuser.com/questions/907933/correct-aspect-ratio-without-re-encoding-video-file
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.calculateDisplayVideoSize = void 0;
5
+ const calculateDisplayVideoSize = ({ darX, darY, x, y, }) => {
6
+ // We know two equations:
7
+ // newWidth / newHeight = darX / darY
8
+ // and:
9
+ // x * y = (newWidth * newHeight)
10
+ // I solved it then on pen and paper and simplified the formula:
11
+ const dimensions = x * y;
12
+ const newWidth = Math.sqrt(dimensions * (darX / darY));
13
+ const newHeight = dimensions / newWidth;
14
+ return {
15
+ height: Math.round(newHeight),
16
+ width: Math.round(newWidth),
17
+ };
18
+ };
19
+ exports.calculateDisplayVideoSize = calculateDisplayVideoSize;
package/dist/client.d.ts CHANGED
@@ -194,14 +194,160 @@ export declare const BrowserSafeApis: {
194
194
  preferLossless: boolean;
195
195
  }) => void;
196
196
  options: {
197
- scaleOption: import(".").RemotionOption;
198
- crfOption: import(".").RemotionOption;
199
- jpegQualityOption: import(".").RemotionOption;
200
- videoBitrate: import(".").RemotionOption;
201
- audioBitrateOption: import(".").RemotionOption;
202
- enforceAudioOption: import(".").RemotionOption;
203
- muteOption: import(".").RemotionOption;
204
- videoCodecOption: import(".").RemotionOption;
197
+ scaleOption: {
198
+ name: string;
199
+ cliFlag: string;
200
+ description: JSX.Element;
201
+ ssrName: string;
202
+ docLink: string;
203
+ type: number;
204
+ };
205
+ crfOption: {
206
+ name: string;
207
+ cliFlag: string;
208
+ description: JSX.Element;
209
+ ssrName: string;
210
+ docLink: string;
211
+ type: number;
212
+ };
213
+ jpegQualityOption: {
214
+ name: string;
215
+ cliFlag: string;
216
+ description: JSX.Element;
217
+ ssrName: string;
218
+ docLink: string;
219
+ type: number;
220
+ };
221
+ videoBitrate: {
222
+ name: string;
223
+ cliFlag: string;
224
+ description: JSX.Element;
225
+ ssrName: string;
226
+ docLink: string;
227
+ type: string;
228
+ };
229
+ audioBitrateOption: {
230
+ name: string;
231
+ cliFlag: string;
232
+ description: JSX.Element;
233
+ ssrName: string;
234
+ docLink: string;
235
+ type: string;
236
+ };
237
+ enforceAudioOption: {
238
+ name: string;
239
+ cliFlag: string;
240
+ description: JSX.Element;
241
+ ssrName: string;
242
+ docLink: string;
243
+ type: boolean;
244
+ };
245
+ muteOption: {
246
+ name: string;
247
+ cliFlag: string;
248
+ description: JSX.Element;
249
+ ssrName: string;
250
+ docLink: string;
251
+ type: boolean;
252
+ };
253
+ videoCodecOption: {
254
+ name: string;
255
+ cliFlag: string;
256
+ description: JSX.Element;
257
+ ssrName: string;
258
+ docLink: string;
259
+ type: string;
260
+ };
261
+ offthreadVideoCacheSizeInBytesOption: {
262
+ name: string;
263
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
264
+ description: JSX.Element;
265
+ ssrName: "offthreadVideoCacheSizeInBytes";
266
+ docLink: string;
267
+ type: number | null;
268
+ };
269
+ };
270
+ optionsMap: {
271
+ readonly renderMedia: readonly [{
272
+ name: string;
273
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
274
+ description: JSX.Element;
275
+ ssrName: "offthreadVideoCacheSizeInBytes";
276
+ docLink: string;
277
+ type: number | null;
278
+ }];
279
+ readonly renderStill: readonly [{
280
+ name: string;
281
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
282
+ description: JSX.Element;
283
+ ssrName: "offthreadVideoCacheSizeInBytes";
284
+ docLink: string;
285
+ type: number | null;
286
+ }];
287
+ readonly getCompositions: readonly [{
288
+ name: string;
289
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
290
+ description: JSX.Element;
291
+ ssrName: "offthreadVideoCacheSizeInBytes";
292
+ docLink: string;
293
+ type: number | null;
294
+ }];
295
+ readonly selectComposition: readonly [{
296
+ name: string;
297
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
298
+ description: JSX.Element;
299
+ ssrName: "offthreadVideoCacheSizeInBytes";
300
+ docLink: string;
301
+ type: number | null;
302
+ }];
303
+ readonly renderFrames: readonly [{
304
+ name: string;
305
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
306
+ description: JSX.Element;
307
+ ssrName: "offthreadVideoCacheSizeInBytes";
308
+ docLink: string;
309
+ type: number | null;
310
+ }];
311
+ readonly renderMediaOnLambda: readonly [{
312
+ name: string;
313
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
314
+ description: JSX.Element;
315
+ ssrName: "offthreadVideoCacheSizeInBytes";
316
+ docLink: string;
317
+ type: number | null;
318
+ }];
319
+ readonly renderStillOnLambda: readonly [{
320
+ name: string;
321
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
322
+ description: JSX.Element;
323
+ ssrName: "offthreadVideoCacheSizeInBytes";
324
+ docLink: string;
325
+ type: number | null;
326
+ }];
327
+ readonly getCompositionsOnLambda: readonly [{
328
+ name: string;
329
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
330
+ description: JSX.Element;
331
+ ssrName: "offthreadVideoCacheSizeInBytes";
332
+ docLink: string;
333
+ type: number | null;
334
+ }];
335
+ readonly renderMediaOnCloudRun: readonly [{
336
+ name: string;
337
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
338
+ description: JSX.Element;
339
+ ssrName: "offthreadVideoCacheSizeInBytes";
340
+ docLink: string;
341
+ type: number | null;
342
+ }];
343
+ readonly renderStillOnCloudRun: readonly [{
344
+ name: string;
345
+ cliFlag: "offthreadvideo-cache-size-in-bytes";
346
+ description: JSX.Element;
347
+ ssrName: "offthreadVideoCacheSizeInBytes";
348
+ docLink: string;
349
+ type: number | null;
350
+ }];
205
351
  };
206
352
  codecSupportsCrf: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
207
353
  codecSupportsVideoBitrate: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
package/dist/client.js CHANGED
@@ -13,6 +13,8 @@ const crf_2 = require("./options/crf");
13
13
  const enforce_audio_1 = require("./options/enforce-audio");
14
14
  const jpeg_quality_1 = require("./options/jpeg-quality");
15
15
  const mute_1 = require("./options/mute");
16
+ const offthreadvideo_cache_size_1 = require("./options/offthreadvideo-cache-size");
17
+ const options_map_1 = require("./options/options-map");
16
18
  const scale_1 = require("./options/scale");
17
19
  const video_bitrate_1 = require("./options/video-bitrate");
18
20
  const video_codec_1 = require("./options/video-codec");
@@ -45,7 +47,9 @@ exports.BrowserSafeApis = {
45
47
  enforceAudioOption: enforce_audio_1.enforceAudioOption,
46
48
  muteOption: mute_1.muteOption,
47
49
  videoCodecOption: video_codec_1.videoCodecOption,
50
+ offthreadVideoCacheSizeInBytesOption: offthreadvideo_cache_size_1.offthreadVideoCacheSizeInBytesOption,
48
51
  },
52
+ optionsMap: options_map_1.optionsMap,
49
53
  codecSupportsCrf: codec_supports_media_1.codecSupportsCrf,
50
54
  codecSupportsVideoBitrate: codec_supports_media_1.codecSupportsVideoBitrate,
51
55
  };
package/dist/codec.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export declare const validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
2
- export type Codec = typeof validCodecs[number];
2
+ export type Codec = (typeof validCodecs)[number];
3
3
  export type CodecOrUndefined = Codec | undefined;
4
4
  export declare const DEFAULT_CODEC: Codec;
@@ -7,6 +7,6 @@ export type Compositor = {
7
7
  waitForDone: () => Promise<void>;
8
8
  pid: number | null;
9
9
  };
10
- export declare const getIdealMaximumFrameCacheItems: () => number;
11
- export declare const startLongRunningCompositor: (maximumFrameCacheItems: number, logLevel: LogLevel, indent: boolean) => Compositor;
10
+ export declare const getIdealMaximumFrameCacheSizeInBytes: () => number;
11
+ export declare const startLongRunningCompositor: (maximumFrameCacheItemsInBytes: number, logLevel: LogLevel, indent: boolean) => Compositor;
12
12
  export declare const startCompositor: <T extends keyof CompositorCommand>(type: T, payload: CompositorCommand[T], logLevel: LogLevel, indent: boolean) => Compositor;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.startCompositor = exports.startLongRunningCompositor = exports.getIdealMaximumFrameCacheItems = void 0;
6
+ exports.startCompositor = exports.startLongRunningCompositor = exports.getIdealMaximumFrameCacheSizeInBytes = void 0;
7
7
  const node_child_process_1 = require("node:child_process");
8
8
  const node_fs_1 = require("node:fs");
9
9
  const node_os_1 = __importDefault(require("node:os"));
@@ -14,21 +14,20 @@ const logger_1 = require("../logger");
14
14
  const compose_1 = require("./compose");
15
15
  const get_executable_path_1 = require("./get-executable-path");
16
16
  const make_nonce_1 = require("./make-nonce");
17
- const getIdealMaximumFrameCacheItems = () => {
17
+ const getIdealMaximumFrameCacheSizeInBytes = () => {
18
18
  const freeMemory = node_os_1.default.freemem();
19
- // Assuming 1 frame is approximately 24MB
20
- // (4K video)
21
19
  // Assuming only half the available memory should be used
22
- const max = Math.floor(freeMemory / (1024 * 1024 * 24));
23
- // Never store more than 2000 frames
24
- // But 60 is needed even if it's going to swap
25
- return Math.max(60, Math.min(max, 2000));
20
+ const max = freeMemory / 2;
21
+ // Never store more than 2000 MB
22
+ // But 240MB is needed even if it's going to swap
23
+ return Math.max(mbToBytes(240), Math.min(max, mbToBytes(2000)));
26
24
  };
27
- exports.getIdealMaximumFrameCacheItems = getIdealMaximumFrameCacheItems;
28
- const startLongRunningCompositor = (maximumFrameCacheItems, logLevel, indent) => {
25
+ exports.getIdealMaximumFrameCacheSizeInBytes = getIdealMaximumFrameCacheSizeInBytes;
26
+ const mbToBytes = (mb) => mb * 1024 * 1024;
27
+ const startLongRunningCompositor = (maximumFrameCacheItemsInBytes, logLevel, indent) => {
29
28
  return (0, exports.startCompositor)('StartLongRunningProcess', {
30
29
  concurrency: (0, get_concurrency_1.getActualConcurrency)(null),
31
- maximum_frame_cache_items: maximumFrameCacheItems,
30
+ maximum_frame_cache_size_in_bytes: maximumFrameCacheItemsInBytes,
32
31
  verbose: (0, log_level_1.isEqualOrBelowLogLevel)(logLevel, 'verbose'),
33
32
  }, logLevel, indent);
34
33
  };
@@ -149,17 +148,17 @@ const startCompositor = (type, payload, logLevel, indent) => {
149
148
  child.on('close', (code, signal) => {
150
149
  const waitersToKill = Array.from(waiters.values());
151
150
  if (code === 0) {
152
- runningStatus = { type: 'quit-without-error' };
151
+ runningStatus = { type: 'quit-without-error', signal };
153
152
  resolve === null || resolve === void 0 ? void 0 : resolve();
154
153
  for (const waiter of waitersToKill) {
155
- waiter.reject(new Error(`Compositor already quit`));
154
+ waiter.reject(new Error(`Compositor quit${signal ? ` with signal ${signal}` : ''}`));
156
155
  }
157
156
  waiters.clear();
158
157
  }
159
158
  else {
160
159
  const errorMessage = Buffer.concat(stderrChunks).toString('utf-8') +
161
160
  outputBuffer.toString('utf-8');
162
- runningStatus = { type: 'quit-with-error', error: errorMessage };
161
+ runningStatus = { type: 'quit-with-error', error: errorMessage, signal };
163
162
  const error = code === null
164
163
  ? new Error(`Compositor exited with signal ${signal}`)
165
164
  : new Error(`Compositor panicked with code ${code}: ${errorMessage}`);
@@ -174,11 +173,15 @@ const startCompositor = (type, payload, logLevel, indent) => {
174
173
  waitForDone: () => {
175
174
  return new Promise((res, rej) => {
176
175
  if (runningStatus.type === 'quit-without-error') {
177
- rej(new Error('Compositor already quit'));
176
+ rej(new Error(`Compositor quit${runningStatus.signal
177
+ ? ` with signal ${runningStatus.signal}`
178
+ : ''}`));
178
179
  return;
179
180
  }
180
181
  if (runningStatus.type === 'quit-with-error') {
181
- rej(new Error(`Compositor already quit: ${runningStatus.error}`));
182
+ rej(new Error(`Compositor quit${runningStatus.signal
183
+ ? ` with signal ${runningStatus.signal}`
184
+ : ''}: ${runningStatus.error}`));
182
185
  return;
183
186
  }
184
187
  resolve = res;
@@ -187,16 +190,16 @@ const startCompositor = (type, payload, logLevel, indent) => {
187
190
  },
188
191
  finishCommands: () => {
189
192
  if (runningStatus.type === 'quit-with-error') {
190
- throw new Error(`Compositor already quit: ${runningStatus.error}`);
193
+ throw new Error(`Compositor quit${runningStatus.signal ? ` with signal ${runningStatus.signal}` : ''}: ${runningStatus.error}`);
191
194
  }
192
195
  if (runningStatus.type === 'quit-without-error') {
193
- throw new Error('Compositor already quit');
196
+ throw new Error(`Compositor quit${runningStatus.signal ? ` with signal ${runningStatus.signal}` : ''}`);
194
197
  }
195
198
  child.stdin.write('EOF\n');
196
199
  },
197
200
  executeCommand: (command, params) => {
198
201
  if (runningStatus.type === 'quit-without-error') {
199
- throw new Error('Compositor already quit');
202
+ throw new Error(`Compositor quit${runningStatus.signal ? ` with signal ${runningStatus.signal}` : ''}`);
200
203
  }
201
204
  if (runningStatus.type === 'quit-with-error') {
202
205
  throw new Error(`Compositor quit: ${runningStatus.error}`);
@@ -72,7 +72,7 @@ export type CompositorCommand = {
72
72
  };
73
73
  StartLongRunningProcess: {
74
74
  concurrency: number;
75
- maximum_frame_cache_items: number;
75
+ maximum_frame_cache_size_in_bytes: number;
76
76
  verbose: boolean;
77
77
  };
78
78
  CopyImageToClipboard: {
@@ -82,7 +82,7 @@ export type CompositorCommand = {
82
82
  DeliberatePanic: {};
83
83
  CloseAllVideos: {};
84
84
  FreeUpMemory: {
85
- percent_of_memory: number;
85
+ remaining_bytes: number;
86
86
  };
87
87
  GetVideoMetadata: {
88
88
  src: string;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.copyImageToClipboard = void 0;
4
4
  const compositor_1 = require("./compositor/compositor");
5
5
  const copyImageToClipboard = async (src, logLevel) => {
6
- const compositor = (0, compositor_1.startLongRunningCompositor)((0, compositor_1.getIdealMaximumFrameCacheItems)(), logLevel, false);
6
+ const compositor = (0, compositor_1.startLongRunningCompositor)((0, compositor_1.getIdealMaximumFrameCacheSizeInBytes)(), logLevel, false);
7
7
  await compositor.executeCommand('CopyImageToClipboard', {
8
8
  src,
9
9
  });
@@ -4,6 +4,9 @@ export declare const createFfmpegComplexFilter: ({ filters, downloadMap, }: {
4
4
  filters: PreprocessedAudioTrack[];
5
5
  downloadMap: DownloadMap;
6
6
  }) => Promise<{
7
- complexFilterFlag: [string, string] | null;
7
+ complexFilterFlag: [
8
+ string,
9
+ string
10
+ ] | null;
8
11
  cleanup: () => void;
9
12
  }>;
@@ -0,0 +1,4 @@
1
+ export declare const determineResizeParams: (needsResize: [
2
+ number,
3
+ number
4
+ ] | null) => string[];
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.determineResizeParams = void 0;
4
+ const determineResizeParams = (needsResize) => {
5
+ if (needsResize === null) {
6
+ return [];
7
+ }
8
+ return ['-s', `${needsResize[0]}x${needsResize[1]}`];
9
+ };
10
+ exports.determineResizeParams = determineResizeParams;
@@ -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;
@@ -0,0 +1,18 @@
1
+ export type EnsureFfmpegOptions = {
2
+ remotionRoot?: string;
3
+ };
4
+ type Result = {
5
+ result: 'found-in-path' | 'found-in-node-modules' | 'installed';
6
+ wasAlreadyInstalled: boolean;
7
+ };
8
+ /**
9
+ * @description Checks if the ffmpeg binary is installed and if it is not, downloads it and puts it into your node_modules folder.
10
+ * @see [Documentation](https://www.remotion.dev/docs/renderer/ensure-ffmpeg)
11
+ */
12
+ export declare const ensureFfmpeg: (options?: EnsureFfmpegOptions) => Promise<Result>;
13
+ /**
14
+ * @description Checks if the ffprobe binary is installed and if it is not, downloads it and puts it into your node_modules folder.
15
+ * @see [Documentation](https://www.remotion.dev/docs/renderer/ensure-ffprobe)
16
+ */
17
+ export declare const ensureFfprobe: (options?: EnsureFfmpegOptions) => Promise<Result>;
18
+ export {};
@@ -0,0 +1,58 @@
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.ensureFfprobe = exports.ensureFfmpeg = void 0;
7
+ const fs_1 = require("fs");
8
+ const os_1 = __importDefault(require("os"));
9
+ const ffmpeg_flags_1 = require("./ffmpeg-flags");
10
+ const validate_ffmpeg_1 = require("./validate-ffmpeg");
11
+ const ensureFfmpegOrFfprobe = async (binary, options) => {
12
+ var _a;
13
+ const exists = (0, validate_ffmpeg_1.binaryExists)(binary);
14
+ const remotionRoot = (_a = options === null || options === void 0 ? void 0 : options.remotionRoot) !== null && _a !== void 0 ? _a : process.cwd();
15
+ if (exists) {
16
+ return {
17
+ wasAlreadyInstalled: true,
18
+ result: 'found-in-path',
19
+ };
20
+ }
21
+ if (process.platform === 'linux' && (0, fs_1.existsSync)(ffmpeg_flags_1.lambdaFfmpegPaths[binary])) {
22
+ return {
23
+ wasAlreadyInstalled: true,
24
+ result: 'found-in-path',
25
+ };
26
+ }
27
+ if ((0, ffmpeg_flags_1.ffmpegInNodeModules)(remotionRoot, binary)) {
28
+ return {
29
+ result: 'found-in-node-modules',
30
+ wasAlreadyInstalled: true,
31
+ };
32
+ }
33
+ const binaryUrl = (0, ffmpeg_flags_1.getBinaryDownloadUrl)(binary);
34
+ if (binaryUrl) {
35
+ await (0, ffmpeg_flags_1.downloadBinary)(remotionRoot, binaryUrl.url, binary);
36
+ return {
37
+ result: 'installed',
38
+ wasAlreadyInstalled: false,
39
+ };
40
+ }
41
+ throw new Error(`${binary} could not be installed automatically. Your architecture and OS combination (os = ${os_1.default.platform()}, arch = ${process.arch}) is not supported. Please install ${binary} manually and add "${binary}" to your PATH.`);
42
+ };
43
+ /**
44
+ * @description Checks if the ffmpeg binary is installed and if it is not, downloads it and puts it into your node_modules folder.
45
+ * @see [Documentation](https://www.remotion.dev/docs/renderer/ensure-ffmpeg)
46
+ */
47
+ const ensureFfmpeg = (options) => {
48
+ return ensureFfmpegOrFfprobe('ffmpeg', options);
49
+ };
50
+ exports.ensureFfmpeg = ensureFfmpeg;
51
+ /**
52
+ * @description Checks if the ffprobe binary is installed and if it is not, downloads it and puts it into your node_modules folder.
53
+ * @see [Documentation](https://www.remotion.dev/docs/renderer/ensure-ffprobe)
54
+ */
55
+ const ensureFfprobe = (options) => {
56
+ return ensureFfmpegOrFfprobe('ffprobe', options);
57
+ };
58
+ exports.ensureFfprobe = ensureFfprobe;
@@ -0,0 +1,15 @@
1
+ import type { DownloadMap } from './assets/download-map';
2
+ import type { FfmpegExecutable } from './ffmpeg-executable';
3
+ export declare const ensurePresentationTimestampWithoutCache: ({ src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }: {
4
+ src: string;
5
+ remotionRoot: string;
6
+ ffmpegExecutable: FfmpegExecutable;
7
+ ffprobeExecutable: FfmpegExecutable;
8
+ }) => Promise<string>;
9
+ export declare const ensurePresentationTimestamps: ({ downloadMap, src, remotionRoot, ffmpegExecutable, ffprobeExecutable, }: {
10
+ downloadMap: DownloadMap;
11
+ src: string;
12
+ remotionRoot: string;
13
+ ffmpegExecutable: FfmpegExecutable;
14
+ ffprobeExecutable: FfmpegExecutable;
15
+ }) => Promise<string>;