@remotion/renderer 4.0.21 → 4.0.23

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 (117) 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/browser/Product.d.ts +16 -0
  6. package/dist/browser/Product.js +17 -0
  7. package/dist/browser/create-browser-fetcher.d.ts +17 -0
  8. package/dist/browser/create-browser-fetcher.js +58 -0
  9. package/dist/browser/revisions.d.ts +20 -0
  10. package/dist/browser/revisions.js +21 -0
  11. package/dist/calculate-sar-dar-pixels.d.ts +9 -0
  12. package/dist/calculate-sar-dar-pixels.js +19 -0
  13. package/dist/client.d.ts +155 -8
  14. package/dist/client.js +6 -0
  15. package/dist/codec.d.ts +1 -1
  16. package/dist/compositor/compositor.d.ts +2 -2
  17. package/dist/compositor/compositor.js +22 -19
  18. package/dist/compositor/payloads.d.ts +2 -2
  19. package/dist/copy-to-clipboard.js +1 -1
  20. package/dist/create-ffmpeg-complex-filter.d.ts +4 -1
  21. package/dist/determine-resize-params.d.ts +4 -0
  22. package/dist/determine-resize-params.js +10 -0
  23. package/dist/determine-vcodec-ffmpeg-flags.d.ts +2 -0
  24. package/dist/determine-vcodec-ffmpeg-flags.js +13 -0
  25. package/dist/ensure-ffmpeg.d.ts +18 -0
  26. package/dist/ensure-ffmpeg.js +58 -0
  27. package/dist/ensure-presentation-timestamp.d.ts +15 -0
  28. package/dist/ensure-presentation-timestamp.js +88 -0
  29. package/dist/extract-frame-from-video.d.ts +16 -0
  30. package/dist/extract-frame-from-video.js +191 -0
  31. package/dist/ffmpeg-executable.d.ts +1 -0
  32. package/dist/ffmpeg-executable.js +2 -0
  33. package/dist/ffmpeg-flags.d.ts +31 -0
  34. package/dist/ffmpeg-flags.js +245 -0
  35. package/dist/file-extensions.d.ts +1 -1
  36. package/dist/format-logs.js +3 -1
  37. package/dist/frame-to-ffmpeg-timestamp.d.ts +1 -0
  38. package/dist/frame-to-ffmpeg-timestamp.js +8 -0
  39. package/dist/get-can-extract-frames-fast.d.ts +14 -0
  40. package/dist/get-can-extract-frames-fast.js +71 -0
  41. package/dist/get-compositions.d.ts +5 -2
  42. package/dist/get-compositions.js +4 -1
  43. package/dist/get-extension-from-codec.js +1 -2
  44. package/dist/get-frame-of-video-slow.d.ts +17 -0
  45. package/dist/get-frame-of-video-slow.js +72 -0
  46. package/dist/get-silent-parts.d.ts +1 -1
  47. package/dist/get-silent-parts.js +1 -1
  48. package/dist/get-video-info.d.ts +8 -0
  49. package/dist/get-video-info.js +59 -0
  50. package/dist/get-video-metadata.js +1 -1
  51. package/dist/image-format.d.ts +2 -2
  52. package/dist/index.d.ts +54 -29
  53. package/dist/is-beyond-last-frame.d.ts +3 -0
  54. package/dist/is-beyond-last-frame.js +12 -0
  55. package/dist/last-frame-from-video-cache.d.ts +17 -0
  56. package/dist/last-frame-from-video-cache.js +55 -0
  57. package/dist/legacy-webpack-config.d.ts +9 -0
  58. package/dist/legacy-webpack-config.js +13 -0
  59. package/dist/log-level.d.ts +1 -1
  60. package/dist/logger.d.ts +1 -1
  61. package/dist/offthread-video-server.d.ts +2 -1
  62. package/dist/offthread-video-server.js +7 -2
  63. package/dist/open-browser.d.ts +1 -1
  64. package/dist/options/audio-bitrate.d.ts +8 -2
  65. package/dist/options/audio-bitrate.js +1 -0
  66. package/dist/options/crf.d.ts +8 -2
  67. package/dist/options/crf.js +1 -0
  68. package/dist/options/enforce-audio.d.ts +8 -2
  69. package/dist/options/enforce-audio.js +1 -0
  70. package/dist/options/jpeg-quality.d.ts +8 -2
  71. package/dist/options/jpeg-quality.js +1 -0
  72. package/dist/options/mute.d.ts +8 -2
  73. package/dist/options/mute.js +1 -0
  74. package/dist/options/offthreadvideo-cache-size.d.ts +9 -0
  75. package/dist/options/offthreadvideo-cache-size.js +33 -0
  76. package/dist/options/option.d.ts +7 -2
  77. package/dist/options/options-map.d.ts +82 -0
  78. package/dist/options/options-map.js +16 -0
  79. package/dist/options/scale.d.ts +8 -2
  80. package/dist/options/scale.js +1 -0
  81. package/dist/options/video-bitrate.d.ts +8 -2
  82. package/dist/options/video-bitrate.js +1 -0
  83. package/dist/options/video-codec.d.ts +8 -2
  84. package/dist/options/video-codec.js +1 -0
  85. package/dist/pixel-format.d.ts +1 -1
  86. package/dist/prepare-server.d.ts +2 -1
  87. package/dist/prepare-server.js +3 -1
  88. package/dist/prores-profile.d.ts +1 -1
  89. package/dist/provide-screenshot.d.ts +0 -1
  90. package/dist/puppeteer-screenshot.d.ts +0 -1
  91. package/dist/quality.d.ts +1 -0
  92. package/dist/quality.js +21 -0
  93. package/dist/render-frames.d.ts +5 -2
  94. package/dist/render-frames.js +4 -2
  95. package/dist/render-media.d.ts +9 -3
  96. package/dist/render-media.js +12 -2
  97. package/dist/render-still.d.ts +5 -1
  98. package/dist/render-still.js +3 -1
  99. package/dist/screenshot-dom-element.d.ts +0 -1
  100. package/dist/screenshot-task.d.ts +0 -1
  101. package/dist/select-composition.d.ts +4 -1
  102. package/dist/select-composition.js +5 -1
  103. package/dist/serve-static.d.ts +1 -0
  104. package/dist/serve-static.js +1 -0
  105. package/dist/stitch-frames-to-video.d.ts +4 -2
  106. package/dist/stitch-frames-to-video.js +4 -2
  107. package/dist/take-frame-and-compose.d.ts +0 -1
  108. package/dist/try-to-extract-frame-of-video-fast.d.ts +12 -0
  109. package/dist/try-to-extract-frame-of-video-fast.js +55 -0
  110. package/dist/validate-ffmpeg.d.ts +7 -0
  111. package/dist/validate-ffmpeg.js +77 -0
  112. package/dist/validate-opengl-renderer.d.ts +1 -1
  113. package/dist/warn-about-ffmpeg-version.d.ts +5 -0
  114. package/dist/warn-about-ffmpeg-version.js +37 -0
  115. package/dist/x264-preset.d.ts +7 -0
  116. package/dist/x264-preset.js +29 -0
  117. package/package.json +11 -12
@@ -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,16 @@
1
+ /**
2
+ * Copyright 2020 Google Inc. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export type Product = 'chrome' | 'firefox';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright 2020 Google Inc. All rights reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright 2020 Google Inc. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import type { Product } from './Product';
17
+ export declare function downloadBrowser(product: Product): Promise<void>;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright 2020 Google Inc. All rights reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.downloadBrowser = void 0;
19
+ const BrowserFetcher_1 = require("./BrowserFetcher");
20
+ const revisions_1 = require("./revisions");
21
+ const supportedProducts = {
22
+ chrome: 'Chromium',
23
+ firefox: 'Firefox Nightly',
24
+ };
25
+ function getRevision(product) {
26
+ if (product === 'chrome') {
27
+ return revisions_1.PUPPETEER_REVISIONS.chromium;
28
+ }
29
+ throw new Error(`Unsupported product ${product}`);
30
+ }
31
+ async function downloadBrowser(product) {
32
+ const revision = getRevision(product);
33
+ const revisionInfo = (0, BrowserFetcher_1.getRevisionInfo)(revision, product);
34
+ await (0, BrowserFetcher_1.download)({
35
+ revision: revisionInfo.revision,
36
+ progressCallback: (downloadedBytes, totalBytes) => {
37
+ console.log('Downloading', supportedProducts[product], toMegabytes(downloadedBytes) + '/' + toMegabytes(totalBytes));
38
+ },
39
+ product,
40
+ platform: (0, BrowserFetcher_1.getPlatform)(product),
41
+ downloadHost: (0, BrowserFetcher_1.getDownloadHost)(product),
42
+ downloadsFolder: (0, BrowserFetcher_1.getDownloadsFolder)(product),
43
+ });
44
+ const _localRevisions = await (0, BrowserFetcher_1.localRevisions)((0, BrowserFetcher_1.getDownloadsFolder)(product), product, (0, BrowserFetcher_1.getPlatform)(product));
45
+ console.log(`${supportedProducts[product]} (${revisionInfo.revision}) downloaded to ${revisionInfo.folderPath}`);
46
+ await Promise.all(_localRevisions
47
+ .filter((__revision) => {
48
+ return __revision !== revisionInfo.revision;
49
+ })
50
+ .map((__revision) => {
51
+ return (0, BrowserFetcher_1.removeBrowser)(__revision, (0, BrowserFetcher_1.getFolderPath)(revision, (0, BrowserFetcher_1.getDownloadsFolder)(product), (0, BrowserFetcher_1.getPlatform)(product)));
52
+ }));
53
+ }
54
+ exports.downloadBrowser = downloadBrowser;
55
+ function toMegabytes(bytes) {
56
+ const mb = bytes / 1024 / 1024;
57
+ return `${Math.round(mb * 10) / 10} Mb`;
58
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright 2020 Google Inc. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ type Revisions = Readonly<{
17
+ readonly chromium: string;
18
+ }>;
19
+ export declare const PUPPETEER_REVISIONS: Revisions;
20
+ export {};
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright 2020 Google Inc. All rights reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.PUPPETEER_REVISIONS = void 0;
19
+ exports.PUPPETEER_REVISIONS = {
20
+ chromium: '1002410',
21
+ };
@@ -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
@@ -6,6 +6,7 @@ export declare const BrowserSafeApis: {
6
6
  getValidCrfRanges: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => [number, number];
7
7
  isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
8
8
  proResProfileOptions: readonly ["4444-xq", "4444", "hq", "standard", "light", "proxy"];
9
+ x264PresetOptions: readonly ["ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo"];
9
10
  validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
10
11
  DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
11
12
  supportedAudioCodecs: {
@@ -193,14 +194,160 @@ export declare const BrowserSafeApis: {
193
194
  preferLossless: boolean;
194
195
  }) => void;
195
196
  options: {
196
- scaleOption: import(".").RemotionOption;
197
- crfOption: import(".").RemotionOption;
198
- jpegQualityOption: import(".").RemotionOption;
199
- videoBitrate: import(".").RemotionOption;
200
- audioBitrateOption: import(".").RemotionOption;
201
- enforceAudioOption: import(".").RemotionOption;
202
- muteOption: import(".").RemotionOption;
203
- 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
+ }];
204
351
  };
205
352
  codecSupportsCrf: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
206
353
  codecSupportsVideoBitrate: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif") => boolean;
package/dist/client.js CHANGED
@@ -13,12 +13,15 @@ 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");
19
21
  const pixel_format_1 = require("./pixel-format");
20
22
  const prores_profile_1 = require("./prores-profile");
21
23
  const validate_output_filename_1 = require("./validate-output-filename");
24
+ const x264_preset_1 = require("./x264-preset");
22
25
  exports.BrowserSafeApis = {
23
26
  getFileExtensionFromCodec: get_extension_from_codec_1.getFileExtensionFromCodec,
24
27
  validCodecs: codec_1.validCodecs,
@@ -27,6 +30,7 @@ exports.BrowserSafeApis = {
27
30
  getValidCrfRanges: crf_1.getValidCrfRanges,
28
31
  isAudioCodec: is_audio_codec_1.isAudioCodec,
29
32
  proResProfileOptions: prores_profile_1.proResProfileOptions,
33
+ x264PresetOptions: x264_preset_1.x264PresetOptions,
30
34
  validPixelFormats: pixel_format_1.validPixelFormats,
31
35
  DEFAULT_PIXEL_FORMAT: pixel_format_1.DEFAULT_PIXEL_FORMAT,
32
36
  supportedAudioCodecs: audio_codec_1.supportedAudioCodecs,
@@ -43,7 +47,9 @@ exports.BrowserSafeApis = {
43
47
  enforceAudioOption: enforce_audio_1.enforceAudioOption,
44
48
  muteOption: mute_1.muteOption,
45
49
  videoCodecOption: video_codec_1.videoCodecOption,
50
+ offthreadVideoCacheSizeInBytesOption: offthreadvideo_cache_size_1.offthreadVideoCacheSizeInBytesOption,
46
51
  },
52
+ optionsMap: options_map_1.optionsMap,
47
53
  codecSupportsCrf: codec_supports_media_1.codecSupportsCrf,
48
54
  codecSupportsVideoBitrate: codec_supports_media_1.codecSupportsVideoBitrate,
49
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
  });