@remotion/renderer 4.0.532 → 4.0.534

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 (176) hide show
  1. package/dist/aac-priming.js +6 -2
  2. package/dist/browser/BrowserFetcher.d.ts +7 -1
  3. package/dist/browser/BrowserFetcher.js +33 -13
  4. package/dist/browser/Connection.js +5 -17
  5. package/dist/browser/DOMWorld.js +19 -13
  6. package/dist/browser/devtools-commands.d.ts +13 -1
  7. package/dist/browser/devtools-types.d.ts +62 -0
  8. package/dist/browser/get-chrome-download-url.d.ts +1 -1
  9. package/dist/browser/get-chrome-download-url.js +19 -33
  10. package/dist/can-use-parallel-encoding.d.ts +0 -1
  11. package/dist/can-use-parallel-encoding.js +10 -10
  12. package/dist/client.d.ts +93 -4
  13. package/dist/client.js +2 -0
  14. package/dist/compress-assets.d.ts +1 -1
  15. package/dist/compress-assets.js +1 -1
  16. package/dist/cycle-browser-tabs.js +9 -1
  17. package/dist/ensure-browser.js +30 -6
  18. package/dist/esm/client.mjs +943 -796
  19. package/dist/esm/index.mjs +4113 -2997
  20. package/dist/esm/pure.mjs +33 -9
  21. package/dist/file-extensions.js +4 -1
  22. package/dist/get-mp4-brand.d.ts +1 -0
  23. package/dist/get-mp4-brand.js +21 -0
  24. package/dist/image-format.d.ts +1 -0
  25. package/dist/image-format.js +8 -4
  26. package/dist/index.d.ts +14 -1
  27. package/dist/index.js +4 -0
  28. package/dist/memory/from-macos-sysctl.d.ts +1 -0
  29. package/dist/memory/from-macos-sysctl.js +50 -0
  30. package/dist/memory/from-proc-meminfo.d.ts +1 -1
  31. package/dist/memory/from-proc-meminfo.js +7 -4
  32. package/dist/memory/get-available-memory.js +29 -21
  33. package/dist/mux-video-and-audio.js +8 -2
  34. package/dist/next-frame-to-render.d.ts +3 -7
  35. package/dist/next-frame-to-render.js +3 -22
  36. package/dist/open-browser.js +1 -0
  37. package/dist/options/allow-html-in-canvas.js +1 -1
  38. package/dist/options/api-key.js +1 -1
  39. package/dist/options/ask-ai.js +1 -1
  40. package/dist/options/audio-bitrate.js +1 -1
  41. package/dist/options/audio-codec.js +12 -6
  42. package/dist/options/beep-on-finish.js +1 -1
  43. package/dist/options/benchmark-concurrencies.js +1 -1
  44. package/dist/options/binaries-directory.js +1 -1
  45. package/dist/options/browser-executable.js +1 -1
  46. package/dist/options/browser.js +1 -1
  47. package/dist/options/bundle-cache.js +1 -1
  48. package/dist/options/canvas-tabs.js +1 -1
  49. package/dist/options/chrome-mode.js +1 -1
  50. package/dist/options/color-space.js +1 -1
  51. package/dist/options/concurrency.js +1 -1
  52. package/dist/options/config.js +1 -1
  53. package/dist/options/crf.js +1 -1
  54. package/dist/options/cross-site-isolation.js +1 -1
  55. package/dist/options/dark-mode.js +1 -1
  56. package/dist/options/default-coding-agent.js +1 -1
  57. package/dist/options/default-editor.js +1 -1
  58. package/dist/options/delete-after.js +1 -1
  59. package/dist/options/disable-git-source.js +1 -1
  60. package/dist/options/disable-shared-memory-capture.d.ts +16 -0
  61. package/dist/options/disable-shared-memory-capture.js +29 -0
  62. package/dist/options/disable-web-security.js +1 -1
  63. package/dist/options/disallow-parallel-encoding.js +1 -1
  64. package/dist/options/enable-cancellation.js +1 -1
  65. package/dist/options/enable-lambda-insights.js +1 -1
  66. package/dist/options/enable-multiprocess-on-linux.js +1 -1
  67. package/dist/options/encoding-buffer-size.js +1 -1
  68. package/dist/options/encoding-max-rate.js +1 -1
  69. package/dist/options/enforce-audio.js +1 -1
  70. package/dist/options/env-file.js +1 -1
  71. package/dist/options/every-nth-frame.js +1 -1
  72. package/dist/options/experimental-keep-audio-context-alive.js +1 -1
  73. package/dist/options/experimental-tracks.d.ts +18 -0
  74. package/dist/options/experimental-tracks.js +42 -0
  75. package/dist/options/folder-expiry.js +1 -1
  76. package/dist/options/for-seamless-aac-concatenation.js +1 -1
  77. package/dist/options/force-new-studio.js +1 -1
  78. package/dist/options/frames.js +1 -1
  79. package/dist/options/gl.js +1 -1
  80. package/dist/options/gop-size.js +1 -1
  81. package/dist/options/hardware-acceleration.js +1 -1
  82. package/dist/options/headless.js +1 -1
  83. package/dist/options/ignore-certificate-errors.js +1 -1
  84. package/dist/options/image-sequence-pattern.d.ts +4 -1
  85. package/dist/options/image-sequence-pattern.js +9 -3
  86. package/dist/options/image-sequence.js +1 -1
  87. package/dist/options/index.d.ts +39 -2
  88. package/dist/options/index.js +4 -0
  89. package/dist/options/interactivity.js +1 -1
  90. package/dist/options/ipv4.js +1 -1
  91. package/dist/options/is-production.js +1 -1
  92. package/dist/options/jpeg-quality.js +5 -2
  93. package/dist/options/keyboard-shortcuts.js +1 -1
  94. package/dist/options/latency-hint.js +1 -1
  95. package/dist/options/license-key.js +1 -1
  96. package/dist/options/log-level.js +1 -1
  97. package/dist/options/metadata.js +1 -1
  98. package/dist/options/mute.js +1 -1
  99. package/dist/options/no-open.js +1 -1
  100. package/dist/options/number-of-gif-loops.js +1 -1
  101. package/dist/options/number-of-shared-audio-tags.js +1 -1
  102. package/dist/options/offthreadvideo-cache-size.js +1 -1
  103. package/dist/options/offthreadvideo-threads.js +1 -1
  104. package/dist/options/on-browser-download.js +1 -1
  105. package/dist/options/options-map.d.ts +52 -1
  106. package/dist/options/options-map.js +4 -0
  107. package/dist/options/out-dir.js +1 -1
  108. package/dist/options/override-duration.js +1 -1
  109. package/dist/options/override-fps.js +1 -1
  110. package/dist/options/override-height.js +1 -1
  111. package/dist/options/override-width.js +1 -1
  112. package/dist/options/overwrite.js +1 -1
  113. package/dist/options/package-manager.js +1 -1
  114. package/dist/options/pixel-format.js +1 -1
  115. package/dist/options/port.js +1 -1
  116. package/dist/options/prefer-lossless.js +1 -1
  117. package/dist/options/preview-sample-rate.js +1 -1
  118. package/dist/options/props.js +1 -1
  119. package/dist/options/prores-profile.js +1 -1
  120. package/dist/options/public-dir.js +1 -1
  121. package/dist/options/public-license-key.js +1 -1
  122. package/dist/options/public-path.js +1 -1
  123. package/dist/options/repro.js +1 -1
  124. package/dist/options/rspack.d.ts +1 -1
  125. package/dist/options/rspack.js +1 -1
  126. package/dist/options/runs.js +1 -1
  127. package/dist/options/sample-rate.js +1 -1
  128. package/dist/options/scale.js +1 -1
  129. package/dist/options/separate-audio.js +1 -1
  130. package/dist/options/skip-skills.js +1 -1
  131. package/dist/options/still-frame.js +1 -1
  132. package/dist/options/still-image-format.js +1 -1
  133. package/dist/options/throw-if-site-exists.js +1 -1
  134. package/dist/options/timeout.js +1 -1
  135. package/dist/options/user-agent.js +1 -1
  136. package/dist/options/version-flag.js +1 -1
  137. package/dist/options/video-bitrate.js +1 -1
  138. package/dist/options/video-cache-size.js +1 -1
  139. package/dist/options/video-codec.js +4 -3
  140. package/dist/options/video-image-format.js +6 -2
  141. package/dist/options/webhook-custom-data.js +1 -1
  142. package/dist/options/webpack-poll.js +1 -1
  143. package/dist/options/x264-preset.js +1 -1
  144. package/dist/prespawn-ffmpeg.d.ts +20 -0
  145. package/dist/prespawn-ffmpeg.js +152 -29
  146. package/dist/probe-shared-memory-capture.d.ts +8 -0
  147. package/dist/probe-shared-memory-capture.js +111 -0
  148. package/dist/puppeteer-screenshot.d.ts +3 -1
  149. package/dist/puppeteer-screenshot.js +1 -0
  150. package/dist/pure.d.ts +1 -1
  151. package/dist/remotion-shared-memory-ffmpeg.d.ts +26 -0
  152. package/dist/remotion-shared-memory-ffmpeg.js +312 -0
  153. package/dist/remotion-shared-memory.d.ts +49 -0
  154. package/dist/remotion-shared-memory.js +359 -0
  155. package/dist/render-frame-and-retry-target-close.d.ts +7 -3
  156. package/dist/render-frame-and-retry-target-close.js +23 -4
  157. package/dist/render-frame-with-option-to-reject.d.ts +6 -2
  158. package/dist/render-frame-with-option-to-reject.js +207 -115
  159. package/dist/render-frame.d.ts +6 -6
  160. package/dist/render-frame.js +4 -1
  161. package/dist/render-frames.d.ts +7 -0
  162. package/dist/render-frames.js +20 -18
  163. package/dist/render-media.d.ts +1 -1
  164. package/dist/render-media.js +131 -46
  165. package/dist/render-still.js +1 -0
  166. package/dist/screenshot-background.d.ts +2 -0
  167. package/dist/screenshot-background.js +20 -0
  168. package/dist/screenshot-task.d.ts +4 -2
  169. package/dist/screenshot-task.js +40 -21
  170. package/dist/seek-to-frame.js +1 -1
  171. package/dist/stitch-frames-to-video.js +71 -10
  172. package/dist/take-frame.d.ts +11 -3
  173. package/dist/take-frame.js +10 -8
  174. package/dist/validate-output-filename.d.ts +1 -1
  175. package/dist/validate-output-filename.js +10 -2
  176. package/package.json +13 -13
@@ -6,7 +6,7 @@ const cliFlag = 'separate-audio-to';
6
6
  exports.separateAudioOption = {
7
7
  cliFlag,
8
8
  description: () => `If set, the audio will not be included in the main output but rendered as a separate file at the location you pass. If the render contains no audio, a silent audio file is produced even when enforceAudioTrack is false. The muted option still takes precedence. It is recommended to use an absolute path. If a relative path is passed, it is relative to the Remotion Root.`,
9
- docLink: 'https://remotion.dev/docs/renderer/render-media',
9
+ docLink: 'https://www.remotion.dev/docs/options/separate-audio-to',
10
10
  getValue: ({ commandLine }) => {
11
11
  if (commandLine[cliFlag]) {
12
12
  return {
@@ -8,7 +8,7 @@ exports.skipSkillsOption = {
8
8
  cliFlag,
9
9
  description: () => (jsx_runtime_1.jsx(jsx_runtime_1.Fragment, { children: "Do not update installed Remotion Agent Skills while upgrading Remotion." })),
10
10
  ssrName: null,
11
- docLink: 'https://www.remotion.dev/docs/cli/upgrade#--skip-skills',
11
+ docLink: 'https://www.remotion.dev/docs/options/skip-skills',
12
12
  getValue: ({ commandLine }) => {
13
13
  if (commandLine[cliFlag]) {
14
14
  return {
@@ -19,7 +19,7 @@ exports.stillFrameOption = {
19
19
  ". From v3.2.27, negative values are allowed, with", ' ', jsx_runtime_1.jsx("code", { children: "-1" }),
20
20
  " being the last frame."] })),
21
21
  ssrName: 'frame',
22
- docLink: 'https://www.remotion.dev/docs/cli/still#--frame',
22
+ docLink: 'https://www.remotion.dev/docs/options/frame',
23
23
  getValue: ({ commandLine }) => {
24
24
  if (commandLine[cliFlag] !== undefined) {
25
25
  const frame = Number(commandLine[cliFlag]);
@@ -11,7 +11,7 @@ exports.stillImageFormatOption = {
11
11
  description: () => (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: ["The image format to use when rendering a still. Must be one of", ' ', image_format_1.validStillImageFormats.map((f) => `"${f}"`).join(', '), ". Default:", ' ', jsx_runtime_1.jsx("code", { children: "\"png\"" }),
12
12
  "."] })),
13
13
  ssrName: 'imageFormat',
14
- docLink: 'https://www.remotion.dev/docs/renderer/render-still#imageformat',
14
+ docLink: 'https://www.remotion.dev/docs/options/still-image-format',
15
15
  type: null,
16
16
  getValue: ({ commandLine }) => {
17
17
  if (commandLine[cliFlag] !== undefined) {
@@ -6,7 +6,7 @@ const cliFlag = 'throw-if-site-exists';
6
6
  exports.throwIfSiteExistsOption = {
7
7
  cliFlag,
8
8
  description: () => `Prevents accidential update of an existing site. If there are any files in the subfolder where the site should be placed, the function will throw.`,
9
- docLink: 'https://remotion.dev/docs/lambda/deploy-site',
9
+ docLink: 'https://www.remotion.dev/docs/options/throw-if-site-exists',
10
10
  getValue: ({ commandLine }) => {
11
11
  if (commandLine[cliFlag]) {
12
12
  return {
@@ -19,7 +19,7 @@ exports.delayRenderTimeoutInMillisecondsOption = {
19
19
  jsx_runtime_1.jsx("code", { children: "30000" })
20
20
  ] })),
21
21
  ssrName: 'timeoutInMilliseconds',
22
- docLink: 'https://www.remotion.dev/docs/timeout',
22
+ docLink: 'https://www.remotion.dev/docs/options/timeout',
23
23
  type: 0,
24
24
  getValue: ({ commandLine }) => {
25
25
  if (commandLine[cliFlag] !== undefined) {
@@ -9,7 +9,7 @@ exports.userAgentOption = {
9
9
  cliFlag,
10
10
  description: () => (jsx_runtime_1.jsx(jsx_runtime_1.Fragment, { children: "Lets you set a custom user agent that the headless Chrome browser assumes." })),
11
11
  ssrName: 'userAgent',
12
- docLink: 'https://www.remotion.dev/docs/chromium-flags#--user-agent',
12
+ docLink: 'https://www.remotion.dev/docs/options/user-agent',
13
13
  type: null,
14
14
  getValue: ({ commandLine }) => {
15
15
  if (commandLine[cliFlag] !== undefined) {
@@ -8,7 +8,7 @@ exports.versionFlagOption = {
8
8
  cliFlag,
9
9
  description: () => (jsx_runtime_1.jsx(jsx_runtime_1.Fragment, { children: "Install a specific version. Also enables downgrading to an older version." })),
10
10
  ssrName: null,
11
- docLink: 'https://www.remotion.dev/docs/cli/upgrade#--version',
11
+ docLink: 'https://www.remotion.dev/docs/options/version',
12
12
  getValue: ({ commandLine }) => {
13
13
  if (commandLine[cliFlag] !== undefined) {
14
14
  return {
@@ -15,7 +15,7 @@ exports.videoBitrateOption = {
15
15
  jsx_runtime_1.jsx("code", { children: "1M" }),
16
16
  " for 1 Mbps."] })),
17
17
  ssrName: 'videoBitrate',
18
- docLink: 'https://www.remotion.dev/docs/renderer/render-media#videobitrate',
18
+ docLink: 'https://www.remotion.dev/docs/options/video-bitrate',
19
19
  type: '',
20
20
  getValue: ({ commandLine }) => {
21
21
  if (commandLine[cliFlag] !== undefined) {
@@ -19,7 +19,7 @@ exports.mediaCacheSizeInBytesOption = {
19
19
  jsx_runtime_1.jsx("br", {}),
20
20
  "The default is half of the available system memory when the render starts."] })),
21
21
  ssrName: 'mediaCacheSizeInBytes',
22
- docLink: 'https://www.remotion.dev/docs/media/cache',
22
+ docLink: 'https://www.remotion.dev/docs/options/media-cache-size-in-bytes',
23
23
  type: 0,
24
24
  getValue: ({ commandLine }) => {
25
25
  if (commandLine[cliFlag] !== undefined) {
@@ -25,9 +25,10 @@ const deriveCodecsFromFilename = (extension) => {
25
25
  if (extension === null) {
26
26
  return { possible: [], default: null };
27
27
  }
28
+ const normalizedExtension = extension.toLowerCase();
28
29
  return {
29
- default: (_a = get_extension_from_codec_1.defaultCodecsForFileExtension[extension]) !== null && _a !== void 0 ? _a : null,
30
- possible: (_b = (0, get_extension_from_codec_1.makeFileExtensionMap)()[extension]) !== null && _b !== void 0 ? _b : [],
30
+ default: (_a = get_extension_from_codec_1.defaultCodecsForFileExtension[normalizedExtension]) !== null && _a !== void 0 ? _a : null,
31
+ possible: (_b = (0, get_extension_from_codec_1.makeFileExtensionMap)()[normalizedExtension]) !== null && _b !== void 0 ? _b : [],
31
32
  };
32
33
  };
33
34
  const cliFlag = 'codec';
@@ -36,7 +37,7 @@ exports.videoCodecOption = {
36
37
  cliFlag,
37
38
  description: () => (jsx_runtime_1.jsx(jsx_runtime_1.Fragment, { children: "H264 works well in most cases, but sometimes it's worth going for a different codec. WebM achieves higher compression but is slower to render. WebM, GIF and ProRes support transparency." })),
38
39
  ssrName: 'codec',
39
- docLink: 'https://www.remotion.dev/docs/encoding/#choosing-a-codec',
40
+ docLink: 'https://www.remotion.dev/docs/options/codec',
40
41
  type: '',
41
42
  getValue: ({ commandLine }, { compositionCodec, configFile, downloadName, outName, uiCodec, }) => {
42
43
  if (uiCodec) {
@@ -10,9 +10,13 @@ exports.videoImageFormatOption = {
10
10
  name: 'Video Image Format',
11
11
  cliFlag,
12
12
  description: () => (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: ["The image format to use when rendering frames for a video. Must be one of", ' ', image_format_1.validVideoImageFormats.map((f) => `"${f}"`).join(', '), ". Default:", ' ', jsx_runtime_1.jsx("code", { children: "\"jpeg\"" }),
13
- ". JPEG is faster, but does not support transparency."] })),
13
+ ". JPEG is faster, but does not support transparency.",
14
+ jsx_runtime_1.jsx("br", {}),
15
+ "When ",
16
+ jsx_runtime_1.jsx("a", { href: "/docs/shared-memory-capture", children: "shared-memory capture" }),
17
+ " is active, this option has no effect. The output pixel format determines transparency."] })),
14
18
  ssrName: 'imageFormat',
15
- docLink: 'https://www.remotion.dev/docs/renderer/render-media#imageformat',
19
+ docLink: 'https://www.remotion.dev/docs/options/video-image-format',
16
20
  type: null,
17
21
  getValue: ({ commandLine }, options) => {
18
22
  if (options === null || options === void 0 ? void 0 : options.uiVideoImageFormat) {
@@ -10,7 +10,7 @@ exports.webhookCustomDataOption = {
10
10
  ? 'Alternatively, pass a file path pointing to a JSON file'
11
11
  : null] })),
12
12
  ssrName: 'customData',
13
- docLink: 'https://www.remotion.dev/docs/lambda/webhooks',
13
+ docLink: 'https://www.remotion.dev/docs/options/webhook-custom-data',
14
14
  type: {},
15
15
  getValue: () => {
16
16
  throw new Error('Option resolution not implemented');
@@ -9,7 +9,7 @@ exports.webpackPollOption = {
9
9
  cliFlag,
10
10
  description: () => (jsx_runtime_1.jsx(jsx_runtime_1.Fragment, { children: "Enables Webpack polling instead of the file system event listeners for hot reloading. This is useful if you are inside a virtual machine or have a remote file system. Pass a value in milliseconds." })),
11
11
  ssrName: null,
12
- docLink: 'https://www.remotion.dev/docs/config#setwebpackpollinginmilliseconds',
12
+ docLink: 'https://www.remotion.dev/docs/options/webpack-poll',
13
13
  getValue: ({ commandLine }) => {
14
14
  if (commandLine[cliFlag] !== undefined) {
15
15
  const val = commandLine[cliFlag];
@@ -59,7 +59,7 @@ exports.x264Option = {
59
59
  jsx_runtime_1.jsx("code", { children: DEFAULT_PRESET })
60
60
  ] })),
61
61
  ssrName: 'x264Preset',
62
- docLink: 'https://www.remotion.dev/docs/renderer/render-media',
62
+ docLink: 'https://www.remotion.dev/docs/options/x264-preset',
63
63
  type: 'fast',
64
64
  getValue: ({ commandLine }) => {
65
65
  const value = commandLine[cliFlag];
@@ -9,6 +9,7 @@ import type { CancelSignal } from './make-cancel-signal';
9
9
  import type { ColorSpace } from './options/color-space';
10
10
  import type { X264Preset } from './options/x264-preset';
11
11
  import type { PixelFormat } from './pixel-format';
12
+ import type { RemotionRawFrame } from './remotion-shared-memory';
12
13
  type RunningStatus = {
13
14
  type: 'running';
14
15
  } | {
@@ -44,10 +45,29 @@ type PreStitcherOptions = {
44
45
  binariesDirectory: string | null;
45
46
  hardwareAcceleration: HardwareAccelerationOption;
46
47
  onLog: OnLog;
48
+ inputMode: 'encoded-image' | 'remotion-shared-memory';
49
+ remotionSharedMemoryPoolDirectory: string | null;
47
50
  };
51
+ export type RemotionSharedMemoryFfmpegSupport = {
52
+ sharedMemory: boolean;
53
+ filePools: boolean;
54
+ };
55
+ export declare const probeRemotionSharedMemoryFfmpegSupport: ({ binariesDirectory, indent, logLevel, }: {
56
+ binariesDirectory: string | null;
57
+ indent: boolean;
58
+ logLevel: "error" | "info" | "trace" | "verbose" | "warn";
59
+ }) => Promise<RemotionSharedMemoryFfmpegSupport>;
48
60
  export declare const prespawnFfmpeg: (options: PreStitcherOptions) => {
49
61
  task: import("execa").ExecaChildProcess<string>;
50
62
  getLogs: () => string;
51
63
  getExitStatus: () => RunningStatus;
64
+ writeFrame: ({ frame, pts, }: {
65
+ frame: Buffer | RemotionRawFrame;
66
+ pts: number;
67
+ }) => Promise<{
68
+ waitForAck: Promise<void>;
69
+ }>;
70
+ finishInput: () => Promise<void>;
71
+ abortInput: (error: Error) => void;
52
72
  };
53
73
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.prespawnFfmpeg = void 0;
3
+ exports.prespawnFfmpeg = exports.probeRemotionSharedMemoryFfmpegSupport = void 0;
4
4
  const call_ffmpeg_1 = require("./call-ffmpeg");
5
5
  const codec_1 = require("./codec");
6
6
  const ffmpeg_args_1 = require("./ffmpeg-args");
@@ -11,8 +11,66 @@ const from_lambda_env_1 = require("./memory/from-lambda-env");
11
11
  const parse_ffmpeg_progress_1 = require("./parse-ffmpeg-progress");
12
12
  const pixel_format_1 = require("./pixel-format");
13
13
  const probe_encoder_1 = require("./probe-encoder");
14
+ const remotion_shared_memory_ffmpeg_1 = require("./remotion-shared-memory-ffmpeg");
14
15
  const validate_1 = require("./validate");
15
16
  const validate_even_dimensions_with_codec_1 = require("./validate-even-dimensions-with-codec");
17
+ const write_with_backpressure_1 = require("./write-with-backpressure");
18
+ const remotionSharedMemorySupport = new Map();
19
+ const probeRemotionSharedMemoryFfmpegSupport = ({ binariesDirectory, indent, logLevel, }) => {
20
+ const key = binariesDirectory !== null && binariesDirectory !== void 0 ? binariesDirectory : '<bundled>';
21
+ const cached = remotionSharedMemorySupport.get(key);
22
+ if (cached) {
23
+ return cached;
24
+ }
25
+ const result = (async () => {
26
+ try {
27
+ const devices = await (0, call_ffmpeg_1.callFf)({
28
+ bin: 'ffmpeg',
29
+ args: ['-hide_banner', '-devices'],
30
+ indent,
31
+ logLevel,
32
+ binariesDirectory,
33
+ cancelSignal: undefined,
34
+ });
35
+ if (!/(?:^|\n)\s*D\s{2}remotionshm(?:\s|$)/.test(`${devices.stdout}\n${devices.stderr}`)) {
36
+ return { sharedMemory: false, filePools: false };
37
+ }
38
+ const help = await (0, call_ffmpeg_1.callFf)({
39
+ bin: 'ffmpeg',
40
+ args: ['-hide_banner', '-h', 'demuxer=remotionshm'],
41
+ indent,
42
+ logLevel,
43
+ binariesDirectory,
44
+ cancelSignal: undefined,
45
+ });
46
+ return {
47
+ sharedMemory: true,
48
+ filePools: /(?:^|\n)\s*-pool_dir\s/.test(`${help.stdout}\n${help.stderr}`),
49
+ };
50
+ }
51
+ catch (_a) {
52
+ return { sharedMemory: false, filePools: false };
53
+ }
54
+ })();
55
+ remotionSharedMemorySupport.set(key, result);
56
+ return result;
57
+ };
58
+ exports.probeRemotionSharedMemoryFfmpegSupport = probeRemotionSharedMemoryFfmpegSupport;
59
+ const fpsAsFraction = (fps) => {
60
+ const denominator = 1000000;
61
+ let numerator = Math.round(fps * denominator);
62
+ let divisor = denominator;
63
+ let left = numerator;
64
+ let right = divisor;
65
+ while (right !== 0) {
66
+ const remainder = left % right;
67
+ left = right;
68
+ right = remainder;
69
+ }
70
+ numerator /= left;
71
+ divisor /= left;
72
+ return `${numerator}/${divisor}`;
73
+ };
16
74
  const prespawnFfmpeg = (options) => {
17
75
  var _a;
18
76
  var _b, _c;
@@ -43,34 +101,59 @@ const prespawnFfmpeg = (options) => {
43
101
  encodingBufferSize: options.encodingBufferSize,
44
102
  onLog: options.onLog,
45
103
  });
104
+ const encodingArgs = (0, ffmpeg_args_1.generateFfmpegArgs)({
105
+ hasPreencoded: false,
106
+ proResProfileName,
107
+ pixelFormat,
108
+ x264Preset: options.x264Preset,
109
+ gopSize: options.gopSize,
110
+ codec,
111
+ crf: options.crf,
112
+ videoBitrate: options.videoBitrate,
113
+ encodingMaxRate: options.encodingMaxRate,
114
+ encodingBufferSize: options.encodingBufferSize,
115
+ colorSpace: options.colorSpace,
116
+ hardwareAcceleration: resolvedHardwareAcceleration,
117
+ indent: options.indent,
118
+ logLevel: options.logLevel,
119
+ cpuCount: (0, get_cpu_count_1.getCpuCount)(),
120
+ lambdaMemoryInBytes: (0, from_lambda_env_1.getMaxLambdaMemory)(),
121
+ });
122
+ const encodingArgsWithOwnedPixels = options.inputMode === 'remotion-shared-memory'
123
+ ? encodingArgs.some(([flag]) => flag === '-vf')
124
+ ? encodingArgs.map((args) => args[0] === '-vf' ? ['-vf', `copy,${args[1]}`] : args)
125
+ : [...encodingArgs, ['-vf', 'copy']]
126
+ : encodingArgs;
46
127
  const ffmpegArgs = [
47
- ['-r', options.fps],
48
- ...[
49
- ['-f', 'image2pipe'],
50
- ['-s', `${options.width}x${options.height}`],
51
- // If scale is very small (like 0.1), FFMPEG cannot figure out the image
52
- // format on it's own and we need to hint the format
53
- ['-vcodec', options.imageFormat === 'jpeg' ? 'mjpeg' : 'png'],
54
- ['-i', '-'],
55
- ],
56
- ...(0, ffmpeg_args_1.generateFfmpegArgs)({
57
- hasPreencoded: false,
58
- proResProfileName,
59
- pixelFormat,
60
- x264Preset: options.x264Preset,
61
- gopSize: options.gopSize,
62
- codec,
63
- crf: options.crf,
64
- videoBitrate: options.videoBitrate,
65
- encodingMaxRate: options.encodingMaxRate,
66
- encodingBufferSize: options.encodingBufferSize,
67
- colorSpace: options.colorSpace,
68
- hardwareAcceleration: resolvedHardwareAcceleration,
69
- indent: options.indent,
70
- logLevel: options.logLevel,
71
- cpuCount: (0, get_cpu_count_1.getCpuCount)(),
72
- lambdaMemoryInBytes: (0, from_lambda_env_1.getMaxLambdaMemory)(),
73
- }),
128
+ ...(options.inputMode === 'remotion-shared-memory'
129
+ ? [
130
+ ['-nostdin'],
131
+ ['-xerror'],
132
+ ['-nofind_stream_info'],
133
+ ['-threads:v', '1'],
134
+ ['-f', 'remotionshm'],
135
+ ['-video_size', `${options.width}x${options.height}`],
136
+ ['-framerate', fpsAsFraction(options.fps)],
137
+ ['-control_fd', '3'],
138
+ ['-ack_fd', '4'],
139
+ options.remotionSharedMemoryPoolDirectory === null
140
+ ? null
141
+ : ['-pool_dir', options.remotionSharedMemoryPoolDirectory],
142
+ ['-i', 'remotion'],
143
+ ]
144
+ : [
145
+ ['-r', options.fps],
146
+ ['-f', 'image2pipe'],
147
+ ['-s', `${options.width}x${options.height}`],
148
+ // If scale is very small (like 0.1), FFMPEG cannot figure out the image
149
+ // format on its own and we need to hint the format.
150
+ ['-vcodec', options.imageFormat === 'jpeg' ? 'mjpeg' : 'png'],
151
+ ['-i', '-'],
152
+ ]),
153
+ ...encodingArgsWithOwnedPixels,
154
+ options.inputMode === 'remotion-shared-memory'
155
+ ? ['-fps_mode', 'passthrough']
156
+ : null,
74
157
  '-y',
75
158
  options.outputLocation,
76
159
  ];
@@ -95,7 +178,16 @@ const prespawnFfmpeg = (options) => {
95
178
  logLevel: options.logLevel,
96
179
  binariesDirectory: options.binariesDirectory,
97
180
  cancelSignal: options.signal,
181
+ options: options.inputMode === 'remotion-shared-memory'
182
+ ? { stdio: ['ignore', 'pipe', 'pipe', 'pipe', 'pipe'] }
183
+ : undefined,
98
184
  });
185
+ const remotionSharedMemory = options.inputMode === 'remotion-shared-memory'
186
+ ? (0, remotion_shared_memory_ffmpeg_1.createRemotionSharedMemoryFfmpegBridge)({
187
+ control: task.stdio[3],
188
+ acknowledgements: task.stdio[4],
189
+ })
190
+ : null;
99
191
  let ffmpegOutput = '';
100
192
  (_a = task.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
101
193
  const str = data.toString();
@@ -126,6 +218,37 @@ const prespawnFfmpeg = (options) => {
126
218
  };
127
219
  }
128
220
  });
129
- return { task, getLogs: () => ffmpegOutput, getExitStatus: () => exitCode };
221
+ return {
222
+ task,
223
+ getLogs: () => ffmpegOutput,
224
+ getExitStatus: () => exitCode,
225
+ writeFrame: async ({ frame, pts, }) => {
226
+ if (remotionSharedMemory) {
227
+ if (Buffer.isBuffer(frame)) {
228
+ throw new Error('Expected a Remotion shared-memory frame.');
229
+ }
230
+ return remotionSharedMemory.writeFrame({ frame, pts });
231
+ }
232
+ if (!Buffer.isBuffer(frame)) {
233
+ throw new Error('Expected an encoded image frame.');
234
+ }
235
+ if (!task.stdin) {
236
+ throw new Error('FFmpeg stdin is not available.');
237
+ }
238
+ await (0, write_with_backpressure_1.writeWithBackpressure)({ data: frame, writable: task.stdin });
239
+ return { waitForAck: Promise.resolve() };
240
+ },
241
+ finishInput: async () => {
242
+ var _a;
243
+ if (remotionSharedMemory) {
244
+ await remotionSharedMemory.finish();
245
+ return;
246
+ }
247
+ (_a = task.stdin) === null || _a === void 0 ? void 0 : _a.end();
248
+ },
249
+ abortInput: (error) => {
250
+ remotionSharedMemory === null || remotionSharedMemory === void 0 ? void 0 : remotionSharedMemory.fail(error);
251
+ },
252
+ };
130
253
  };
131
254
  exports.prespawnFfmpeg = prespawnFfmpeg;
@@ -0,0 +1,8 @@
1
+ import type { ChromiumOptions } from './open-browser';
2
+ export declare const probeSharedMemoryCapture: ({ browserExecutable, chromeMode, chromiumOptions, binariesDirectory, logLevel, }: {
3
+ browserExecutable: string | null;
4
+ chromeMode: "chrome-for-testing" | "headless-shell";
5
+ chromiumOptions: ChromiumOptions;
6
+ binariesDirectory: string | null;
7
+ logLevel: "error" | "info" | "trace" | "verbose" | "warn";
8
+ }) => Promise<boolean>;
@@ -0,0 +1,111 @@
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.probeSharedMemoryCapture = void 0;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_os_1 = __importDefault(require("node:os"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const get_local_browser_executable_1 = require("./get-local-browser-executable");
11
+ const open_browser_1 = require("./open-browser");
12
+ const prespawn_ffmpeg_1 = require("./prespawn-ffmpeg");
13
+ const remotion_shared_memory_1 = require("./remotion-shared-memory");
14
+ const probes = new Map();
15
+ const probeSharedMemoryCapture = async ({ browserExecutable, chromeMode, chromiumOptions, binariesDirectory, logLevel, }) => {
16
+ // Opening the render modal should not download a browser.
17
+ let executablePath;
18
+ let executableStat;
19
+ try {
20
+ executablePath = (0, get_local_browser_executable_1.getLocalBrowserExecutable)({
21
+ preferredBrowserExecutable: browserExecutable,
22
+ chromeMode,
23
+ indent: false,
24
+ logLevel,
25
+ });
26
+ executableStat = node_fs_1.default.statSync(executablePath);
27
+ }
28
+ catch (_a) {
29
+ return false;
30
+ }
31
+ const key = JSON.stringify({
32
+ executablePath,
33
+ mtime: executableStat.mtimeMs,
34
+ ctime: executableStat.ctimeMs,
35
+ size: executableStat.size,
36
+ chromeMode,
37
+ chromiumOptions,
38
+ binariesDirectory,
39
+ backend: (0, remotion_shared_memory_1.getPreferredRemotionSharedMemoryBackend)(),
40
+ });
41
+ const cached = probes.get(key);
42
+ if (cached) {
43
+ return cached;
44
+ }
45
+ const probe = (async () => {
46
+ const support = await (0, prespawn_ffmpeg_1.probeRemotionSharedMemoryFfmpegSupport)({
47
+ binariesDirectory,
48
+ indent: false,
49
+ logLevel,
50
+ });
51
+ if (!support.sharedMemory) {
52
+ return false;
53
+ }
54
+ const browser = await (0, open_browser_1.openBrowser)('chrome', {
55
+ browserExecutable: executablePath,
56
+ chromeMode,
57
+ chromiumOptions: { ...chromiumOptions, headless: true },
58
+ forceDeviceScaleFactor: 1,
59
+ logLevel,
60
+ });
61
+ let backingDirectory = null;
62
+ let capture = null;
63
+ try {
64
+ backingDirectory = support.filePools
65
+ ? node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'remotion-shm-probe-'))
66
+ : null;
67
+ capture = new remotion_shared_memory_1.RemotionSharedMemoryCapture({
68
+ width: 16,
69
+ height: 16,
70
+ indent: false,
71
+ logLevel,
72
+ backingDirectory,
73
+ });
74
+ const page = await browser.newPage({
75
+ context: () => null,
76
+ logLevel,
77
+ indent: false,
78
+ pageIndex: 0,
79
+ onBrowserLog: null,
80
+ onLog: () => undefined,
81
+ });
82
+ await capture.initializePages([page]);
83
+ return capture.isSupported();
84
+ }
85
+ finally {
86
+ try {
87
+ await (capture === null || capture === void 0 ? void 0 : capture.dispose());
88
+ }
89
+ finally {
90
+ try {
91
+ await browser.close({ silent: true });
92
+ }
93
+ finally {
94
+ if (backingDirectory !== null) {
95
+ node_fs_1.default.rmSync(backingDirectory, { recursive: true, force: true });
96
+ }
97
+ }
98
+ }
99
+ }
100
+ })();
101
+ probes.set(key, probe);
102
+ try {
103
+ return await probe;
104
+ }
105
+ catch (_b) {
106
+ // Keep the screenshot controls if probing fails, and retry next time.
107
+ probes.delete(key);
108
+ return false;
109
+ }
110
+ };
111
+ exports.probeSharedMemoryCapture = probeSharedMemoryCapture;
@@ -1,4 +1,5 @@
1
1
  import type { Page } from './browser/BrowserPage';
2
+ import type { CapturedFrame, RemotionSharedMemoryCapture } from './remotion-shared-memory';
2
3
  export declare const screenshot: (options: {
3
4
  page: Page;
4
5
  type: "jpeg" | "pdf" | "png" | "webp";
@@ -8,4 +9,5 @@ export declare const screenshot: (options: {
8
9
  width: number;
9
10
  height: number;
10
11
  scale: number;
11
- }) => Promise<Buffer>;
12
+ remotionSharedMemory: RemotionSharedMemoryCapture | null;
13
+ }) => Promise<CapturedFrame>;
@@ -53,6 +53,7 @@ const screenshot = (options) => {
53
53
  path: options.path,
54
54
  jpegQuality: options.type === 'jpeg' ? options.jpegQuality : undefined,
55
55
  scale: options.scale,
56
+ remotionSharedMemory: options.remotionSharedMemory,
56
57
  }));
57
58
  };
58
59
  exports.screenshot = screenshot;
package/dist/pure.d.ts CHANGED
@@ -4,7 +4,7 @@ export declare const NoReactAPIs: {
4
4
  validateOutputFilename: <T extends "aac" | "av1" | "gif" | "h264" | "h264-mkv" | "h264-ts" | "h265" | "mp3" | "prores" | "vp8" | "vp9" | "wav">({ codec, audioCodecSetting, extension, preferLossless, separateAudioTo, }: {
5
5
  codec: T;
6
6
  audioCodecSetting: "aac" | "mp3" | "opus" | "pcm-16" | null;
7
- extension: string;
7
+ extension: string | null;
8
8
  preferLossless: boolean;
9
9
  separateAudioTo: string | null;
10
10
  }) => void;
@@ -0,0 +1,26 @@
1
+ import type { Readable, Writable } from 'node:stream';
2
+ import type { RemotionRawFrame } from './remotion-shared-memory';
3
+ export declare const serializeRemotionSharedMemoryPool: (frame: RemotionRawFrame) => string;
4
+ export declare const serializeRemotionSharedMemoryFrame: ({ frame, pts, }: {
5
+ frame: RemotionRawFrame;
6
+ pts: number;
7
+ }) => string;
8
+ export declare const serializeRemotionSharedMemoryPoolRetirement: (poolId: number) => string;
9
+ export declare const parseRemotionSharedMemoryAck: (line: string) => {
10
+ poolId: number;
11
+ slot: number;
12
+ frameId: string;
13
+ };
14
+ export declare const createRemotionSharedMemoryFfmpegBridge: ({ control, acknowledgements, }: {
15
+ control: Writable;
16
+ acknowledgements: Readable;
17
+ }) => {
18
+ writeFrame: ({ frame, pts, }: {
19
+ frame: RemotionRawFrame;
20
+ pts: number;
21
+ }) => Promise<{
22
+ waitForAck: Promise<void>;
23
+ }>;
24
+ finish: () => Promise<void>;
25
+ fail: (error: Error) => void;
26
+ };