@remotion/cli 3.3.18 → 3.3.25

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 (106) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/config/index.d.ts +1 -0
  3. package/dist/config/index.js +3 -0
  4. package/dist/config/log.d.ts +1 -1
  5. package/dist/config/open-browser.d.ts +2 -0
  6. package/dist/config/open-browser.js +15 -0
  7. package/dist/convert-entry-point-to-serve-url.d.ts +1 -0
  8. package/dist/convert-entry-point-to-serve-url.js +15 -0
  9. package/dist/editor/components/CollapsableOptions.d.ts +6 -0
  10. package/dist/editor/components/CollapsableOptions.js +35 -0
  11. package/dist/editor/components/InlineAction.d.ts +5 -0
  12. package/dist/editor/components/InlineAction.js +34 -0
  13. package/dist/editor/components/RenderButton.d.ts +1 -1
  14. package/dist/editor/components/RenderButton.js +24 -34
  15. package/dist/editor/components/RenderModal/RenderErrorModal.d.ts +5 -0
  16. package/dist/editor/components/RenderModal/RenderErrorModal.js +64 -0
  17. package/dist/editor/components/RenderModal/RenderModal.d.ts +8 -2
  18. package/dist/editor/components/RenderModal/RenderModal.js +204 -32
  19. package/dist/editor/components/RenderQueue/CircularProgress.d.ts +5 -0
  20. package/dist/editor/components/RenderQueue/CircularProgress.js +18 -0
  21. package/dist/editor/components/RenderQueue/RenderQueueError.d.ts +5 -0
  22. package/dist/editor/components/RenderQueue/RenderQueueError.js +26 -0
  23. package/dist/editor/components/RenderQueue/RenderQueueItem.js +14 -1
  24. package/dist/editor/components/RenderQueue/RenderQueueItemStatus.js +11 -3
  25. package/dist/editor/components/RenderQueue/RenderQueueOutputName.js +12 -52
  26. package/dist/editor/components/RenderQueue/RenderQueueProgressMessage.d.ts +5 -0
  27. package/dist/editor/components/RenderQueue/RenderQueueProgressMessage.js +27 -0
  28. package/dist/editor/components/RenderQueue/RenderQueueRemoveItem.js +6 -40
  29. package/dist/editor/components/RenderQueue/RenderQueueRepeat.d.ts +5 -0
  30. package/dist/editor/components/RenderQueue/RenderQueueRepeat.js +22 -0
  31. package/dist/editor/components/RenderQueue/actions.d.ts +32 -0
  32. package/dist/editor/components/RenderQueue/actions.js +75 -0
  33. package/dist/editor/components/RenderQueue/context.d.ts +1 -0
  34. package/dist/editor/components/RenderQueue/context.js +6 -1
  35. package/dist/editor/components/RenderQueue/index.js +1 -1
  36. package/dist/editor/components/RenderQueue/item-style.d.ts +2 -0
  37. package/dist/editor/components/RenderQueue/item-style.js +21 -0
  38. package/dist/editor/components/RenderToolbarIcon.d.ts +2 -0
  39. package/dist/editor/components/RenderToolbarIcon.js +47 -0
  40. package/dist/editor/components/RendersTab.js +6 -2
  41. package/dist/editor/components/SegmentedControl.d.ts +15 -0
  42. package/dist/editor/components/SegmentedControl.js +46 -0
  43. package/dist/editor/components/SidebarContent.js +21 -4
  44. package/dist/editor/components/Tabs/index.js +3 -1
  45. package/dist/editor/components/Timeline/TimelineZoomControls.js +3 -1
  46. package/dist/editor/helpers/use-file-existence.d.ts +1 -0
  47. package/dist/editor/helpers/use-file-existence.js +57 -0
  48. package/dist/editor/helpers/use-menu-structure.js +15 -1
  49. package/dist/editor/icons/RenderStillIcon.d.ts +3 -0
  50. package/dist/editor/icons/RenderStillIcon.js +8 -0
  51. package/dist/editor/icons/render.d.ts +0 -1
  52. package/dist/editor/icons/render.js +1 -1
  53. package/dist/editor/icons/video.d.ts +5 -0
  54. package/dist/editor/icons/video.js +8 -0
  55. package/dist/file-watcher.d.ts +9 -0
  56. package/dist/file-watcher.js +35 -0
  57. package/dist/get-cli-options.d.ts +1 -1
  58. package/dist/index.d.ts +3 -3
  59. package/dist/list-of-remotion-packages.js +1 -0
  60. package/dist/load-config.js +1 -10
  61. package/dist/parse-command-line.d.ts +1 -0
  62. package/dist/parse-command-line.js +1 -0
  63. package/dist/preview-server/actions.d.ts +0 -0
  64. package/dist/preview-server/actions.js +1 -0
  65. package/dist/preview-server/api-routes.d.ts +4 -0
  66. package/dist/preview-server/api-routes.js +15 -0
  67. package/dist/preview-server/api-types.d.ts +26 -0
  68. package/dist/preview-server/api-types.js +2 -0
  69. package/dist/preview-server/file-existence-watchers.d.ts +10 -0
  70. package/dist/preview-server/file-existence-watchers.js +46 -0
  71. package/dist/preview-server/get-file-existence.d.ts +2 -0
  72. package/dist/preview-server/get-file-existence.js +36 -0
  73. package/dist/preview-server/handler.d.ts +9 -0
  74. package/dist/preview-server/handler.js +34 -0
  75. package/dist/preview-server/render-queue/add-render.d.ts +3 -2
  76. package/dist/preview-server/render-queue/add-render.js +20 -25
  77. package/dist/preview-server/render-queue/index.d.ts +14 -3
  78. package/dist/preview-server/render-queue/index.js +51 -10
  79. package/dist/preview-server/render-queue/job.d.ts +56 -6
  80. package/dist/preview-server/render-queue/make-retry-payload.d.ts +3 -0
  81. package/dist/preview-server/render-queue/make-retry-payload.js +32 -0
  82. package/dist/preview-server/render-queue/open-directory-in-finder.js +7 -5
  83. package/dist/preview-server/render-queue/open-in-file-explorer.js +1 -0
  84. package/dist/preview-server/render-queue/process-still.d.ts +8 -0
  85. package/dist/preview-server/render-queue/process-still.js +50 -0
  86. package/dist/preview-server/render-queue/process-video.d.ts +8 -0
  87. package/dist/preview-server/render-queue/process-video.js +57 -0
  88. package/dist/preview-server/render-queue/queue.d.ts +20 -0
  89. package/dist/preview-server/render-queue/queue.js +169 -0
  90. package/dist/preview-server/render-queue/remove-render.js +3 -2
  91. package/dist/preview-server/routes/add-render.d.ts +3 -0
  92. package/dist/preview-server/routes/add-render.js +52 -0
  93. package/dist/preview-server/routes/open-in-file-explorer.d.ts +3 -0
  94. package/dist/preview-server/routes/open-in-file-explorer.js +14 -0
  95. package/dist/preview-server/routes/remove-render.d.ts +3 -0
  96. package/dist/preview-server/routes/remove-render.js +9 -0
  97. package/dist/preview-server/routes/subscribe-to-file-existence.d.ts +3 -0
  98. package/dist/preview-server/routes/subscribe-to-file-existence.js +13 -0
  99. package/dist/preview-server/routes/unsubscribe-from-file-existence.d.ts +3 -0
  100. package/dist/preview-server/routes/unsubscribe-from-file-existence.js +9 -0
  101. package/dist/preview.js +25 -1
  102. package/dist/render-flows/render.d.ts +35 -0
  103. package/dist/render-flows/render.js +245 -0
  104. package/dist/render-flows/still.d.ts +31 -0
  105. package/dist/render-flows/still.js +168 -0
  106. package/package.json +7 -8
@@ -1,16 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleRemoveRender = void 0;
4
- const _1 = require(".");
5
4
  const parse_body_1 = require("../parse-body");
5
+ const queue_1 = require("./queue");
6
6
  const handleRemoveRender = async (req, res) => {
7
7
  if (req.method === 'OPTIONS') {
8
8
  res.statusCode = 200;
9
9
  res.end();
10
+ return;
10
11
  }
11
12
  try {
12
13
  const body = (await (0, parse_body_1.parseRequestBody)(req));
13
- (0, _1.removeJob)(body.jobId);
14
+ (0, queue_1.removeJob)(body.jobId);
14
15
  res.setHeader('content-type', 'application/json');
15
16
  res.writeHead(200);
16
17
  res.end(JSON.stringify({
@@ -0,0 +1,3 @@
1
+ import type { ApiHandler } from '../api-types';
2
+ import type { AddRenderRequest } from '../render-queue/job';
3
+ export declare const handleAddRender: ApiHandler<AddRenderRequest, undefined>;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleAddRender = void 0;
4
+ const queue_1 = require("../render-queue/queue");
5
+ const handleAddRender = ({ input, entryPoint, remotionRoot, }) => {
6
+ const id = String(Math.random()).replace('0.', '');
7
+ if (input.type === 'video') {
8
+ (0, queue_1.addJob)({
9
+ entryPoint,
10
+ remotionRoot,
11
+ job: {
12
+ cleanup: [],
13
+ // TODO: Allow to change codec
14
+ codec: 'h264',
15
+ compositionId: input.compositionId,
16
+ deletedOutputLocation: false,
17
+ type: 'video',
18
+ status: 'idle',
19
+ id,
20
+ imageFormat: input.imageFormat,
21
+ outName: input.outName,
22
+ quality: input.quality,
23
+ scale: input.scale,
24
+ startedAt: Date.now(),
25
+ verbose: input.verbose,
26
+ },
27
+ });
28
+ }
29
+ if (input.type === 'still') {
30
+ (0, queue_1.addJob)({
31
+ job: {
32
+ compositionId: input.compositionId,
33
+ id: String(Math.random()).replace('0.', ''),
34
+ startedAt: Date.now(),
35
+ type: 'still',
36
+ outName: input.outName,
37
+ status: 'idle',
38
+ imageFormat: input.imageFormat,
39
+ quality: input.quality,
40
+ frame: input.frame,
41
+ scale: input.scale,
42
+ cleanup: [],
43
+ deletedOutputLocation: false,
44
+ verbose: input.verbose,
45
+ },
46
+ entryPoint,
47
+ remotionRoot,
48
+ });
49
+ }
50
+ return Promise.resolve(undefined);
51
+ };
52
+ exports.handleAddRender = handleAddRender;
@@ -0,0 +1,3 @@
1
+ import type { ApiHandler } from '../api-types';
2
+ import type { OpenInFileExplorerRequest } from '../render-queue/job';
3
+ export declare const handleOpenInFileExplorer: ApiHandler<OpenInFileExplorerRequest, void>;
@@ -0,0 +1,14 @@
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.handleOpenInFileExplorer = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const open_directory_in_finder_1 = require("../render-queue/open-directory-in-finder");
9
+ const handleOpenInFileExplorer = ({ input: { directory }, remotionRoot }) => {
10
+ const actualDirectory = path_1.default.resolve(remotionRoot, directory);
11
+ // TODO: Disallow opening file that is not in Remotion CWD
12
+ return (0, open_directory_in_finder_1.openDirectoryInFinder)(actualDirectory);
13
+ };
14
+ exports.handleOpenInFileExplorer = handleOpenInFileExplorer;
@@ -0,0 +1,3 @@
1
+ import type { ApiHandler } from '../api-types';
2
+ import type { RemoveRenderRequest } from '../render-queue/job';
3
+ export declare const handleRemoveRender: ApiHandler<RemoveRenderRequest, undefined>;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleRemoveRender = void 0;
4
+ const queue_1 = require("../render-queue/queue");
5
+ const handleRemoveRender = ({ input: { jobId }, }) => {
6
+ (0, queue_1.removeJob)(jobId);
7
+ return Promise.resolve(undefined);
8
+ };
9
+ exports.handleRemoveRender = handleRemoveRender;
@@ -0,0 +1,3 @@
1
+ import type { ApiHandler } from '../api-types';
2
+ import type { SubscribeToFileExistenceRequest, SubscribeToFileExistenceResponse } from '../render-queue/job';
3
+ export declare const subscribeToFileExistence: ApiHandler<SubscribeToFileExistenceRequest, SubscribeToFileExistenceResponse>;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.subscribeToFileExistence = void 0;
4
+ const file_existence_watchers_1 = require("../file-existence-watchers");
5
+ const subscribeToFileExistence = ({ input: { file }, remotionRoot }) => {
6
+ // TODO: What if the user reloads the page? The file watcher doesn't get cleared
7
+ const { exists } = (0, file_existence_watchers_1.subscribeToFileExistenceWatchers)({
8
+ file,
9
+ remotionRoot,
10
+ });
11
+ return Promise.resolve({ exists });
12
+ };
13
+ exports.subscribeToFileExistence = subscribeToFileExistence;
@@ -0,0 +1,3 @@
1
+ import type { ApiHandler } from '../api-types';
2
+ import type { UnsubscribeFromFileExistenceRequest } from '../render-queue/job';
3
+ export declare const unsubscribeFromFileExistence: ApiHandler<UnsubscribeFromFileExistenceRequest, undefined>;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unsubscribeFromFileExistence = void 0;
4
+ const file_existence_watchers_1 = require("../file-existence-watchers");
5
+ const unsubscribeFromFileExistence = ({ input, remotionRoot }) => {
6
+ (0, file_existence_watchers_1.unsubscribeFromFileExistenceWatchers)({ file: input.file, remotionRoot });
7
+ return Promise.resolve(undefined);
8
+ };
9
+ exports.unsubscribeFromFileExistence = unsubscribeFromFileExistence;
package/dist/preview.js CHANGED
@@ -32,6 +32,24 @@ const waitForLiveEventsListener = () => {
32
32
  });
33
33
  });
34
34
  };
35
+ const getShouldOpenBrowser = () => {
36
+ if (parse_command_line_1.parsedCli['no-open']) {
37
+ return {
38
+ shouldOpenBrowser: false,
39
+ reasonForBrowserDecision: '--no-open specified',
40
+ };
41
+ }
42
+ if (process.env.BROWSER === 'none') {
43
+ return {
44
+ shouldOpenBrowser: false,
45
+ reasonForBrowserDecision: 'env BROWSER=none was set',
46
+ };
47
+ }
48
+ if (config_1.ConfigInternals.getShouldOpenBrowser() === false) {
49
+ return { shouldOpenBrowser: false, reasonForBrowserDecision: 'Config file' };
50
+ }
51
+ return { shouldOpenBrowser: true, reasonForBrowserDecision: 'default' };
52
+ };
35
53
  const previewCommand = async (remotionRoot, args) => {
36
54
  const { file, reason } = (0, entry_point_1.findEntryPoint)(args, remotionRoot);
37
55
  log_1.Log.verbose('Entry point:', file, 'reason:', reason);
@@ -80,7 +98,13 @@ const previewCommand = async (remotionRoot, args) => {
80
98
  else {
81
99
  log_1.Log.info(`Running on http://localhost:${port}`);
82
100
  }
83
- (0, better_opn_1.default)(`http://localhost:${port}`);
101
+ const { reasonForBrowserDecision, shouldOpenBrowser } = getShouldOpenBrowser();
102
+ if (shouldOpenBrowser) {
103
+ (0, better_opn_1.default)(`http://localhost:${port}`);
104
+ }
105
+ else {
106
+ log_1.Log.verbose(`Not opening browser, reason: ${reasonForBrowserDecision}`);
107
+ }
84
108
  await new Promise(noop);
85
109
  };
86
110
  exports.previewCommand = previewCommand;
@@ -0,0 +1,35 @@
1
+ import type { Browser, BrowserExecutable, ChromiumOptions, FfmpegExecutable, FrameRange, ImageFormat, LogLevel } from '@remotion/renderer';
2
+ import type { JobProgressCallback } from '../preview-server/render-queue/job';
3
+ export declare const renderCompFlow: ({ remotionRoot, fullEntryPoint, ffmpegExecutable, ffprobeExecutable, indent, logLevel, browserExecutable, browser, chromiumOptions, scale, shouldOutputImageSequence, publicDir, inputProps, envVariables, puppeteerTimeout, port, height, width, remainingArgs, compositionIdFromUi, entryPointReason, overwrite, quiet, concurrency, frameRange, everyNthFrame, configFileImageFormat, outputLocationFromUI, quality, onProgress, addCleanupCallback, }: {
4
+ remotionRoot: string;
5
+ fullEntryPoint: string;
6
+ entryPointReason: string;
7
+ browserExecutable: BrowserExecutable;
8
+ chromiumOptions: ChromiumOptions;
9
+ ffmpegExecutable: FfmpegExecutable;
10
+ ffprobeExecutable: FfmpegExecutable;
11
+ logLevel: LogLevel;
12
+ browser: Browser;
13
+ scale: number;
14
+ indent: boolean;
15
+ shouldOutputImageSequence: boolean;
16
+ publicDir: string | null;
17
+ inputProps: object;
18
+ envVariables: Record<string, string>;
19
+ puppeteerTimeout: number;
20
+ port: number | null;
21
+ height: number | null;
22
+ width: number | null;
23
+ remainingArgs: string[];
24
+ compositionIdFromUi: string | null;
25
+ outputLocationFromUI: string | null;
26
+ overwrite: boolean;
27
+ quiet: boolean;
28
+ concurrency: number | null;
29
+ frameRange: FrameRange | null;
30
+ everyNthFrame: number;
31
+ configFileImageFormat: ImageFormat | undefined;
32
+ quality: number | undefined;
33
+ onProgress: JobProgressCallback;
34
+ addCleanupCallback: (cb: () => Promise<void>) => void;
35
+ }) => Promise<void>;
@@ -0,0 +1,245 @@
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.renderCompFlow = void 0;
7
+ const renderer_1 = require("@remotion/renderer");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const os_1 = __importDefault(require("os"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const chalk_1 = require("../chalk");
12
+ const get_cli_options_1 = require("../get-cli-options");
13
+ const get_composition_with_dimension_override_1 = require("../get-composition-with-dimension-override");
14
+ const get_filename_1 = require("../get-filename");
15
+ const get_render_media_options_1 = require("../get-render-media-options");
16
+ const image_formats_1 = require("../image-formats");
17
+ const log_1 = require("../log");
18
+ const progress_bar_1 = require("../progress-bar");
19
+ const setup_cache_1 = require("../setup-cache");
20
+ const truthy_1 = require("../truthy");
21
+ const user_passed_output_location_1 = require("../user-passed-output-location");
22
+ const renderCompFlow = async ({ remotionRoot, fullEntryPoint, ffmpegExecutable, ffprobeExecutable, indent, logLevel, browserExecutable, browser, chromiumOptions, scale, shouldOutputImageSequence, publicDir, inputProps, envVariables, puppeteerTimeout, port, height, width, remainingArgs, compositionIdFromUi, entryPointReason, overwrite, quiet, concurrency, frameRange, everyNthFrame, configFileImageFormat, outputLocationFromUI, quality, onProgress, addCleanupCallback, }) => {
23
+ const downloads = [];
24
+ const downloadMap = renderer_1.RenderInternals.makeDownloadMap();
25
+ addCleanupCallback(() => renderer_1.RenderInternals.cleanDownloadMap(downloadMap));
26
+ const ffmpegVersion = await renderer_1.RenderInternals.getFfmpegVersion({
27
+ ffmpegExecutable,
28
+ remotionRoot,
29
+ });
30
+ log_1.Log.verboseAdvanced({ indent, logLevel }, 'FFMPEG Version:', ffmpegVersion ? ffmpegVersion.join('.') : 'Built from source');
31
+ log_1.Log.verboseAdvanced({ indent, logLevel }, 'Browser executable: ', browserExecutable);
32
+ log_1.Log.verboseAdvanced({ indent, logLevel }, 'Asset dirs', downloadMap.assetDir);
33
+ const browserInstance = (0, renderer_1.openBrowser)(browser, {
34
+ browserExecutable,
35
+ shouldDumpIo: renderer_1.RenderInternals.isEqualOrBelowLogLevel(logLevel, 'verbose'),
36
+ chromiumOptions,
37
+ forceDeviceScaleFactor: scale,
38
+ indentationString: indent ? log_1.INDENT_TOKEN + ' ' : '',
39
+ });
40
+ const steps = [
41
+ renderer_1.RenderInternals.isServeUrl(fullEntryPoint) ? null : 'bundling',
42
+ 'rendering',
43
+ shouldOutputImageSequence ? null : 'stitching',
44
+ ].filter(truthy_1.truthy);
45
+ const { urlOrBundle, cleanup: cleanupBundle } = await (0, setup_cache_1.bundleOnCliOrTakeServeUrl)({
46
+ fullPath: fullEntryPoint,
47
+ remotionRoot,
48
+ steps,
49
+ publicDir,
50
+ // TODO: Implement onProgress
51
+ onProgress: () => undefined,
52
+ indentOutput: indent,
53
+ logLevel,
54
+ });
55
+ addCleanupCallback(cleanupBundle);
56
+ const onDownload = (src) => {
57
+ const id = Math.random();
58
+ const download = {
59
+ id,
60
+ name: src,
61
+ progress: 0,
62
+ downloaded: 0,
63
+ totalBytes: null,
64
+ };
65
+ downloads.push(download);
66
+ updateRenderProgress();
67
+ return ({ percent, downloaded, totalSize }) => {
68
+ download.progress = percent;
69
+ download.totalBytes = totalSize;
70
+ download.downloaded = downloaded;
71
+ updateRenderProgress();
72
+ };
73
+ };
74
+ const puppeteerInstance = await browserInstance;
75
+ addCleanupCallback(() => puppeteerInstance.close(false));
76
+ const comps = await (0, renderer_1.getCompositions)(urlOrBundle, {
77
+ inputProps,
78
+ puppeteerInstance,
79
+ envVariables,
80
+ timeoutInMilliseconds: puppeteerTimeout,
81
+ chromiumOptions,
82
+ browserExecutable,
83
+ downloadMap,
84
+ port,
85
+ });
86
+ const { compositionId, config, reason, argsAfterComposition } = await (0, get_composition_with_dimension_override_1.getCompositionWithDimensionOverride)({
87
+ validCompositions: comps,
88
+ height,
89
+ width,
90
+ args: remainingArgs,
91
+ compositionIdFromUi,
92
+ });
93
+ // TODO: Should use codec from UI if explicitly specified
94
+ const { codec, reason: codecReason } = (0, get_cli_options_1.getFinalCodec)({
95
+ downloadName: null,
96
+ outName: (0, user_passed_output_location_1.getUserPassedOutputLocation)(argsAfterComposition),
97
+ });
98
+ (0, get_cli_options_1.validateFfmepgCanUseCodec)(codec, remotionRoot);
99
+ renderer_1.RenderInternals.validateEvenDimensionsWithCodec({
100
+ width: config.width,
101
+ height: config.height,
102
+ codec,
103
+ scale,
104
+ });
105
+ const relativeOutputLocation = (0, get_filename_1.getOutputFilename)({
106
+ codec,
107
+ imageSequence: shouldOutputImageSequence,
108
+ compositionName: compositionId,
109
+ defaultExtension: renderer_1.RenderInternals.getFileExtensionFromCodec(codec, 'final'),
110
+ args: argsAfterComposition,
111
+ indent,
112
+ fromUi: outputLocationFromUI,
113
+ logLevel,
114
+ });
115
+ log_1.Log.infoAdvanced({ indent, logLevel }, chalk_1.chalk.gray(`Entry point = ${fullEntryPoint} (${entryPointReason}), Composition = ${compositionId} (${reason}), Codec = ${codec} (${codecReason}), Output = ${relativeOutputLocation}`));
116
+ const absoluteOutputFile = (0, get_cli_options_1.getAndValidateAbsoluteOutputFile)(relativeOutputLocation, overwrite);
117
+ const outputDir = shouldOutputImageSequence
118
+ ? absoluteOutputFile
119
+ : await fs_1.default.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'react-motion-render'));
120
+ log_1.Log.verboseAdvanced({ indent, logLevel }, 'Output dir', outputDir);
121
+ const renderProgress = (0, progress_bar_1.createOverwriteableCliOutput)({
122
+ quiet,
123
+ });
124
+ const realFrameRange = renderer_1.RenderInternals.getRealFrameRange(config.durationInFrames, frameRange);
125
+ const totalFrames = renderer_1.RenderInternals.getFramesToRender(realFrameRange, everyNthFrame);
126
+ let encodedFrames = 0;
127
+ let renderedFrames = 0;
128
+ let encodedDoneIn = null;
129
+ let renderedDoneIn = null;
130
+ let stitchStage = 'encoding';
131
+ const updateRenderProgress = () => {
132
+ if (totalFrames.length === 0) {
133
+ throw new Error('totalFrames should not be 0');
134
+ }
135
+ const { output, message, progress } = (0, progress_bar_1.makeRenderingAndStitchingProgress)({
136
+ rendering: {
137
+ frames: renderedFrames,
138
+ totalFrames: totalFrames.length,
139
+ concurrency: renderer_1.RenderInternals.getActualConcurrency(concurrency),
140
+ doneIn: renderedDoneIn,
141
+ steps,
142
+ },
143
+ stitching: shouldOutputImageSequence
144
+ ? null
145
+ : {
146
+ doneIn: encodedDoneIn,
147
+ frames: encodedFrames,
148
+ stage: stitchStage,
149
+ steps,
150
+ totalFrames: totalFrames.length,
151
+ codec,
152
+ },
153
+ downloads,
154
+ bundling: {
155
+ message: 'Bundled',
156
+ progress: 1,
157
+ },
158
+ }, indent);
159
+ onProgress({ progress, message });
160
+ return renderProgress.update(output);
161
+ };
162
+ // TODO: Should take the one from the UI instead
163
+ const imageFormat = (0, image_formats_1.getImageFormat)(shouldOutputImageSequence ? undefined : codec, configFileImageFormat);
164
+ if (shouldOutputImageSequence) {
165
+ fs_1.default.mkdirSync(absoluteOutputFile, {
166
+ recursive: true,
167
+ });
168
+ if (imageFormat === 'none') {
169
+ throw new Error(`Cannot render an image sequence with a codec that renders no images. codec = ${codec}, imageFormat = ${imageFormat}`);
170
+ }
171
+ await (0, renderer_1.renderFrames)({
172
+ config,
173
+ imageFormat,
174
+ inputProps,
175
+ onFrameUpdate: (rendered) => {
176
+ renderedFrames = rendered;
177
+ updateRenderProgress();
178
+ },
179
+ onStart: () => undefined,
180
+ onDownload: (src) => {
181
+ if (src.startsWith('data:')) {
182
+ log_1.Log.infoAdvanced({ indent, logLevel }, '\nWriting Data URL to file: ', src.substring(0, 30) + '...');
183
+ }
184
+ else {
185
+ log_1.Log.infoAdvanced({ indent, logLevel }, '\nDownloading asset... ', src);
186
+ }
187
+ },
188
+ outputDir,
189
+ serveUrl: urlOrBundle,
190
+ dumpBrowserLogs: renderer_1.RenderInternals.isEqualOrBelowLogLevel(logLevel, 'verbose'),
191
+ everyNthFrame,
192
+ envVariables,
193
+ frameRange,
194
+ concurrency,
195
+ puppeteerInstance,
196
+ quality,
197
+ timeoutInMilliseconds: puppeteerTimeout,
198
+ chromiumOptions,
199
+ scale,
200
+ ffmpegExecutable,
201
+ ffprobeExecutable,
202
+ browserExecutable,
203
+ port,
204
+ downloadMap,
205
+ });
206
+ updateRenderProgress();
207
+ log_1.Log.infoAdvanced({ indent, logLevel });
208
+ log_1.Log.infoAdvanced({ indent, logLevel }, chalk_1.chalk.cyan(`▶ ${absoluteOutputFile}`));
209
+ }
210
+ const options = await (0, get_render_media_options_1.getRenderMediaOptions)({
211
+ config,
212
+ outputLocation: absoluteOutputFile,
213
+ serveUrl: urlOrBundle,
214
+ codec,
215
+ remotionRoot,
216
+ });
217
+ await (0, renderer_1.renderMedia)({
218
+ ...options,
219
+ onProgress: (update) => {
220
+ encodedDoneIn = update.encodedDoneIn;
221
+ encodedFrames = update.encodedFrames;
222
+ renderedDoneIn = update.renderedDoneIn;
223
+ stitchStage = update.stitchStage;
224
+ renderedFrames = update.renderedFrames;
225
+ updateRenderProgress();
226
+ },
227
+ puppeteerInstance,
228
+ onDownload,
229
+ downloadMap,
230
+ onSlowestFrames: (slowestFrames) => {
231
+ log_1.Log.verboseAdvanced({ indent, logLevel });
232
+ log_1.Log.verboseAdvanced({ indent, logLevel }, `Slowest frames:`);
233
+ slowestFrames.forEach(({ frame, time }) => {
234
+ log_1.Log.verboseAdvanced({ indent, logLevel }, `Frame ${frame} (${time.toFixed(3)}ms)`);
235
+ });
236
+ },
237
+ printLog: (...str) => log_1.Log.verboseAdvanced({ indent, logLevel }, ...str),
238
+ });
239
+ log_1.Log.infoAdvanced({ indent, logLevel });
240
+ log_1.Log.infoAdvanced({ indent, logLevel }, chalk_1.chalk.cyan(`▶ ${absoluteOutputFile}`));
241
+ for (const line of renderer_1.RenderInternals.perf.getPerf()) {
242
+ log_1.Log.verboseAdvanced({ indent, logLevel }, line);
243
+ }
244
+ };
245
+ exports.renderCompFlow = renderCompFlow;
@@ -0,0 +1,31 @@
1
+ import type { Browser, BrowserExecutable, ChromiumOptions, FfmpegExecutable, ImageFormat, LogLevel, StillImageFormat } from '@remotion/renderer';
2
+ import type { JobProgressCallback } from '../preview-server/render-queue/job';
3
+ export declare const renderStillFlow: ({ remotionRoot, fullEntryPoint, entryPointReason, remainingArgs, browser, browserExecutable, chromiumOptions, envVariables, ffmpegExecutable, ffprobeExecutable, height, inputProps, overwrite, port, publicDir, puppeteerTimeout, quality, scale, stillFrame, width, compositionIdFromUi, imageFormatFromUi, logLevel, configFileImageFormat, onProgress, indentOutput, addCleanupCallback, }: {
4
+ remotionRoot: string;
5
+ fullEntryPoint: string;
6
+ entryPointReason: string;
7
+ remainingArgs: string[];
8
+ inputProps: object;
9
+ envVariables: Record<string, string>;
10
+ quality: number | undefined;
11
+ browser: Browser;
12
+ stillFrame: number;
13
+ browserExecutable: BrowserExecutable;
14
+ chromiumOptions: ChromiumOptions;
15
+ scale: number;
16
+ ffmpegExecutable: FfmpegExecutable;
17
+ ffprobeExecutable: FfmpegExecutable;
18
+ overwrite: boolean;
19
+ puppeteerTimeout: number;
20
+ port: number | null;
21
+ publicDir: string | null;
22
+ height: number | null;
23
+ width: number | null;
24
+ compositionIdFromUi: string | null;
25
+ imageFormatFromUi: StillImageFormat | null;
26
+ logLevel: LogLevel;
27
+ configFileImageFormat: ImageFormat | undefined;
28
+ onProgress: JobProgressCallback;
29
+ indentOutput: boolean;
30
+ addCleanupCallback: (cb: () => Promise<void>) => void;
31
+ }) => Promise<void>;
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ // Prints to CLI and also reports back to browser
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.renderStillFlow = void 0;
8
+ const renderer_1 = require("@remotion/renderer");
9
+ const fs_1 = require("fs");
10
+ const path_1 = __importDefault(require("path"));
11
+ const chalk_1 = require("../chalk");
12
+ const determine_image_format_1 = require("../determine-image-format");
13
+ const get_cli_options_1 = require("../get-cli-options");
14
+ const get_composition_with_dimension_override_1 = require("../get-composition-with-dimension-override");
15
+ const log_1 = require("../log");
16
+ const parse_command_line_1 = require("../parse-command-line");
17
+ const progress_bar_1 = require("../progress-bar");
18
+ const setup_cache_1 = require("../setup-cache");
19
+ const truthy_1 = require("../truthy");
20
+ const user_passed_output_location_1 = require("../user-passed-output-location");
21
+ const renderStillFlow = async ({ remotionRoot, fullEntryPoint, entryPointReason, remainingArgs, browser, browserExecutable, chromiumOptions, envVariables, ffmpegExecutable, ffprobeExecutable, height, inputProps, overwrite, port, publicDir, puppeteerTimeout, quality, scale, stillFrame, width, compositionIdFromUi, imageFormatFromUi, logLevel, configFileImageFormat, onProgress, indentOutput, addCleanupCallback, }) => {
22
+ var _a;
23
+ const downloads = [];
24
+ const aggregate = {
25
+ rendering: null,
26
+ downloads,
27
+ stitching: null,
28
+ bundling: {
29
+ message: null,
30
+ progress: 0,
31
+ },
32
+ };
33
+ let renderProgress = null;
34
+ const updateProgress = () => {
35
+ const { output, progress, message } = (0, progress_bar_1.makeRenderingAndStitchingProgress)(aggregate, indentOutput);
36
+ if (renderProgress) {
37
+ renderProgress.update(output);
38
+ }
39
+ onProgress({ progress, message });
40
+ };
41
+ log_1.Log.verboseAdvanced({ indent: indentOutput, logLevel }, 'Browser executable: ', browserExecutable);
42
+ const shouldDumpIo = renderer_1.RenderInternals.isEqualOrBelowLogLevel(logLevel, 'verbose');
43
+ const browserInstance = (0, renderer_1.openBrowser)(browser, {
44
+ browserExecutable,
45
+ chromiumOptions,
46
+ shouldDumpIo,
47
+ forceDeviceScaleFactor: scale,
48
+ indentationString: indentOutput ? log_1.INDENT_TOKEN + ' ' : '',
49
+ });
50
+ const steps = [
51
+ renderer_1.RenderInternals.isServeUrl(fullEntryPoint) ? null : 'bundling',
52
+ 'rendering',
53
+ ].filter(truthy_1.truthy);
54
+ const { cleanup: cleanupBundle, urlOrBundle } = await (0, setup_cache_1.bundleOnCliOrTakeServeUrl)({
55
+ fullPath: fullEntryPoint,
56
+ remotionRoot,
57
+ steps,
58
+ publicDir,
59
+ onProgress: (progress) => {
60
+ aggregate.bundling = progress;
61
+ updateProgress();
62
+ },
63
+ indentOutput,
64
+ logLevel,
65
+ });
66
+ addCleanupCallback(cleanupBundle);
67
+ const puppeteerInstance = await browserInstance;
68
+ addCleanupCallback(() => puppeteerInstance.close(false));
69
+ const downloadMap = renderer_1.RenderInternals.makeDownloadMap();
70
+ addCleanupCallback(() => renderer_1.RenderInternals.cleanDownloadMap(downloadMap));
71
+ const comps = await (0, renderer_1.getCompositions)(urlOrBundle, {
72
+ inputProps,
73
+ puppeteerInstance,
74
+ envVariables,
75
+ timeoutInMilliseconds: puppeteerTimeout,
76
+ chromiumOptions,
77
+ port,
78
+ browserExecutable,
79
+ ffmpegExecutable,
80
+ ffprobeExecutable,
81
+ downloadMap,
82
+ });
83
+ const { compositionId, config, reason, argsAfterComposition } = await (0, get_composition_with_dimension_override_1.getCompositionWithDimensionOverride)({
84
+ validCompositions: comps,
85
+ height,
86
+ width,
87
+ args: remainingArgs,
88
+ compositionIdFromUi,
89
+ });
90
+ const { format: imageFormat, source } = (0, determine_image_format_1.determineFinalImageFormat)({
91
+ cliFlag: (_a = parse_command_line_1.parsedCli['image-format']) !== null && _a !== void 0 ? _a : null,
92
+ configImageFormat: configFileImageFormat !== null && configFileImageFormat !== void 0 ? configFileImageFormat : null,
93
+ downloadName: null,
94
+ outName: (0, user_passed_output_location_1.getUserPassedOutputLocation)(argsAfterComposition),
95
+ isLambda: false,
96
+ fromUi: imageFormatFromUi,
97
+ });
98
+ const relativeOutputLocation = (0, user_passed_output_location_1.getOutputLocation)({
99
+ compositionId,
100
+ defaultExtension: imageFormat,
101
+ args: argsAfterComposition,
102
+ });
103
+ const absoluteOutputLocation = (0, get_cli_options_1.getAndValidateAbsoluteOutputFile)(relativeOutputLocation, overwrite);
104
+ (0, fs_1.mkdirSync)(path_1.default.join(absoluteOutputLocation, '..'), {
105
+ recursive: true,
106
+ });
107
+ log_1.Log.infoAdvanced({ indent: indentOutput, logLevel }, chalk_1.chalk.gray(`Entry point = ${fullEntryPoint} (${entryPointReason}), Output = ${relativeOutputLocation}, Format = ${imageFormat} (${source}), Composition = ${compositionId} (${reason})`));
108
+ renderProgress = (0, progress_bar_1.createOverwriteableCliOutput)({
109
+ quiet: (0, parse_command_line_1.quietFlagProvided)(),
110
+ });
111
+ const renderStart = Date.now();
112
+ aggregate.rendering = {
113
+ frames: 0,
114
+ concurrency: 1,
115
+ doneIn: null,
116
+ steps,
117
+ totalFrames: 1,
118
+ };
119
+ updateProgress();
120
+ const onDownload = (src) => {
121
+ const id = Math.random();
122
+ const download = {
123
+ id,
124
+ name: src,
125
+ progress: 0,
126
+ downloaded: 0,
127
+ totalBytes: null,
128
+ };
129
+ downloads.push(download);
130
+ updateProgress();
131
+ return ({ percent }) => {
132
+ download.progress = percent;
133
+ updateProgress();
134
+ };
135
+ };
136
+ await (0, renderer_1.renderStill)({
137
+ composition: config,
138
+ frame: stillFrame,
139
+ output: absoluteOutputLocation,
140
+ serveUrl: urlOrBundle,
141
+ quality,
142
+ dumpBrowserLogs: shouldDumpIo,
143
+ envVariables,
144
+ imageFormat,
145
+ inputProps,
146
+ chromiumOptions,
147
+ timeoutInMilliseconds: puppeteerTimeout,
148
+ scale,
149
+ ffmpegExecutable,
150
+ browserExecutable,
151
+ overwrite,
152
+ onDownload,
153
+ port,
154
+ downloadMap,
155
+ puppeteerInstance,
156
+ });
157
+ aggregate.rendering = {
158
+ frames: 1,
159
+ concurrency: 1,
160
+ doneIn: Date.now() - renderStart,
161
+ steps,
162
+ totalFrames: 1,
163
+ };
164
+ updateProgress();
165
+ log_1.Log.infoAdvanced({ indent: indentOutput, logLevel });
166
+ log_1.Log.infoAdvanced({ indent: indentOutput, logLevel }, chalk_1.chalk.cyan(`▶️ ${absoluteOutputLocation}`));
167
+ };
168
+ exports.renderStillFlow = renderStillFlow;