@remotion/renderer 4.0.0-alpha4 → 4.0.0-alpha6

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 (143) hide show
  1. package/README.md +5 -43
  2. package/dist/assets/download-and-map-assets-to-file.js +6 -6
  3. package/dist/assets/download-file.d.ts +3 -2
  4. package/dist/assets/download-file.js +18 -3
  5. package/dist/assets/download-map.d.ts +0 -26
  6. package/dist/assets/download-map.js +7 -12
  7. package/dist/assets/get-audio-channels.d.ts +1 -2
  8. package/dist/assets/get-audio-channels.js +5 -9
  9. package/dist/assets/read-file.d.ts +1 -1
  10. package/dist/assets/read-file.js +2 -2
  11. package/dist/assets/sanitize-filepath.js +2 -2
  12. package/dist/audio-codec.d.ts +4 -3
  13. package/dist/audio-codec.js +3 -9
  14. package/dist/browser/BrowserFetcher.d.ts +0 -1
  15. package/dist/browser/BrowserFetcher.js +14 -15
  16. package/dist/browser/BrowserRunner.d.ts +1 -1
  17. package/dist/browser/BrowserRunner.js +10 -4
  18. package/dist/browser/FrameManager.js +2 -3
  19. package/dist/browser/LaunchOptions.d.ts +1 -0
  20. package/dist/browser/Launcher.js +6 -5
  21. package/dist/browser/NodeWebSocketTransport.js +4 -4
  22. package/dist/browser/devtools-commands.d.ts +5 -1
  23. package/dist/browser/devtools-types.d.ts +78 -0
  24. package/dist/browser/get-download-destination.js +8 -8
  25. package/dist/browser/is-target-closed-err.d.ts +1 -0
  26. package/dist/browser/is-target-closed-err.js +9 -0
  27. package/dist/call-ffmpeg.d.ts +14 -0
  28. package/dist/call-ffmpeg.js +40 -0
  29. package/dist/check-apple-silicon.js +2 -45
  30. package/dist/client.d.ts +79 -42
  31. package/dist/client.js +27 -1
  32. package/dist/codec-supports-media.d.ts +2 -1
  33. package/dist/codec-supports-media.js +20 -5
  34. package/dist/combine-videos.d.ts +0 -3
  35. package/dist/combine-videos.js +9 -13
  36. package/dist/compositor/compose.d.ts +3 -1
  37. package/dist/compositor/compose.js +41 -18
  38. package/dist/compositor/compositor.d.ts +12 -0
  39. package/dist/compositor/compositor.js +204 -0
  40. package/dist/compositor/get-executable-path.d.ts +1 -1
  41. package/dist/compositor/get-executable-path.js +27 -8
  42. package/dist/compositor/make-nonce.d.ts +1 -0
  43. package/dist/compositor/make-nonce.js +8 -0
  44. package/dist/compositor/payloads.d.ts +34 -7
  45. package/dist/create-ffmpeg-complex-filter.d.ts +5 -5
  46. package/dist/create-ffmpeg-complex-filter.js +2 -4
  47. package/dist/create-ffmpeg-merge-filter.d.ts +2 -5
  48. package/dist/create-ffmpeg-merge-filter.js +2 -10
  49. package/dist/create-silent-audio.d.ts +1 -4
  50. package/dist/create-silent-audio.js +3 -7
  51. package/dist/crf.js +8 -2
  52. package/dist/delete-directory.js +18 -18
  53. package/dist/does-have-m2-bug.js +2 -2
  54. package/dist/ensure-output-directory.js +5 -5
  55. package/dist/ffmpeg-filter-file.js +7 -7
  56. package/dist/file-extensions.d.ts +1 -12
  57. package/dist/file-extensions.js +8 -14
  58. package/dist/find-closest-package-json.js +6 -6
  59. package/dist/get-compositions.d.ts +3 -5
  60. package/dist/get-compositions.js +8 -11
  61. package/dist/get-concurrency.js +3 -3
  62. package/dist/get-extension-from-codec.d.ts +2 -2
  63. package/dist/get-extension-of-filename.js +2 -2
  64. package/dist/get-frame-padded-index.d.ts +2 -1
  65. package/dist/get-local-browser-executable.js +4 -4
  66. package/dist/get-video-threads-flag.js +3 -3
  67. package/dist/guess-extension-for-media.d.ts +1 -3
  68. package/dist/guess-extension-for-media.js +4 -8
  69. package/dist/image-format.d.ts +12 -6
  70. package/dist/image-format.js +16 -13
  71. package/dist/index.d.ts +80 -61
  72. package/dist/index.js +15 -17
  73. package/dist/jpeg-quality.d.ts +1 -0
  74. package/dist/jpeg-quality.js +21 -0
  75. package/dist/merge-audio-track.d.ts +0 -2
  76. package/dist/merge-audio-track.js +5 -12
  77. package/dist/mime-types.js +2 -2
  78. package/dist/offthread-video-server.d.ts +9 -9
  79. package/dist/offthread-video-server.js +65 -58
  80. package/dist/open-browser.d.ts +1 -0
  81. package/dist/open-browser.js +7 -6
  82. package/dist/options/audio-bitrate.d.ts +2 -0
  83. package/dist/options/audio-bitrate.js +11 -0
  84. package/dist/options/crf.d.ts +2 -0
  85. package/dist/options/crf.js +11 -0
  86. package/dist/options/enforce-audio.d.ts +2 -0
  87. package/dist/options/enforce-audio.js +11 -0
  88. package/dist/options/jpeg-quality.d.ts +2 -0
  89. package/dist/options/jpeg-quality.js +11 -0
  90. package/dist/options/mute.d.ts +2 -0
  91. package/dist/options/mute.js +11 -0
  92. package/dist/options/option.d.ts +8 -0
  93. package/dist/options/option.js +2 -0
  94. package/dist/options/scale.d.ts +2 -0
  95. package/dist/options/scale.js +11 -0
  96. package/dist/options/video-bitrate.d.ts +2 -0
  97. package/dist/options/video-bitrate.js +11 -0
  98. package/dist/options/video-codec.d.ts +2 -0
  99. package/dist/options/video-codec.js +11 -0
  100. package/dist/perf.d.ts +1 -1
  101. package/dist/perf.js +9 -7
  102. package/dist/prepare-server.d.ts +3 -4
  103. package/dist/prepare-server.js +9 -9
  104. package/dist/preprocess-audio-track.d.ts +0 -4
  105. package/dist/preprocess-audio-track.js +4 -8
  106. package/dist/prespawn-ffmpeg.d.ts +6 -9
  107. package/dist/prespawn-ffmpeg.js +7 -12
  108. package/dist/prestitcher-memory-usage.d.ts +0 -4
  109. package/dist/prestitcher-memory-usage.js +4 -5
  110. package/dist/prores-profile.d.ts +1 -2
  111. package/dist/prores-profile.js +4 -4
  112. package/dist/provide-screenshot.d.ts +4 -5
  113. package/dist/provide-screenshot.js +2 -2
  114. package/dist/puppeteer-screenshot.d.ts +3 -3
  115. package/dist/puppeteer-screenshot.js +10 -33
  116. package/dist/render-frames.d.ts +13 -25
  117. package/dist/render-frames.js +34 -45
  118. package/dist/render-media.d.ts +16 -18
  119. package/dist/render-media.js +42 -52
  120. package/dist/render-still.d.ts +12 -8
  121. package/dist/render-still.js +30 -18
  122. package/dist/resolve-asset-src.js +2 -2
  123. package/dist/screenshot-dom-element.d.ts +4 -5
  124. package/dist/screenshot-dom-element.js +6 -3
  125. package/dist/screenshot-task.d.ts +2 -3
  126. package/dist/screenshot-task.js +40 -25
  127. package/dist/serve-handler/index.d.ts +1 -1
  128. package/dist/serve-handler/index.js +21 -19
  129. package/dist/serve-handler/is-path-inside.js +3 -3
  130. package/dist/serve-static.d.ts +2 -3
  131. package/dist/serve-static.js +26 -22
  132. package/dist/stitch-frames-to-video.d.ts +2 -12
  133. package/dist/stitch-frames-to-video.js +37 -46
  134. package/dist/take-frame-and-compose.d.ts +4 -5
  135. package/dist/take-frame-and-compose.js +15 -9
  136. package/dist/tmp-dir.js +7 -8
  137. package/dist/validate-concurrency.d.ts +2 -0
  138. package/dist/validate-concurrency.js +11 -5
  139. package/dist/validate-output-filename.d.ts +1 -1
  140. package/dist/validate-puppeteer-timeout.js +1 -0
  141. package/install-toolchain.mjs +36 -0
  142. package/package.json +11 -10
  143. package/types/ws/index.d.ts +5 -5
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.renderMedia = void 0;
7
- const fs_1 = __importDefault(require("fs"));
8
- const os_1 = __importDefault(require("os"));
9
- const path_1 = __importDefault(require("path"));
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
10
  const remotion_1 = require("remotion");
11
11
  const download_map_1 = require("./assets/download-map");
12
12
  const can_use_parallel_encoding_1 = require("./can-use-parallel-encoding");
@@ -15,14 +15,13 @@ const crf_1 = require("./crf");
15
15
  const delete_directory_1 = require("./delete-directory");
16
16
  const ensure_frames_in_order_1 = require("./ensure-frames-in-order");
17
17
  const ensure_output_directory_1 = require("./ensure-output-directory");
18
- const find_closest_package_json_1 = require("./find-closest-package-json");
19
18
  const get_duration_from_frame_range_1 = require("./get-duration-from-frame-range");
20
19
  const get_extension_from_codec_1 = require("./get-extension-from-codec");
21
20
  const get_extension_of_filename_1 = require("./get-extension-of-filename");
22
21
  const get_frame_to_render_1 = require("./get-frame-to-render");
23
22
  const image_format_1 = require("./image-format");
24
23
  const is_audio_codec_1 = require("./is-audio-codec");
25
- const legacy_webpack_config_1 = require("./legacy-webpack-config");
24
+ const jpeg_quality_1 = require("./jpeg-quality");
26
25
  const make_cancel_signal_1 = require("./make-cancel-signal");
27
26
  const overwrite_1 = require("./overwrite");
28
27
  const perf_1 = require("./perf");
@@ -30,36 +29,27 @@ const pixel_format_1 = require("./pixel-format");
30
29
  const prespawn_ffmpeg_1 = require("./prespawn-ffmpeg");
31
30
  const prestitcher_memory_usage_1 = require("./prestitcher-memory-usage");
32
31
  const prores_profile_1 = require("./prores-profile");
33
- const quality_1 = require("./quality");
34
32
  const render_frames_1 = require("./render-frames");
35
33
  const stitch_frames_to_video_1 = require("./stitch-frames-to-video");
36
34
  const validate_even_dimensions_with_codec_1 = require("./validate-even-dimensions-with-codec");
37
35
  const validate_every_nth_frame_1 = require("./validate-every-nth-frame");
38
- const validate_ffmpeg_1 = require("./validate-ffmpeg");
39
36
  const validate_ffmpeg_override_1 = require("./validate-ffmpeg-override");
37
+ const validate_number_of_gif_loops_1 = require("./validate-number-of-gif-loops");
40
38
  const validate_output_filename_1 = require("./validate-output-filename");
41
39
  const validate_scale_1 = require("./validate-scale");
42
40
  const validate_videobitrate_1 = require("./validate-videobitrate");
43
41
  const SLOWEST_FRAME_COUNT = 10;
44
- const getConcurrency = (others) => {
45
- if ('concurrency' in others) {
46
- return others.concurrency;
47
- }
48
- if ('parallelism' in others) {
49
- return others.parallelism;
50
- }
51
- return null;
52
- };
53
42
  /**
54
43
  *
55
44
  * @description Render a video from a composition
56
45
  * @see [Documentation](https://www.remotion.dev/docs/renderer/render-media)
57
46
  */
58
- const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprobeExecutable, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, onSlowestFrames, audioCodec, ...options }) => {
59
- var _a, _b, _c, _d, _e, _f, _g;
60
- const remotionRoot = (0, find_closest_package_json_1.findRemotionRoot)();
61
- (0, validate_ffmpeg_1.validateFfmpeg)(ffmpegExecutable !== null && ffmpegExecutable !== void 0 ? ffmpegExecutable : null, remotionRoot, 'ffmpeg');
62
- (0, quality_1.validateQuality)(options.quality);
47
+ const renderMedia = ({ proResProfile, crf, composition, inputProps, pixelFormat, codec, envVariables, frameRange, puppeteerInstance, outputLocation, onProgress, overwrite, onDownload, dumpBrowserLogs, onBrowserLog, onStart, timeoutInMilliseconds, chromiumOptions, scale, browserExecutable, port, cancelSignal, muted, enforceAudioTrack, ffmpegOverride, audioBitrate, videoBitrate, audioCodec, ...options }) => {
48
+ var _a, _b, _c, _d, _e, _f, _g, _h;
49
+ if (options.quality) {
50
+ throw new Error(`The "quality" option has been renamed. Please use "jpegQuality" instead.`);
51
+ }
52
+ (0, jpeg_quality_1.validateJpegQuality)(options.jpegQuality);
63
53
  (0, crf_1.validateQualitySettings)({ crf, codec, videoBitrate });
64
54
  (0, validate_videobitrate_1.validateBitrate)(audioBitrate, 'audioBitrate');
65
55
  (0, validate_videobitrate_1.validateBitrate)(videoBitrate, 'videoBitrate');
@@ -77,15 +67,14 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
77
67
  });
78
68
  }
79
69
  const absoluteOutputLocation = outputLocation
80
- ? path_1.default.resolve(process.cwd(), outputLocation)
70
+ ? node_path_1.default.resolve(process.cwd(), outputLocation)
81
71
  : null;
82
72
  (0, validate_scale_1.validateScale)(scale);
83
- const concurrency = getConcurrency(options);
84
73
  (0, validate_ffmpeg_override_1.validateFfmpegOverride)(ffmpegOverride);
85
74
  const everyNthFrame = (_b = options.everyNthFrame) !== null && _b !== void 0 ? _b : 1;
86
75
  (0, validate_every_nth_frame_1.validateEveryNthFrame)(everyNthFrame, codec);
87
76
  const numberOfGifLoops = (_c = options.numberOfGifLoops) !== null && _c !== void 0 ? _c : null;
88
- const serveUrl = (0, legacy_webpack_config_1.getServeUrlWithFallback)(options);
77
+ (0, validate_number_of_gif_loops_1.validateNumberOfGifLoops)(numberOfGifLoops, codec);
89
78
  let stitchStage = 'encoding';
90
79
  let stitcherFfmpeg;
91
80
  let preStitcher = null;
@@ -104,28 +93,29 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
104
93
  hasEnoughMemory &&
105
94
  (0, can_use_parallel_encoding_1.canUseParallelEncoding)(codec);
106
95
  if (options.verbose) {
107
- console.log('[PRESTITCHER] Free memory:', freeMemory, 'Estimated usage parallel encoding', estimatedUsage);
108
- console.log('[PRESTITCHER]: Codec supports parallel rendering:', (0, can_use_parallel_encoding_1.canUseParallelEncoding)(codec));
109
- console.log('[PRESTITCHER]: User disallowed parallel encoding:', Boolean(options.disallowParallelEncoding));
96
+ const log = (_f = options.printLog) !== null && _f !== void 0 ? _f : console.log;
97
+ log('[PRESTITCHER] Free memory:', freeMemory, 'Estimated usage parallel encoding', estimatedUsage);
98
+ log('[PRESTITCHER]: Codec supports parallel rendering:', (0, can_use_parallel_encoding_1.canUseParallelEncoding)(codec));
99
+ log('[PRESTITCHER]: User disallowed parallel encoding:', Boolean(options.disallowParallelEncoding));
110
100
  if (parallelEncoding) {
111
- console.log('[PRESTITCHER] Parallel encoding is enabled.');
101
+ log('[PRESTITCHER] Parallel encoding is enabled.');
112
102
  }
113
103
  else {
114
- console.log('[PRESTITCHER] Parallel encoding is disabled.');
104
+ log('[PRESTITCHER] Parallel encoding is disabled.');
115
105
  }
116
106
  }
117
107
  const imageFormat = (0, is_audio_codec_1.isAudioCodec)(codec)
118
108
  ? 'none'
119
- : (_f = options.imageFormat) !== null && _f !== void 0 ? _f : 'jpeg';
120
- const quality = imageFormat === 'jpeg' ? options.quality : undefined;
109
+ : (_g = options.imageFormat) !== null && _g !== void 0 ? _g : 'jpeg';
110
+ const jpegQuality = imageFormat === 'jpeg' ? options.jpegQuality : undefined;
121
111
  (0, image_format_1.validateSelectedPixelFormatAndImageFormatCombination)(pixelFormat, imageFormat);
122
112
  const preEncodedFileLocation = parallelEncoding
123
- ? path_1.default.join(downloadMap.preEncode, 'pre-encode.' + (0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec, audioCodec !== null && audioCodec !== void 0 ? audioCodec : null))
113
+ ? node_path_1.default.join(downloadMap.preEncode, 'pre-encode.' + (0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec, audioCodec !== null && audioCodec !== void 0 ? audioCodec : null))
124
114
  : null;
125
115
  const outputDir = parallelEncoding
126
116
  ? null
127
- : fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'react-motion-render'));
128
- if (((_g = options.internal) === null || _g === void 0 ? void 0 : _g.onCtrlCExit) && outputDir) {
117
+ : node_fs_1.default.mkdtempSync(node_path_1.default.join(node_os_1.default.tmpdir(), 'react-motion-render'));
118
+ if (((_h = options.internal) === null || _h === void 0 ? void 0 : _h.onCtrlCExit) && outputDir) {
129
119
  options.internal.onCtrlCExit(() => (0, delete_directory_1.deleteDirectory)(outputDir));
130
120
  }
131
121
  (0, validate_even_dimensions_with_codec_1.validateEvenDimensionsWithCodec)({
@@ -156,10 +146,10 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
156
146
  const { waitForRightTimeOfFrameToBeInserted, setFrameToStitch, waitForFinish } = (0, ensure_frames_in_order_1.ensureFramesInOrder)(realFrameRange);
157
147
  const fps = composition.fps / (everyNthFrame !== null && everyNthFrame !== void 0 ? everyNthFrame : 1);
158
148
  remotion_1.Internals.validateFps(fps, 'in "renderMedia()"', codec === 'gif');
159
- const createPrestitcherIfNecessary = async () => {
149
+ const createPrestitcherIfNecessary = () => {
160
150
  var _a;
161
151
  if (preEncodedFileLocation) {
162
- preStitcher = await (0, prespawn_ffmpeg_1.prespawnFfmpeg)({
152
+ preStitcher = (0, prespawn_ffmpeg_1.prespawnFfmpeg)({
163
153
  width: composition.width * (scale !== null && scale !== void 0 ? scale : 1),
164
154
  height: composition.height * (scale !== null && scale !== void 0 ? scale : 1),
165
155
  fps,
@@ -173,12 +163,11 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
173
163
  callUpdate();
174
164
  },
175
165
  verbose: (_a = options.verbose) !== null && _a !== void 0 ? _a : false,
176
- ffmpegExecutable,
177
166
  imageFormat,
178
167
  signal: cancelPrestitcher.cancelSignal,
179
168
  ffmpegOverride: ffmpegOverride !== null && ffmpegOverride !== void 0 ? ffmpegOverride : (({ args }) => args),
180
169
  videoBitrate: videoBitrate !== null && videoBitrate !== void 0 ? videoBitrate : null,
181
- }, remotionRoot);
170
+ });
182
171
  stitcherFfmpeg = preStitcher.task;
183
172
  }
184
173
  };
@@ -221,16 +210,17 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
221
210
  }
222
211
  minTime = (_b = (_a = slowestFrames[slowestFrames.length - 1]) === null || _a === void 0 ? void 0 : _a.time) !== null && _b !== void 0 ? _b : minTime;
223
212
  };
224
- const happyPath = createPrestitcherIfNecessary()
213
+ const happyPath = Promise.resolve(createPrestitcherIfNecessary())
225
214
  .then(() => {
215
+ var _a;
226
216
  const renderFramesProc = (0, render_frames_1.renderFrames)({
227
- config: composition,
217
+ composition,
228
218
  onFrameUpdate: (frame, frameIndex, timeToRenderInMilliseconds) => {
229
219
  renderedFrames = frame;
230
220
  callUpdate();
231
221
  recordFrameTime(frameIndex, timeToRenderInMilliseconds);
232
222
  },
233
- concurrency,
223
+ concurrency: options.concurrency,
234
224
  outputDir,
235
225
  onStart: (data) => {
236
226
  renderedFrames = 0;
@@ -240,7 +230,7 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
240
230
  inputProps,
241
231
  envVariables,
242
232
  imageFormat,
243
- quality,
233
+ jpegQuality,
244
234
  frameRange: frameRange !== null && frameRange !== void 0 ? frameRange : null,
245
235
  puppeteerInstance,
246
236
  everyNthFrame,
@@ -257,20 +247,19 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
257
247
  setFrameToStitch(Math.min(realFrameRange[1] + 1, frame + everyNthFrame));
258
248
  }
259
249
  : undefined,
260
- serveUrl,
250
+ serveUrl: options.serveUrl,
261
251
  dumpBrowserLogs,
262
252
  onBrowserLog,
263
253
  onDownload,
264
254
  timeoutInMilliseconds,
265
255
  chromiumOptions,
266
256
  scale,
267
- ffmpegExecutable,
268
- ffprobeExecutable,
269
257
  browserExecutable,
270
258
  port,
271
259
  cancelSignal: cancelRenderFrames.cancelSignal,
272
260
  downloadMap,
273
261
  muted: disableAudio,
262
+ verbose: (_a = options.verbose) !== null && _a !== void 0 ? _a : false,
274
263
  });
275
264
  return renderFramesProc;
276
265
  })
@@ -302,8 +291,6 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
302
291
  proResProfile,
303
292
  crf,
304
293
  assetsInfo,
305
- ffmpegExecutable,
306
- ffprobeExecutable,
307
294
  onProgress: (frame) => {
308
295
  stitchStage = 'muxing';
309
296
  encodedFrames = frame;
@@ -329,8 +316,11 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
329
316
  encodedDoneIn = Date.now() - stitchStart;
330
317
  callUpdate();
331
318
  slowestFrames.sort((a, b) => b.time - a.time);
332
- onSlowestFrames === null || onSlowestFrames === void 0 ? void 0 : onSlowestFrames(slowestFrames);
333
- return buffer;
319
+ const result = {
320
+ buffer,
321
+ slowestFrames,
322
+ };
323
+ return result;
334
324
  })
335
325
  .catch((err) => {
336
326
  /**
@@ -358,15 +348,15 @@ const renderMedia = ({ proResProfile, crf, composition, ffmpegExecutable, ffprob
358
348
  .finally(() => {
359
349
  var _a;
360
350
  if (preEncodedFileLocation !== null &&
361
- fs_1.default.existsSync(preEncodedFileLocation)) {
362
- (0, delete_directory_1.deleteDirectory)(path_1.default.dirname(preEncodedFileLocation));
351
+ node_fs_1.default.existsSync(preEncodedFileLocation)) {
352
+ (0, delete_directory_1.deleteDirectory)(node_path_1.default.dirname(preEncodedFileLocation));
363
353
  }
364
354
  // Clean download map if it was not passed in
365
355
  if (!((_a = options.internal) === null || _a === void 0 ? void 0 : _a.downloadMap)) {
366
356
  (0, download_map_1.cleanDownloadMap)(downloadMap);
367
357
  }
368
358
  // Clean temporary image frames when rendering ends or fails
369
- if (outputDir && fs_1.default.existsSync(outputDir)) {
359
+ if (outputDir && node_fs_1.default.existsSync(outputDir)) {
370
360
  (0, delete_directory_1.deleteDirectory)(outputDir);
371
361
  }
372
362
  });
@@ -1,42 +1,46 @@
1
1
  /// <reference types="node" />
2
- import type { SmallTCompMetadata } from 'remotion';
2
+ import type { AnySmallCompMetadata } from 'remotion';
3
3
  import type { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
4
4
  import type { DownloadMap } from './assets/download-map';
5
5
  import type { BrowserExecutable } from './browser-executable';
6
+ import type { BrowserLog } from './browser-log';
6
7
  import type { Browser as PuppeteerBrowser } from './browser/Browser';
7
- import type { FfmpegExecutable } from './ffmpeg-executable';
8
8
  import type { StillImageFormat } from './image-format';
9
- import type { ServeUrlOrWebpackBundle } from './legacy-webpack-config';
10
9
  import type { CancelSignal } from './make-cancel-signal';
11
10
  import type { ChromiumOptions } from './open-browser';
12
11
  declare type InnerStillOptions = {
13
- composition: SmallTCompMetadata;
12
+ composition: AnySmallCompMetadata;
14
13
  output?: string | null;
15
14
  frame?: number;
16
15
  inputProps?: unknown;
17
16
  imageFormat?: StillImageFormat;
18
- quality?: number;
17
+ /**
18
+ * @deprecated Renamed to `jpegQuality`
19
+ */
20
+ quality?: never;
21
+ jpegQuality?: number;
19
22
  puppeteerInstance?: PuppeteerBrowser;
20
23
  dumpBrowserLogs?: boolean;
21
24
  envVariables?: Record<string, string>;
22
25
  overwrite?: boolean;
23
26
  browserExecutable?: BrowserExecutable;
27
+ onBrowserLog?: (log: BrowserLog) => void;
24
28
  timeoutInMilliseconds?: number;
25
29
  chromiumOptions?: ChromiumOptions;
26
30
  scale?: number;
27
31
  onDownload?: RenderMediaOnDownload;
28
32
  cancelSignal?: CancelSignal;
29
- ffmpegExecutable?: FfmpegExecutable;
30
- ffprobeExecutable?: FfmpegExecutable;
31
33
  /**
32
34
  * @deprecated Only for Remotion internal usage
33
35
  */
34
36
  downloadMap?: DownloadMap;
37
+ verbose?: boolean;
35
38
  };
36
39
  declare type RenderStillReturnValue = {
37
40
  buffer: Buffer | null;
38
41
  };
39
- export declare type RenderStillOptions = InnerStillOptions & ServeUrlOrWebpackBundle & {
42
+ export declare type RenderStillOptions = InnerStillOptions & {
43
+ serveUrl: string;
40
44
  port?: number | null;
41
45
  };
42
46
  /**
@@ -27,8 +27,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.renderStill = void 0;
30
- const fs_1 = __importStar(require("fs"));
31
- const path_1 = __importDefault(require("path"));
30
+ const node_fs_1 = __importStar(require("node:fs"));
31
+ const node_path_1 = __importDefault(require("node:path"));
32
32
  const remotion_1 = require("remotion");
33
33
  const download_map_1 = require("./assets/download-map");
34
34
  const browser_1 = require("./browser");
@@ -37,18 +37,20 @@ const ensure_output_directory_1 = require("./ensure-output-directory");
37
37
  const handle_javascript_exception_1 = require("./error-handling/handle-javascript-exception");
38
38
  const find_closest_package_json_1 = require("./find-closest-package-json");
39
39
  const image_format_1 = require("./image-format");
40
- const legacy_webpack_config_1 = require("./legacy-webpack-config");
40
+ const jpeg_quality_1 = require("./jpeg-quality");
41
41
  const make_cancel_signal_1 = require("./make-cancel-signal");
42
42
  const open_browser_1 = require("./open-browser");
43
43
  const prepare_server_1 = require("./prepare-server");
44
44
  const puppeteer_evaluate_1 = require("./puppeteer-evaluate");
45
- const quality_1 = require("./quality");
46
45
  const seek_to_frame_1 = require("./seek-to-frame");
47
46
  const set_props_and_env_1 = require("./set-props-and-env");
48
47
  const take_frame_and_compose_1 = require("./take-frame-and-compose");
49
48
  const validate_puppeteer_timeout_1 = require("./validate-puppeteer-timeout");
50
49
  const validate_scale_1 = require("./validate-scale");
51
- const innerRenderStill = async ({ composition, quality, imageFormat = 'png', serveUrl, puppeteerInstance, dumpBrowserLogs = false, onError, inputProps, envVariables, output, frame = 0, overwrite = true, browserExecutable, timeoutInMilliseconds, chromiumOptions, scale = 1, proxyPort, cancelSignal, downloadMap, }) => {
50
+ const innerRenderStill = async ({ composition, quality, imageFormat = image_format_1.DEFAULT_STILL_IMAGE_FORMAT, serveUrl, puppeteerInstance, dumpBrowserLogs = false, onError, inputProps, envVariables, output, frame = 0, overwrite = true, browserExecutable, timeoutInMilliseconds, chromiumOptions, scale = 1, proxyPort, cancelSignal, downloadMap, jpegQuality, onBrowserLog, }) => {
51
+ if (quality) {
52
+ throw new Error('quality has been renamed to jpegQuality. Please rename the option.');
53
+ }
52
54
  remotion_1.Internals.validateDimension(composition.height, 'height', 'in the `config` object passed to `renderStill()`');
53
55
  remotion_1.Internals.validateDimension(composition.width, 'width', 'in the `config` object passed to `renderStill()`');
54
56
  remotion_1.Internals.validateFps(composition.fps, 'in the `config` object of `renderStill()`', false);
@@ -57,7 +59,7 @@ const innerRenderStill = async ({ composition, quality, imageFormat = 'png', ser
57
59
  component: 'in the `config` object passed to `renderStill()`',
58
60
  allowFloats: false,
59
61
  });
60
- (0, image_format_1.validateNonNullImageFormat)(imageFormat);
62
+ (0, image_format_1.validateStillImageFormat)(imageFormat);
61
63
  remotion_1.Internals.validateFrame({
62
64
  frame,
63
65
  durationInFrames: composition.durationInFrames,
@@ -70,17 +72,17 @@ const innerRenderStill = async ({ composition, quality, imageFormat = 'png', ser
70
72
  (0, validate_puppeteer_timeout_1.validatePuppeteerTimeout)(timeoutInMilliseconds);
71
73
  (0, validate_scale_1.validateScale)(scale);
72
74
  output =
73
- typeof output === 'string' ? path_1.default.resolve(process.cwd(), output) : null;
74
- if (quality !== undefined && imageFormat !== 'jpeg') {
75
+ typeof output === 'string' ? node_path_1.default.resolve(process.cwd(), output) : null;
76
+ if (jpegQuality !== undefined && imageFormat !== 'jpeg') {
75
77
  throw new Error("You can only pass the `quality` option if `imageFormat` is 'jpeg'.");
76
78
  }
77
- (0, quality_1.validateQuality)(quality);
79
+ (0, jpeg_quality_1.validateJpegQuality)(jpegQuality);
78
80
  if (output) {
79
- if (fs_1.default.existsSync(output)) {
81
+ if (node_fs_1.default.existsSync(output)) {
80
82
  if (!overwrite) {
81
83
  throw new Error(`Cannot render still - "overwrite" option was set to false, but the output destination ${output} already exists.`);
82
84
  }
83
- const stat = (0, fs_1.statSync)(output);
85
+ const stat = (0, node_fs_1.statSync)(output);
84
86
  if (!stat.isFile()) {
85
87
  throw new Error(`The output location ${output} already exists, but is not a file, but something else (e.g. folder). Cannot save to it.`);
86
88
  }
@@ -108,8 +110,16 @@ const innerRenderStill = async ({ composition, quality, imageFormat = 'png', ser
108
110
  onError: errorCallback,
109
111
  frame: null,
110
112
  });
113
+ const logCallback = (log) => {
114
+ onBrowserLog === null || onBrowserLog === void 0 ? void 0 : onBrowserLog({
115
+ stackTrace: log.stackTrace(),
116
+ text: log.text,
117
+ type: log.type,
118
+ });
119
+ };
111
120
  const cleanup = async () => {
112
121
  cleanUpJSException();
122
+ page.off('console', logCallback);
113
123
  if (puppeteerInstance) {
114
124
  await page.close();
115
125
  }
@@ -122,6 +132,9 @@ const innerRenderStill = async ({ composition, quality, imageFormat = 'png', ser
122
132
  cancelSignal === null || cancelSignal === void 0 ? void 0 : cancelSignal(() => {
123
133
  cleanup();
124
134
  });
135
+ if (onBrowserLog) {
136
+ page.on('console', logCallback);
137
+ }
125
138
  await (0, set_props_and_env_1.setPropsAndEnv)({
126
139
  inputProps,
127
140
  envVariables,
@@ -168,7 +181,7 @@ const innerRenderStill = async ({ composition, quality, imageFormat = 'png', ser
168
181
  imageFormat,
169
182
  scale,
170
183
  output,
171
- quality,
184
+ jpegQuality,
172
185
  wantsBuffer: !output,
173
186
  });
174
187
  await cleanup();
@@ -181,22 +194,21 @@ const innerRenderStill = async ({ composition, quality, imageFormat = 'png', ser
181
194
  */
182
195
  const renderStill = (options) => {
183
196
  var _a, _b;
184
- const selectedServeUrl = (0, legacy_webpack_config_1.getServeUrlWithFallback)(options);
185
197
  const downloadMap = (_a = options.downloadMap) !== null && _a !== void 0 ? _a : (0, download_map_1.makeDownloadMap)();
186
198
  const onDownload = (_b = options.onDownload) !== null && _b !== void 0 ? _b : (() => () => undefined);
187
199
  const happyPath = new Promise((resolve, reject) => {
188
- var _a, _b, _c;
200
+ var _a, _b;
189
201
  const onError = (err) => reject(err);
190
202
  let close = null;
191
203
  (0, prepare_server_1.prepareServer)({
192
- webpackConfigOrServeUrl: selectedServeUrl,
204
+ webpackConfigOrServeUrl: options.serveUrl,
193
205
  onDownload,
194
206
  onError,
195
- ffmpegExecutable: (_a = options.ffmpegExecutable) !== null && _a !== void 0 ? _a : null,
196
- ffprobeExecutable: (_b = options.ffprobeExecutable) !== null && _b !== void 0 ? _b : null,
197
- port: (_c = options.port) !== null && _c !== void 0 ? _c : null,
207
+ port: (_a = options.port) !== null && _a !== void 0 ? _a : null,
198
208
  downloadMap,
199
209
  remotionRoot: (0, find_closest_package_json_1.findRemotionRoot)(),
210
+ concurrency: 1,
211
+ verbose: (_b = options.verbose) !== null && _b !== void 0 ? _b : false,
200
212
  })
201
213
  .then(({ serveUrl, closeServer, offthreadPort }) => {
202
214
  close = closeServer;
@@ -4,14 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.resolveAssetSrc = void 0;
7
- const url_1 = __importDefault(require("url"));
7
+ const node_url_1 = __importDefault(require("node:url"));
8
8
  const resolveAssetSrc = (src) => {
9
9
  if (!src.startsWith('file:')) {
10
10
  return src;
11
11
  }
12
12
  const { protocol } = new URL(src);
13
13
  if (protocol === 'file:')
14
- return url_1.default.fileURLToPath(src);
14
+ return node_url_1.default.fileURLToPath(src);
15
15
  throw new TypeError(`Unexpected src ${src}`);
16
16
  };
17
17
  exports.resolveAssetSrc = resolveAssetSrc;
@@ -1,11 +1,10 @@
1
- /// <reference types="node" />
2
1
  import type { ClipRegion } from 'remotion';
3
2
  import type { Page } from './browser/BrowserPage';
4
- import type { ImageFormat } from './image-format';
5
- export declare const screenshotDOMElement: ({ page, imageFormat, quality, opts, height, width, clipRegion, }: {
3
+ import type { StillImageFormat } from './image-format';
4
+ export declare const screenshotDOMElement: ({ page, imageFormat, jpegQuality, opts, height, width, clipRegion, }: {
6
5
  page: Page;
7
- imageFormat: ImageFormat;
8
- quality: number | undefined;
6
+ imageFormat: StillImageFormat;
7
+ jpegQuality: number | undefined;
9
8
  opts: {
10
9
  path: string | null;
11
10
  };
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.screenshotDOMElement = void 0;
4
4
  const puppeteer_evaluate_1 = require("./puppeteer-evaluate");
5
5
  const puppeteer_screenshot_1 = require("./puppeteer-screenshot");
6
- const screenshotDOMElement = async ({ page, imageFormat, quality, opts, height, width, clipRegion, }) => {
6
+ const screenshotDOMElement = async ({ page, imageFormat, jpegQuality, opts, height, width, clipRegion, }) => {
7
7
  const { path } = opts;
8
- if (imageFormat === 'png') {
8
+ if (imageFormat === 'png' ||
9
+ imageFormat === 'pdf' ||
10
+ imageFormat === 'webp') {
9
11
  await (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatch)({
10
12
  pageFunction: () => {
11
13
  document.body.style.background = 'transparent';
@@ -25,6 +27,7 @@ const screenshotDOMElement = async ({ page, imageFormat, quality, opts, height,
25
27
  page,
26
28
  });
27
29
  }
30
+ // @ts-expect-error
28
31
  if (imageFormat === 'none') {
29
32
  throw new TypeError('Tried to make a screenshot with format "none"');
30
33
  }
@@ -33,7 +36,7 @@ const screenshotDOMElement = async ({ page, imageFormat, quality, opts, height,
33
36
  omitBackground: imageFormat === 'png',
34
37
  path: path !== null && path !== void 0 ? path : undefined,
35
38
  type: imageFormat,
36
- quality,
39
+ jpegQuality,
37
40
  width,
38
41
  height,
39
42
  clipRegion,
@@ -1,12 +1,11 @@
1
- /// <reference types="node" />
2
1
  import type { ClipRegion } from 'remotion';
3
2
  import type { Page } from './browser/BrowserPage';
4
3
  import type { StillImageFormat } from './image-format';
5
- export declare const screenshotTask: ({ format, height, omitBackground, page, width, path, quality, clipRegion, }: {
4
+ export declare const screenshotTask: ({ format, height, omitBackground, page, width, path, jpegQuality, clipRegion, }: {
6
5
  page: Page;
7
6
  format: StillImageFormat;
8
7
  path?: string | undefined;
9
- quality?: number | undefined;
8
+ jpegQuality?: number | undefined;
10
9
  omitBackground: boolean;
11
10
  width: number;
12
11
  height: number;
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.screenshotTask = void 0;
7
- const fs_1 = __importDefault(require("fs"));
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const perf_1 = require("./perf");
9
- const screenshotTask = async ({ format, height, omitBackground, page, width, path, quality, clipRegion, }) => {
9
+ const screenshotTask = async ({ format, height, omitBackground, page, width, path, jpegQuality, clipRegion, }) => {
10
10
  var _a;
11
11
  const client = page._client();
12
12
  const target = page.target();
@@ -15,41 +15,56 @@ const screenshotTask = async ({ format, height, omitBackground, page, width, pat
15
15
  targetId: target._targetId,
16
16
  });
17
17
  (0, perf_1.stopPerfMeasure)(perfTarget);
18
- const shouldSetDefaultBackground = omitBackground && format === 'png';
18
+ const shouldSetDefaultBackground = omitBackground;
19
19
  if (shouldSetDefaultBackground)
20
20
  await client.send('Emulation.setDefaultBackgroundColorOverride', {
21
21
  color: { r: 0, g: 0, b: 0, a: 0 },
22
22
  });
23
23
  const cap = (0, perf_1.startPerfMeasure)('capture');
24
24
  try {
25
- const result = await client.send('Page.captureScreenshot', {
26
- format,
27
- quality,
28
- clip: clipRegion !== null && clipRegion !== 'hide'
29
- ? {
30
- x: clipRegion.x,
31
- y: clipRegion.y,
32
- height: clipRegion.height,
33
- scale: 1,
34
- width: clipRegion.width,
35
- }
36
- : {
37
- x: 0,
38
- y: 0,
39
- height,
40
- scale: 1,
41
- width,
42
- },
43
- captureBeyondViewport: true,
44
- optimizeForSpeed: true,
45
- });
25
+ let result;
26
+ if (format === 'pdf') {
27
+ result = await client.send('Page.printToPDF', {
28
+ paperWidth: width / 96,
29
+ paperHeight: height / 96,
30
+ marginTop: 0,
31
+ marginBottom: 0,
32
+ marginLeft: 0,
33
+ marginRight: 0,
34
+ scale: 1,
35
+ printBackground: true,
36
+ });
37
+ }
38
+ else {
39
+ result = await client.send('Page.captureScreenshot', {
40
+ format,
41
+ quality: jpegQuality,
42
+ clip: clipRegion !== null && clipRegion !== 'hide'
43
+ ? {
44
+ x: clipRegion.x,
45
+ y: clipRegion.y,
46
+ height: clipRegion.height,
47
+ scale: 1,
48
+ width: clipRegion.width,
49
+ }
50
+ : {
51
+ x: 0,
52
+ y: 0,
53
+ height,
54
+ scale: 1,
55
+ width,
56
+ },
57
+ captureBeyondViewport: true,
58
+ optimizeForSpeed: true,
59
+ });
60
+ }
46
61
  (0, perf_1.stopPerfMeasure)(cap);
47
62
  if (shouldSetDefaultBackground)
48
63
  await client.send('Emulation.setDefaultBackgroundColorOverride');
49
64
  const saveMarker = (0, perf_1.startPerfMeasure)('save');
50
65
  const buffer = Buffer.from(result.data, 'base64');
51
66
  if (path)
52
- await fs_1.default.promises.writeFile(path, buffer);
67
+ await node_fs_1.default.promises.writeFile(path, buffer);
53
68
  (0, perf_1.stopPerfMeasure)(saveMarker);
54
69
  return buffer;
55
70
  }
@@ -1,4 +1,4 @@
1
- import type { IncomingMessage, ServerResponse } from 'http';
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
2
  export declare const serveHandler: (request: IncomingMessage, response: ServerResponse, config: {
3
3
  public: string;
4
4
  }) => Promise<void>;