@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
package/LICENSE.md CHANGED
@@ -7,7 +7,7 @@ Depending on the type of your legal entity, you are granted permission to use Re
7
7
 
8
8
  ## Free license
9
9
 
10
- Copyright © 2022 [Remotion](https://www.remotion.dev/)
10
+ Copyright © 2023 [Remotion](https://www.remotion.dev/)
11
11
 
12
12
  ### Eligibility
13
13
 
@@ -54,5 +54,6 @@ export declare const ConfigInternals: {
54
54
  getEntryPoint: () => string | null;
55
55
  getNumberOfGifLoops: () => import("./number-of-gif-loops").Loop;
56
56
  getWebpackPolling: () => number | null;
57
+ getShouldOpenBrowser: () => boolean;
57
58
  };
58
59
  export declare const overrideRemotion: () => void;
@@ -71,6 +71,7 @@ const max_timeline_tracks_2 = require("./max-timeline-tracks");
71
71
  const muted_1 = require("./muted");
72
72
  const number_of_gif_loops_1 = require("./number-of-gif-loops");
73
73
  const number_of_shared_audio_tags_1 = require("./number-of-shared-audio-tags");
74
+ const open_browser_1 = require("./open-browser");
74
75
  const output_location_2 = require("./output-location");
75
76
  const override_webpack_2 = require("./override-webpack");
76
77
  const overwrite_2 = require("./overwrite");
@@ -90,6 +91,7 @@ exports.Config = {
90
91
  setKeyboardShortcutsEnabled: keyboard_shortcuts_1.setKeyboardShortcutsEnabled,
91
92
  setNumberOfSharedAudioTags: number_of_shared_audio_tags_1.setNumberOfSharedAudioTags,
92
93
  setWebpackPollingInMilliseconds: webpack_poll_1.setWebpackPollingInMilliseconds,
94
+ setShouldOpenBrowser: open_browser_1.setShouldOpenBrowser,
93
95
  },
94
96
  Bundling: {
95
97
  overrideWebpackConfig: override_webpack_2.overrideWebpackConfig,
@@ -187,6 +189,7 @@ exports.ConfigInternals = {
187
189
  getEntryPoint: entry_point_1.getEntryPoint,
188
190
  getNumberOfGifLoops: number_of_gif_loops_1.getNumberOfGifLoops,
189
191
  getWebpackPolling: webpack_poll_1.getWebpackPolling,
192
+ getShouldOpenBrowser: open_browser_1.getShouldOpenBrowser,
190
193
  };
191
194
  const overrideRemotion = () => {
192
195
  Object.assign(remotion_1.Config, exports.Config);
@@ -1,3 +1,3 @@
1
1
  import type { LogLevel } from '@remotion/renderer';
2
- export declare const getLogLevel: () => "error" | "verbose" | "info" | "warn";
2
+ export declare const getLogLevel: () => "verbose" | "error" | "info" | "warn";
3
3
  export declare const setLogLevel: (newLogLevel: LogLevel) => void;
@@ -0,0 +1,2 @@
1
+ export declare const setShouldOpenBrowser: (_should: boolean) => void;
2
+ export declare const getShouldOpenBrowser: () => boolean;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getShouldOpenBrowser = exports.setShouldOpenBrowser = void 0;
4
+ let should = true;
5
+ const setShouldOpenBrowser = (_should) => {
6
+ if (typeof _should !== 'boolean') {
7
+ throw new TypeError(`Expected a boolean, got ${typeof _should} (${should})`);
8
+ }
9
+ should = _should;
10
+ };
11
+ exports.setShouldOpenBrowser = setShouldOpenBrowser;
12
+ const getShouldOpenBrowser = () => {
13
+ return should;
14
+ };
15
+ exports.getShouldOpenBrowser = getShouldOpenBrowser;
@@ -0,0 +1 @@
1
+ export declare const convertEntryPointToServeUrl: (entryPoint: string) => string;
@@ -0,0 +1,15 @@
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.convertEntryPointToServeUrl = void 0;
7
+ const renderer_1 = require("@remotion/renderer");
8
+ const path_1 = __importDefault(require("path"));
9
+ const convertEntryPointToServeUrl = (entryPoint) => {
10
+ const fullPath = renderer_1.RenderInternals.isServeUrl(entryPoint)
11
+ ? entryPoint
12
+ : path_1.default.resolve(process.cwd(), entryPoint);
13
+ return fullPath;
14
+ };
15
+ exports.convertEntryPointToServeUrl = convertEntryPointToServeUrl;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export declare const CollapsableOptions: React.FC<{
3
+ children: React.ReactNode;
4
+ showLabel: string;
5
+ hideLabel: string;
6
+ }>;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CollapsableOptions = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const colors_1 = require("../helpers/colors");
7
+ const z_index_1 = require("../state/z-index");
8
+ const layout_1 = require("./layout");
9
+ const TimelineCollapseToggle_1 = require("./Timeline/TimelineCollapseToggle");
10
+ const container = {
11
+ marginLeft: 16,
12
+ height: 40,
13
+ display: 'flex',
14
+ flexDirection: 'row',
15
+ alignItems: 'center',
16
+ };
17
+ const buttonStyle = {
18
+ border: 'none',
19
+ padding: 0,
20
+ appearance: 'none',
21
+ display: 'flex',
22
+ flexDirection: 'row',
23
+ alignItems: 'center',
24
+ fontSize: 14,
25
+ color: colors_1.LIGHT_TEXT,
26
+ };
27
+ const CollapsableOptions = ({ children, showLabel, hideLabel }) => {
28
+ const [show, setShow] = (0, react_1.useState)(false);
29
+ const { tabIndex } = (0, z_index_1.useZIndex)();
30
+ const onClick = (0, react_1.useCallback)(() => {
31
+ setShow((s) => !s);
32
+ }, []);
33
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: container, children: (0, jsx_runtime_1.jsxs)("button", { style: buttonStyle, tabIndex: tabIndex, onClick: onClick, type: "button", children: [(0, jsx_runtime_1.jsx)(TimelineCollapseToggle_1.TimelineCollapseToggle, { color: colors_1.LIGHT_TEXT, collapsed: !show }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { block: true, x: 1 }), show ? hideLabel : showLabel] }) }), show ? children : null] }));
34
+ };
35
+ exports.CollapsableOptions = CollapsableOptions;
@@ -0,0 +1,5 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ import React from 'react';
3
+ export declare const InlineAction: React.FC<PropsWithChildren<{
4
+ onClick: React.MouseEventHandler<HTMLAnchorElement> | undefined;
5
+ }>>;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InlineAction = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const colors_1 = require("../helpers/colors");
7
+ const z_index_1 = require("../state/z-index");
8
+ const InlineAction = ({ children, onClick }) => {
9
+ const { tabIndex } = (0, z_index_1.useZIndex)();
10
+ const [hovered, setHovered] = (0, react_1.useState)(false);
11
+ const onPointerEnter = (0, react_1.useCallback)(() => {
12
+ setHovered(true);
13
+ }, []);
14
+ const onPointerLeave = (0, react_1.useCallback)(() => {
15
+ setHovered(false);
16
+ }, []);
17
+ const style = (0, react_1.useMemo)(() => {
18
+ return {
19
+ border: 'none',
20
+ background: hovered ? colors_1.CLEAR_HOVER : 'transparent',
21
+ height: 24,
22
+ width: 24,
23
+ display: 'inline-flex',
24
+ justifyContent: 'center',
25
+ alignItems: 'center',
26
+ borderRadius: 3,
27
+ opacity: hovered ? 1 : 0.6,
28
+ };
29
+ }, [hovered]);
30
+ return (
31
+ // <div> because cannot use button inside a button
32
+ (0, jsx_runtime_1.jsx)("a", { onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, onClick: onClick, style: style, tabIndex: tabIndex, children: children }));
33
+ };
34
+ exports.InlineAction = InlineAction;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { TCompMetadata } from 'remotion';
3
- export declare const COMPOSITION_ITEM_HEIGHT = 32;
4
3
  export declare const RenderButton: React.FC<{
5
4
  composition: TCompMetadata;
5
+ visible: boolean;
6
6
  }>;
@@ -1,53 +1,43 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RenderButton = exports.COMPOSITION_ITEM_HEIGHT = void 0;
3
+ exports.RenderButton = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const colors_1 = require("../helpers/colors");
6
+ const get_default_out_name_1 = require("../../get-default-out-name");
7
7
  const render_1 = require("../icons/render");
8
8
  const modals_1 = require("../state/modals");
9
- const z_index_1 = require("../state/z-index");
10
- exports.COMPOSITION_ITEM_HEIGHT = 32;
11
- const itemStyle = {
12
- display: 'flex',
13
- cursor: 'default',
14
- alignItems: 'center',
15
- justifyContent: 'center',
16
- marginBottom: 1,
17
- appearance: 'none',
18
- border: 'none',
19
- height: exports.COMPOSITION_ITEM_HEIGHT,
20
- };
21
- const RenderButton = ({ composition }) => {
22
- const [hovered, setHovered] = (0, react_1.useState)(false);
9
+ const InlineAction_1 = require("./InlineAction");
10
+ const RenderButton = ({ composition, visible }) => {
23
11
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
24
- const onPointerEnter = (0, react_1.useCallback)(() => {
25
- setHovered(true);
26
- }, []);
27
- const onPointerLeave = (0, react_1.useCallback)(() => {
28
- setHovered(false);
29
- }, []);
30
- const { tabIndex } = (0, z_index_1.useZIndex)();
31
- const style = (0, react_1.useMemo)(() => {
32
- return {
33
- ...itemStyle,
34
- backgroundColor: hovered ? colors_1.CLEAR_HOVER : 'transparent',
35
- color: hovered ? 'white' : colors_1.LIGHT_TEXT,
36
- };
37
- }, [hovered]);
38
12
  const iconStyle = (0, react_1.useMemo)(() => {
39
13
  return {
40
14
  style: {
41
- height: 14,
15
+ height: 12,
42
16
  },
43
17
  };
44
18
  }, []);
45
- const onClick = (0, react_1.useCallback)(() => {
19
+ const onClick = (0, react_1.useCallback)((e) => {
20
+ var _a, _b, _c, _d, _e;
21
+ e.stopPropagation();
46
22
  setSelectedModal({
47
23
  type: 'render',
48
- composition,
24
+ compositionId: composition.id,
25
+ initialFrame: 0,
26
+ // TODO: JPEG for video, PNG for image
27
+ initialImageFormat: 'png',
28
+ // TODO: Determine defaults from config file
29
+ initialQuality: (_b = (_a = window.remotion_renderDefaults) === null || _a === void 0 ? void 0 : _a.quality) !== null && _b !== void 0 ? _b : 80,
30
+ initialScale: (_d = (_c = window.remotion_renderDefaults) === null || _c === void 0 ? void 0 : _c.scale) !== null && _d !== void 0 ? _d : 1,
31
+ initialVerbose: ((_e = window.remotion_renderDefaults) === null || _e === void 0 ? void 0 : _e.logLevel) === 'verbose',
32
+ initialOutName: (0, get_default_out_name_1.getDefaultOutLocation)({
33
+ compositionName: composition.id,
34
+ defaultExtension: 'png',
35
+ }),
49
36
  });
50
37
  }, [composition, setSelectedModal]);
51
- return ((0, jsx_runtime_1.jsx)("button", { style: style, tabIndex: tabIndex, onClick: onClick, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, type: "button", children: (0, jsx_runtime_1.jsx)(render_1.RenderIcon, { svgProps: iconStyle, color: hovered ? 'white' : colors_1.LIGHT_TEXT }) }));
38
+ if (!visible) {
39
+ return null;
40
+ }
41
+ return ((0, jsx_runtime_1.jsx)(InlineAction_1.InlineAction, { onClick: onClick, children: (0, jsx_runtime_1.jsx)(render_1.RenderIcon, { svgProps: iconStyle }) }));
52
42
  };
53
43
  exports.RenderButton = RenderButton;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import type { RenderJob } from '../../../preview-server/render-queue/job';
3
+ export declare const RenderErrorModal: React.FC<{
4
+ job: RenderJob;
5
+ }>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RenderErrorModal = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const Button_1 = require("../../../preview-server/error-overlay/remotion-overlay/Button");
7
+ const make_retry_payload_1 = require("../../../preview-server/render-queue/make-retry-payload");
8
+ const modals_1 = require("../../state/modals");
9
+ const layout_1 = require("../layout");
10
+ const ModalContainer_1 = require("../ModalContainer");
11
+ const ModalHeader_1 = require("../ModalHeader");
12
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
13
+ const actions_1 = require("../RenderQueue/actions");
14
+ const container = {
15
+ padding: 20,
16
+ maxWidth: 1200,
17
+ paddingTop: 0,
18
+ };
19
+ const codeBlock = {
20
+ backgroundColor: 'black',
21
+ whiteSpace: 'pre',
22
+ padding: 12,
23
+ borderRadius: 4,
24
+ fontFamily: 'monospace',
25
+ overflow: 'auto',
26
+ maxHeight: 300,
27
+ };
28
+ const spacer = {
29
+ height: layout_1.SPACING_UNIT,
30
+ width: layout_1.SPACING_UNIT,
31
+ };
32
+ const buttonRow = {
33
+ display: 'flex',
34
+ flexDirection: 'row',
35
+ justifyContent: 'flex-end',
36
+ };
37
+ const RenderErrorModal = ({ job }) => {
38
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
39
+ const onQuit = (0, react_1.useCallback)(() => {
40
+ setSelectedModal(null);
41
+ }, [setSelectedModal]);
42
+ const onRetry = (0, react_1.useCallback)(() => {
43
+ const retryPayload = (0, make_retry_payload_1.makeRetryPayload)(job);
44
+ setSelectedModal(retryPayload);
45
+ }, [job, setSelectedModal]);
46
+ const onClickOnRemove = (0, react_1.useCallback)(() => {
47
+ setSelectedModal(null);
48
+ (0, actions_1.removeRenderJob)(job).catch((err) => {
49
+ var _a;
50
+ (_a = NotificationCenter_1.notificationCenter.current) === null || _a === void 0 ? void 0 : _a.addNotification({
51
+ content: 'Failed to remove render job: ' + err.message,
52
+ created: Date.now(),
53
+ duration: 2000,
54
+ id: String(Math.random()),
55
+ });
56
+ console.log(err);
57
+ });
58
+ }, [job, setSelectedModal]);
59
+ if (job.status !== 'failed') {
60
+ throw new Error('should not have rendered this modal');
61
+ }
62
+ return ((0, jsx_runtime_1.jsxs)(ModalContainer_1.ModalContainer, { onOutsideClick: onQuit, onEscape: onQuit, children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.NewCompHeader, { title: `Render ${job.compositionId}` }), (0, jsx_runtime_1.jsxs)("div", { style: container, children: [(0, jsx_runtime_1.jsx)("p", { children: "The render failed because of the following error:" }), (0, jsx_runtime_1.jsx)("div", { style: codeBlock, children: job.error.stack }), (0, jsx_runtime_1.jsx)("div", { style: spacer }), (0, jsx_runtime_1.jsxs)("div", { style: buttonRow, children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: onClickOnRemove, children: "Remove render" }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: onRetry, children: "Retry" }), (0, jsx_runtime_1.jsx)("div", { style: spacer }), (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: onQuit, children: "Close" })] })] })] }));
63
+ };
64
+ exports.RenderErrorModal = RenderErrorModal;
@@ -1,5 +1,11 @@
1
+ import type { StillImageFormat } from '@remotion/renderer';
1
2
  import React from 'react';
2
- import type { TCompMetadata } from 'remotion';
3
3
  export declare const RenderModal: React.FC<{
4
- composition: TCompMetadata;
4
+ compositionId: string;
5
+ initialFrame: number;
6
+ initialImageFormat: StillImageFormat;
7
+ initialQuality: number | null;
8
+ initialScale: number;
9
+ initialVerbose: boolean;
10
+ initialOutName: string;
5
11
  }>;
@@ -3,13 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RenderModal = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const get_default_out_name_1 = require("../../../get-default-out-name");
7
6
  const Button_1 = require("../../../preview-server/error-overlay/remotion-overlay/Button");
7
+ const colors_1 = require("../../helpers/colors");
8
+ const use_file_existence_1 = require("../../helpers/use-file-existence");
8
9
  const modals_1 = require("../../state/modals");
10
+ const CollapsableOptions_1 = require("../CollapsableOptions");
9
11
  const layout_1 = require("../layout");
10
12
  const ModalContainer_1 = require("../ModalContainer");
11
13
  const ModalHeader_1 = require("../ModalHeader");
14
+ const InputDragger_1 = require("../NewComposition/InputDragger");
12
15
  const RemInput_1 = require("../NewComposition/RemInput");
16
+ const ValidationMessage_1 = require("../NewComposition/ValidationMessage");
17
+ const actions_1 = require("../RenderQueue/actions");
18
+ const SegmentedControl_1 = require("../SegmentedControl");
13
19
  const SidebarContent_1 = require("../SidebarContent");
14
20
  const initialState = { type: 'idle' };
15
21
  const reducer = (state, action) => {
@@ -30,61 +36,227 @@ const reducer = (state, action) => {
30
36
  }
31
37
  return state;
32
38
  };
33
- const container = {
34
- padding: 20,
39
+ const container = {};
40
+ const optionRow = {
41
+ display: 'flex',
42
+ flexDirection: 'row',
43
+ alignItems: 'flex-start',
44
+ minHeight: 40,
45
+ paddingLeft: 16,
46
+ paddingRight: 16,
35
47
  };
36
- const RenderModal = ({ composition, }) => {
48
+ const label = {
49
+ width: 150,
50
+ fontSize: 14,
51
+ lineHeight: '40px',
52
+ color: colors_1.LIGHT_TEXT,
53
+ };
54
+ const rightRow = {
55
+ display: 'flex',
56
+ flexDirection: 'row',
57
+ justifyContent: 'flex-end',
58
+ alignSelf: 'center',
59
+ flex: 1,
60
+ };
61
+ const buttonRow = {
62
+ display: 'flex',
63
+ flexDirection: 'row',
64
+ justifyContent: 'flex-end',
65
+ borderTop: '1px solid black',
66
+ paddingTop: 8,
67
+ paddingBottom: 8,
68
+ paddingLeft: 16,
69
+ paddingRight: 16,
70
+ };
71
+ const input = {
72
+ minWidth: 250,
73
+ textAlign: 'right',
74
+ };
75
+ const MIN_QUALITY = 1;
76
+ const MAX_QUALITY = 100;
77
+ const MIN_SCALE = 0.1;
78
+ const MAX_SCALE = 10;
79
+ // TODO: Prevent rendering when preview server is disconnected
80
+ const RenderModal = ({ compositionId, initialFrame, initialImageFormat, initialQuality, initialScale, initialVerbose, initialOutName, }) => {
37
81
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
38
82
  const onQuit = (0, react_1.useCallback)(() => {
39
83
  setSelectedModal(null);
40
84
  }, [setSelectedModal]);
41
85
  const isMounted = (0, react_1.useRef)(true);
42
86
  const [state, dispatch] = (0, react_1.useReducer)(reducer, initialState);
43
- // TODO: Allow to change out name
44
- const [outName] = (0, react_1.useState)(() => (0, get_default_out_name_1.getDefaultOutLocation)({
45
- compositionName: composition.id,
46
- // TODO: Set default extension
47
- defaultExtension: 'png',
48
- }));
87
+ const [frame, setFrame] = (0, react_1.useState)(() => initialFrame);
88
+ const [imageFormat, setImageFormat] = (0, react_1.useState)(() => initialImageFormat);
89
+ const [quality, setQuality] = (0, react_1.useState)(() => initialQuality !== null && initialQuality !== void 0 ? initialQuality : 80);
90
+ const [scale, setScale] = (0, react_1.useState)(() => initialScale);
91
+ const [verbose, setVerboseLogging] = (0, react_1.useState)(() => initialVerbose);
92
+ const [outName, setOutName] = (0, react_1.useState)(() => initialOutName);
49
93
  const dispatchIfMounted = (0, react_1.useCallback)((payload) => {
50
94
  if (isMounted.current === false)
51
95
  return;
52
96
  dispatch(payload);
53
97
  }, []);
54
- const onClick = (0, react_1.useCallback)(() => {
98
+ const onValueChange = (0, react_1.useCallback)((e) => {
99
+ setOutName(e.target.value);
100
+ }, []);
101
+ const setPng = (0, react_1.useCallback)(() => {
102
+ setImageFormat('png');
103
+ setOutName((prev) => {
104
+ if (prev.endsWith('.jpeg') || prev.endsWith('.jpg')) {
105
+ return prev.replace(/.jpe?g$/g, '.png');
106
+ }
107
+ return prev;
108
+ });
109
+ }, []);
110
+ const setJpeg = (0, react_1.useCallback)(() => {
111
+ setImageFormat('jpeg');
112
+ setOutName((prev) => {
113
+ if (prev.endsWith('.png')) {
114
+ return prev.replace(/.png$/g, '.jpeg');
115
+ }
116
+ return prev;
117
+ });
118
+ }, []);
119
+ const onClickStill = (0, react_1.useCallback)(() => {
55
120
  var _a;
56
- const body = {
57
- compositionId: composition.id,
58
- type: 'still',
121
+ (_a = SidebarContent_1.leftSidebarTabs.current) === null || _a === void 0 ? void 0 : _a.selectRendersPanel();
122
+ dispatchIfMounted({ type: 'start' });
123
+ (0, actions_1.addStillRenderJob)({
124
+ compositionId,
59
125
  outName,
60
- };
126
+ imageFormat,
127
+ quality: imageFormat === 'jpeg' ? quality : null,
128
+ frame,
129
+ scale,
130
+ verbose,
131
+ })
132
+ .then(() => {
133
+ dispatchIfMounted({ type: 'succeed' });
134
+ setSelectedModal(null);
135
+ })
136
+ .catch(() => {
137
+ dispatchIfMounted({ type: 'fail' });
138
+ });
139
+ }, [
140
+ compositionId,
141
+ dispatchIfMounted,
142
+ frame,
143
+ imageFormat,
144
+ outName,
145
+ quality,
146
+ scale,
147
+ setSelectedModal,
148
+ verbose,
149
+ ]);
150
+ const onClickVideo = (0, react_1.useCallback)(() => {
151
+ var _a;
61
152
  (_a = SidebarContent_1.leftSidebarTabs.current) === null || _a === void 0 ? void 0 : _a.selectRendersPanel();
62
- fetch(`/api/render`, {
63
- method: 'post',
64
- headers: {
65
- 'content-type': 'application/json',
66
- },
67
- body: JSON.stringify(body),
153
+ dispatchIfMounted({ type: 'start' });
154
+ (0, actions_1.addVideoRenderJob)({
155
+ compositionId,
156
+ outName,
157
+ imageFormat,
158
+ quality: imageFormat === 'jpeg' ? quality : null,
159
+ scale,
160
+ verbose,
161
+ // TODO: Make this configurable
162
+ codec: 'h264',
68
163
  })
69
- .then((res) => res.json())
70
- .then((data) => {
71
- if (data.success) {
72
- dispatchIfMounted({ type: 'succeed' });
73
- setSelectedModal(null);
74
- }
75
- else {
76
- dispatchIfMounted({ type: 'fail' });
77
- }
164
+ .then(() => {
165
+ dispatchIfMounted({ type: 'succeed' });
166
+ setSelectedModal(null);
78
167
  })
79
168
  .catch(() => {
80
169
  dispatchIfMounted({ type: 'fail' });
81
170
  });
82
- }, [composition.id, dispatchIfMounted, outName, setSelectedModal]);
171
+ }, [
172
+ compositionId,
173
+ dispatchIfMounted,
174
+ imageFormat,
175
+ outName,
176
+ quality,
177
+ scale,
178
+ setSelectedModal,
179
+ verbose,
180
+ ]);
181
+ const onQualityChangedDirectly = (0, react_1.useCallback)((newQuality) => {
182
+ setQuality(newQuality);
183
+ }, []);
184
+ const onQualityChanged = (0, react_1.useCallback)((e) => {
185
+ setQuality((q) => {
186
+ const newQuality = parseInt(e.target.value, 10);
187
+ if (Number.isNaN(newQuality)) {
188
+ return q;
189
+ }
190
+ const newQualityClamped = Math.min(MAX_QUALITY, Math.max(newQuality, MIN_QUALITY));
191
+ return newQualityClamped;
192
+ });
193
+ }, []);
194
+ const onScaleSetDirectly = (0, react_1.useCallback)((newScale) => {
195
+ setScale(newScale);
196
+ }, []);
197
+ const onScaleChanged = (0, react_1.useCallback)((e) => {
198
+ setScale((q) => {
199
+ const newQuality = parseFloat(e.target.value);
200
+ if (Number.isNaN(newQuality)) {
201
+ return q;
202
+ }
203
+ const newScaleClamped = Math.min(MAX_SCALE, Math.max(newQuality, MIN_SCALE));
204
+ return newScaleClamped;
205
+ });
206
+ }, []);
207
+ const onFrameSetDirectly = (0, react_1.useCallback)((newFrame) => {
208
+ setFrame(newFrame);
209
+ }, []);
210
+ const onFrameChanged = (0, react_1.useCallback)((e) => {
211
+ setFrame((q) => {
212
+ const newFrame = parseFloat(e.target.value);
213
+ if (Number.isNaN(newFrame)) {
214
+ return q;
215
+ }
216
+ // TODO: User could change frame inbetween 😈
217
+ return newFrame;
218
+ });
219
+ }, []);
83
220
  (0, react_1.useEffect)(() => {
84
221
  return () => {
85
222
  isMounted.current = false;
86
223
  };
87
224
  }, []);
88
- return ((0, jsx_runtime_1.jsxs)(ModalContainer_1.ModalContainer, { onOutsideClick: onQuit, onEscape: onQuit, children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.NewCompHeader, { title: `Render ${composition.id}` }), (0, jsx_runtime_1.jsxs)("div", { style: container, children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(RemInput_1.RemotionInput, { type: "text", value: outName }) }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { block: true, y: 0.5 }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: onClick, disabled: state.type === 'load', children: state.type === 'idle' ? 'Render' : 'Rendering...' }) })] })] }));
225
+ const existence = (0, use_file_existence_1.useFileExistence)(outName);
226
+ const imageFormatOptions = (0, react_1.useMemo)(() => {
227
+ return [
228
+ {
229
+ label: 'PNG',
230
+ onClick: setPng,
231
+ key: 'png',
232
+ selected: imageFormat === 'png',
233
+ },
234
+ {
235
+ label: 'JPEG',
236
+ onClick: setJpeg,
237
+ key: 'jpeg',
238
+ selected: imageFormat === 'jpeg',
239
+ },
240
+ ];
241
+ }, [imageFormat, setJpeg, setPng]);
242
+ const onVerboseLoggingChanged = (0, react_1.useCallback)((e) => {
243
+ setVerboseLogging(e.target.checked);
244
+ }, []);
245
+ return ((0, jsx_runtime_1.jsxs)(ModalContainer_1.ModalContainer, { onOutsideClick: onQuit, onEscape: onQuit, children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.NewCompHeader, { title: `Render ${compositionId}` }), (0, jsx_runtime_1.jsxs)("div", { style: container, children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { block: true, y: 0.5 }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Format" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: imageFormatOptions }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Output name" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(RemInput_1.RemotionInput
246
+ // TODO: Validate and reject folders or weird file names
247
+ , {
248
+ // TODO: Validate and reject folders or weird file names
249
+ warning: existence, style: input, type: "text", value: outName, onChange: onValueChange }), existence ? ((0, jsx_runtime_1.jsx)(ValidationMessage_1.ValidationMessage, { align: "flex-end", message: "Will be overwritten" })) : null] }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Frame" }), (0, jsx_runtime_1.jsxs)("div", { style: rightRow, children: [(0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger
250
+ // TODO: Hide if it is a still
251
+ , {
252
+ // TODO: Hide if it is a still
253
+ value: frame, onChange: onFrameChanged,
254
+ // TODO: Actual frame
255
+ placeholder: "0-100", onValueChange: onFrameSetDirectly, name: "frame", step: 1, min: 0,
256
+ // TODO: Add actual frame
257
+ max: Infinity }), ' '] })] }), (0, jsx_runtime_1.jsxs)(CollapsableOptions_1.CollapsableOptions, { showLabel: "Show advanced settings", hideLabel: "Hide advanced settings", children: [(0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Scale" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: scale, onChange: onScaleChanged, placeholder: "0.1-10",
258
+ // TODO: Does not allow non-integer steps
259
+ // TODO: Cannot click and type in 0.2
260
+ onValueChange: onScaleSetDirectly, name: "scale", step: 0.05, min: MIN_SCALE, max: MAX_SCALE }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "Verbose logging" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)("input", { type: 'checkbox', checked: verbose, onChange: onVerboseLoggingChanged }) })] }), imageFormat === 'jpeg' && ((0, jsx_runtime_1.jsxs)("div", { style: optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: label, children: "JPEG Quality" }), (0, jsx_runtime_1.jsx)("div", { style: rightRow, children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: quality, onChange: onQualityChanged, placeholder: "0-100", onValueChange: onQualityChangedDirectly, name: "quality", step: 1, min: MIN_QUALITY, max: MAX_QUALITY }) })] }))] }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { block: true, y: 0.5 }), (0, jsx_runtime_1.jsxs)("div", { style: buttonRow, children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { autoFocus: true, onClick: onClickVideo, disabled: state.type === 'load', children: state.type === 'idle' ? 'Render video' : 'Rendering...' }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { block: true, x: 0.5 }), (0, jsx_runtime_1.jsx)(Button_1.Button, { autoFocus: true, onClick: onClickStill, disabled: state.type === 'load', children: state.type === 'idle' ? 'Render still' : 'Rendering...' })] })] })] }));
89
261
  };
90
262
  exports.RenderModal = RenderModal;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare const RENDER_STATUS_INDICATOR_SIZE = 16;
3
+ export declare const CircularProgress: React.FC<{
4
+ progress: number;
5
+ }>;