@remotion/studio 4.0.395 → 4.0.397

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.
@@ -23,7 +23,7 @@ const Modals = ({ readOnlyStudio }) => {
23
23
  const { selectedModal: modalContextType } = (0, react_1.useContext)(modals_1.ModalsContext);
24
24
  const canRender = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).previewServerState.type ===
25
25
  'connected';
26
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [modalContextType && modalContextType.type === 'duplicate-comp' && ((0, jsx_runtime_1.jsx)(DuplicateComposition_1.DuplicateComposition, { compositionType: modalContextType.compositionType, compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-comp' && ((0, jsx_runtime_1.jsx)(DeleteComposition_1.DeleteComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'rename-comp' && ((0, jsx_runtime_1.jsx)(RenameComposition_1.RenameComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'input-props-override' && ((0, jsx_runtime_1.jsx)(OverrideInputProps_1.OverrideInputPropsModal, {})), modalContextType && modalContextType.type === 'web-render' && ((0, jsx_runtime_1.jsx)(WebRenderModal_1.WebRenderModalWithLoader, { type: "web-render", initialFrame: modalContextType.initialFrame, compositionId: modalContextType.compositionId, defaultProps: modalContextType.defaultProps, inFrameMark: modalContextType.inFrameMark, outFrameMark: modalContextType.outFrameMark })), modalContextType &&
26
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [modalContextType && modalContextType.type === 'duplicate-comp' && ((0, jsx_runtime_1.jsx)(DuplicateComposition_1.DuplicateComposition, { compositionType: modalContextType.compositionType, compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-comp' && ((0, jsx_runtime_1.jsx)(DeleteComposition_1.DeleteComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'rename-comp' && ((0, jsx_runtime_1.jsx)(RenameComposition_1.RenameComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'input-props-override' && ((0, jsx_runtime_1.jsx)(OverrideInputProps_1.OverrideInputPropsModal, {})), modalContextType && modalContextType.type === 'web-render' && ((0, jsx_runtime_1.jsx)(WebRenderModal_1.WebRenderModalWithLoader, { type: "web-render", initialFrame: modalContextType.initialFrame, compositionId: modalContextType.compositionId, defaultProps: modalContextType.defaultProps, inFrameMark: modalContextType.inFrameMark, outFrameMark: modalContextType.outFrameMark, initialLogLevel: modalContextType.initialLogLevel })), modalContextType &&
27
27
  canRender &&
28
28
  modalContextType.type === 'server-render' && ((0, jsx_runtime_1.jsx)(ServerRenderModal_1.RenderModalWithLoader, { initialFrame: modalContextType.initialFrame, initialDarkMode: modalContextType.initialDarkMode, compositionId: modalContextType.compositionId, initialVideoImageFormat: modalContextType.initialVideoImageFormat, initialJpegQuality: modalContextType.initialJpegQuality, initialScale: modalContextType.initialScale, initialLogLevel: modalContextType.initialLogLevel, initialOffthreadVideoCacheSizeInBytes: modalContextType.initialOffthreadVideoCacheSizeInBytes, initialOffthreadVideoThreads: modalContextType.initialOffthreadVideoThreads, initialMediaCacheSizeInBytes: modalContextType.initialMediaCacheSizeInBytes, initialConcurrency: modalContextType.initialConcurrency, maxConcurrency: modalContextType.maxConcurrency, minConcurrency: modalContextType.minConcurrency, initialStillImageFormat: modalContextType.initialStillImageFormat, initialMuted: modalContextType.initialMuted, initialEnforceAudioTrack: modalContextType.initialEnforceAudioTrack, initialProResProfile: modalContextType.initialProResProfile, initialx264Preset: modalContextType.initialx264Preset, initialPixelFormat: modalContextType.initialPixelFormat, initialAudioBitrate: modalContextType.initialAudioBitrate, initialVideoBitrate: modalContextType.initialVideoBitrate, initialEveryNthFrame: modalContextType.initialEveryNthFrame, initialNumberOfGifLoops: modalContextType.initialNumberOfGifLoops, initialDelayRenderTimeout: modalContextType.initialDelayRenderTimeout, initialEnvVariables: modalContextType.initialEnvVariables, initialDisableWebSecurity: modalContextType.initialDisableWebSecurity, initialGl: modalContextType.initialOpenGlRenderer, initialHeadless: modalContextType.initialHeadless, initialIgnoreCertificateErrors: modalContextType.initialIgnoreCertificateErrors, initialEncodingBufferSize: modalContextType.initialEncodingBufferSize, initialEncodingMaxRate: modalContextType.initialEncodingMaxRate, initialUserAgent: modalContextType.initialUserAgent, initialColorSpace: modalContextType.initialColorSpace, initialMultiProcessOnLinux: modalContextType.initialMultiProcessOnLinux, initialRepro: modalContextType.initialRepro, initialBeep: modalContextType.initialBeep, initialForSeamlessAacConcatenation: modalContextType.initialForSeamlessAacConcatenation, defaultProps: modalContextType.defaultProps, inFrameMark: modalContextType.inFrameMark, outFrameMark: modalContextType.outFrameMark, defaultConfigurationAudioCodec: modalContextType.defaultConfigurationAudioCodec, defaultConfigurationVideoCodec: modalContextType.defaultConfigurationVideoCodec, renderTypeOfLastRender: modalContextType.renderTypeOfLastRender, defaultMetadata: modalContextType.defaulMetadata, initialHardwareAcceleration: modalContextType.initialHardwareAcceleration, initialChromeMode: modalContextType.initialChromeMode, renderDefaults: modalContextType.renderDefaults })), modalContextType &&
29
29
  canRender &&
@@ -8,7 +8,7 @@ const check_fullscreen_support_1 = require("../helpers/check-fullscreen-support"
8
8
  const colors_1 = require("../helpers/colors");
9
9
  const is_current_selected_still_1 = require("../helpers/is-current-selected-still");
10
10
  const mobile_layout_1 = require("../helpers/mobile-layout");
11
- const show_browser_rendering_1 = require("../helpers/show-browser-rendering");
11
+ const should_show_render_button_1 = require("../helpers/should-show-render-button");
12
12
  const timeline_layout_1 = require("../helpers/timeline-layout");
13
13
  const loop_1 = require("../state/loop");
14
14
  const CheckboardToggle_1 = require("./CheckboardToggle");
@@ -24,7 +24,6 @@ const RenderButton_1 = require("./RenderButton");
24
24
  const SizeSelector_1 = require("./SizeSelector");
25
25
  const TimelineZoomControls_1 = require("./Timeline/TimelineZoomControls");
26
26
  const TimelineInOutToggle_1 = require("./TimelineInOutToggle");
27
- const TriggerWebRender_1 = require("./WebRender/TriggerWebRender");
28
27
  const layout_1 = require("./layout");
29
28
  const container = {
30
29
  display: 'flex',
@@ -134,6 +133,6 @@ const PreviewToolbar = ({ readOnlyStudio, bufferStateDelayInMilliseconds }) => {
134
133
  };
135
134
  }
136
135
  });
137
- return ((0, jsx_runtime_1.jsxs)("div", { ref: previewToolbarRef, style: isMobileLayout ? mobileContainer : container, className: "css-reset", children: [(0, jsx_runtime_1.jsx)("div", { ref: leftScrollIndicatorRef, style: scrollIndicatorLeft }), isMobileLayout ? null : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)("div", { style: padding }), (0, jsx_runtime_1.jsx)(TimelineZoomControls_1.TimelineZoomControls, {})] }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(SizeSelector_1.SizeSelector, {}), isStill || isVideoComposition ? ((0, jsx_runtime_1.jsx)(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate })) : null] })), isVideoComposition ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(PlayPause_1.PlayPause, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, loop: loop, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }), (0, jsx_runtime_1.jsx)(MuteToggle_1.MuteToggle, { muted: mediaMuted, setMuted: setMediaMuted }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(TimelineInOutToggle_1.TimelineInOutPointToggle, {}), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 })] })) : null, (0, jsx_runtime_1.jsx)(CheckboardToggle_1.CheckboardToggle, {}), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 }), isFullscreenSupported && (0, jsx_runtime_1.jsx)(FullscreenToggle_1.FullScreenToggle, {}), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), isMobileLayout && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(SizeSelector_1.SizeSelector, {}), isStill || isVideoComposition ? ((0, jsx_runtime_1.jsx)(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate })) : null] })), (0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)(layout_1.Flex, {}), !isMobileLayout && (0, jsx_runtime_1.jsx)(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), show_browser_rendering_1.SHOW_BROWSER_RENDERING ? (0, jsx_runtime_1.jsx)(TriggerWebRender_1.TriggerWebRender, {}) : null, readOnlyStudio ? null : (0, jsx_runtime_1.jsx)(RenderButton_1.RenderButton, {}), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1.5 })] }), (0, jsx_runtime_1.jsx)(PlaybackKeyboardShortcutsManager_1.PlaybackKeyboardShortcutsManager, { setPlaybackRate: setPlaybackRate }), (0, jsx_runtime_1.jsx)(PlaybackRatePersistor_1.PlaybackRatePersistor, {}), (0, jsx_runtime_1.jsx)("div", { ref: rightScrollIndicatorRef, style: scrollIndicatorRight })] }));
136
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: previewToolbarRef, style: isMobileLayout ? mobileContainer : container, className: "css-reset", children: [(0, jsx_runtime_1.jsx)("div", { ref: leftScrollIndicatorRef, style: scrollIndicatorLeft }), isMobileLayout ? null : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)("div", { style: padding }), (0, jsx_runtime_1.jsx)(TimelineZoomControls_1.TimelineZoomControls, {})] }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(SizeSelector_1.SizeSelector, {}), isStill || isVideoComposition ? ((0, jsx_runtime_1.jsx)(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate })) : null] })), isVideoComposition ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(PlayPause_1.PlayPause, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, loop: loop, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }), (0, jsx_runtime_1.jsx)(MuteToggle_1.MuteToggle, { muted: mediaMuted, setMuted: setMediaMuted }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(TimelineInOutToggle_1.TimelineInOutPointToggle, {}), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 })] })) : null, (0, jsx_runtime_1.jsx)(CheckboardToggle_1.CheckboardToggle, {}), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 }), isFullscreenSupported && (0, jsx_runtime_1.jsx)(FullscreenToggle_1.FullScreenToggle, {}), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), isMobileLayout && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(SizeSelector_1.SizeSelector, {}), isStill || isVideoComposition ? ((0, jsx_runtime_1.jsx)(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate })) : null] })), (0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)(layout_1.Flex, {}), !isMobileLayout && (0, jsx_runtime_1.jsx)(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, should_show_render_button_1.shouldShowRenderButton)(readOnlyStudio) ? ((0, jsx_runtime_1.jsx)(RenderButton_1.RenderButton, { readOnlyStudio: readOnlyStudio })) : null, (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1.5 })] }), (0, jsx_runtime_1.jsx)(PlaybackKeyboardShortcutsManager_1.PlaybackKeyboardShortcutsManager, { setPlaybackRate: setPlaybackRate }), (0, jsx_runtime_1.jsx)(PlaybackRatePersistor_1.PlaybackRatePersistor, {}), (0, jsx_runtime_1.jsx)("div", { ref: rightScrollIndicatorRef, style: scrollIndicatorRight })] }));
138
137
  };
139
138
  exports.PreviewToolbar = PreviewToolbar;
@@ -1,2 +1,5 @@
1
1
  import React from 'react';
2
- export declare const RenderButton: React.FC;
2
+ export type RenderType = 'server-render' | 'client-render';
3
+ export declare const RenderButton: React.FC<{
4
+ readonly readOnlyStudio: boolean;
5
+ }>;
@@ -1,29 +1,107 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.RenderButton = void 0;
4
7
  const jsx_runtime_1 = require("react/jsx-runtime");
5
8
  const player_1 = require("@remotion/player");
6
9
  const react_1 = require("react");
10
+ const react_dom_1 = __importDefault(require("react-dom"));
7
11
  const remotion_1 = require("remotion");
8
12
  const client_id_1 = require("../helpers/client-id");
13
+ const colors_1 = require("../helpers/colors");
14
+ const show_browser_rendering_1 = require("../helpers/show-browser-rendering");
9
15
  const use_keybinding_1 = require("../helpers/use-keybinding");
16
+ const caret_1 = require("../icons/caret");
10
17
  const render_1 = require("../icons/render");
11
18
  const in_out_1 = require("../state/in-out");
12
19
  const modals_1 = require("../state/modals");
13
- const Button_1 = require("./Button");
20
+ const z_index_1 = require("../state/z-index");
21
+ const is_menu_item_1 = require("./Menu/is-menu-item");
22
+ const portals_1 = require("./Menu/portals");
23
+ const styles_1 = require("./Menu/styles");
24
+ const MenuContent_1 = require("./NewComposition/MenuContent");
14
25
  const layout_1 = require("./layout");
15
- const button = {
26
+ const splitButtonContainer = {
27
+ display: 'inline-flex',
28
+ flexDirection: 'row',
29
+ alignItems: 'stretch',
30
+ borderRadius: 4,
31
+ border: `1px solid ${colors_1.INPUT_BORDER_COLOR_UNHOVERED}`,
32
+ backgroundColor: colors_1.INPUT_BACKGROUND,
33
+ overflow: 'hidden',
34
+ };
35
+ const mainButtonStyle = {
16
36
  paddingLeft: 7,
17
37
  paddingRight: 7,
18
38
  paddingTop: 7,
19
39
  paddingBottom: 7,
40
+ background: 'transparent',
41
+ border: 'none',
42
+ color: 'white',
43
+ cursor: 'pointer',
44
+ display: 'flex',
45
+ alignItems: 'center',
46
+ fontSize: 14,
47
+ fontFamily: 'inherit',
48
+ };
49
+ const dividerStyle = {
50
+ width: 1,
51
+ backgroundColor: colors_1.INPUT_BORDER_COLOR_UNHOVERED,
52
+ alignSelf: 'stretch',
53
+ };
54
+ const dropdownTriggerStyle = {
55
+ paddingLeft: 6,
56
+ paddingRight: 6,
57
+ paddingTop: 7,
58
+ paddingBottom: 7,
59
+ background: 'transparent',
60
+ border: 'none',
61
+ color: 'white',
62
+ cursor: 'pointer',
63
+ display: 'flex',
64
+ alignItems: 'center',
65
+ };
66
+ const mainButtonContent = {
67
+ paddingLeft: 4,
68
+ paddingRight: 6,
20
69
  };
21
70
  const label = {
22
71
  fontSize: 14,
23
72
  };
24
- const RenderButton = () => {
73
+ const RENDER_TYPE_STORAGE_KEY = 'remotion.renderType';
74
+ const getInitialRenderType = (readOnlyStudio) => {
75
+ if (!show_browser_rendering_1.SHOW_BROWSER_RENDERING) {
76
+ return 'server-render';
77
+ }
78
+ if (readOnlyStudio) {
79
+ return 'client-render';
80
+ }
81
+ try {
82
+ const stored = localStorage.getItem(RENDER_TYPE_STORAGE_KEY);
83
+ if (stored === 'server-render' || stored === 'client-render') {
84
+ return stored;
85
+ }
86
+ }
87
+ catch (_a) {
88
+ // localStorage might not be available
89
+ }
90
+ return 'server-render';
91
+ };
92
+ const RenderButton = ({ readOnlyStudio, }) => {
25
93
  const { inFrame, outFrame } = (0, in_out_1.useTimelineInOutFramePosition)();
26
94
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
95
+ const [renderType, setRenderType] = (0, react_1.useState)(() => getInitialRenderType(readOnlyStudio));
96
+ const [dropdownOpened, setDropdownOpened] = (0, react_1.useState)(false);
97
+ const dropdownRef = (0, react_1.useRef)(null);
98
+ const containerRef = (0, react_1.useRef)(null);
99
+ const { currentZIndex } = (0, z_index_1.useZIndex)();
100
+ const size = player_1.PlayerInternals.useElementSize(dropdownRef, {
101
+ triggerOnWindowResize: true,
102
+ shouldApplyCssTransforms: true,
103
+ });
104
+ const refresh = size === null || size === void 0 ? void 0 : size.refresh;
27
105
  const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx)
28
106
  .previewServerState.type;
29
107
  const shortcut = (0, use_keybinding_1.areKeyboardShortcutsDisabled)() ? '' : '(R)';
@@ -41,7 +119,7 @@ const RenderButton = () => {
41
119
  const video = remotion_1.Internals.useVideo();
42
120
  const getCurrentFrame = player_1.PlayerInternals.useFrameImperative();
43
121
  const { props } = (0, react_1.useContext)(remotion_1.Internals.EditorPropsContext);
44
- const onClick = (0, react_1.useCallback)(() => {
122
+ const openServerRenderModal = (0, react_1.useCallback)(() => {
45
123
  var _a, _b, _c;
46
124
  if (!video) {
47
125
  return null;
@@ -101,9 +179,178 @@ const RenderButton = () => {
101
179
  renderDefaults: defaults,
102
180
  });
103
181
  }, [video, setSelectedModal, getCurrentFrame, props, inFrame, outFrame]);
182
+ const openClientRenderModal = (0, react_1.useCallback)(() => {
183
+ var _a;
184
+ if (!video) {
185
+ return null;
186
+ }
187
+ const defaults = window.remotion_renderDefaults;
188
+ if (!defaults) {
189
+ throw new TypeError('Expected defaults');
190
+ }
191
+ setSelectedModal({
192
+ type: 'web-render',
193
+ compositionId: video.id,
194
+ initialFrame: getCurrentFrame(),
195
+ defaultProps: (_a = props[video.id]) !== null && _a !== void 0 ? _a : video.defaultProps,
196
+ inFrameMark: inFrame,
197
+ outFrameMark: outFrame,
198
+ initialLogLevel: defaults.logLevel,
199
+ });
200
+ }, [video, setSelectedModal, getCurrentFrame, props, inFrame, outFrame]);
201
+ const onClick = (0, react_1.useCallback)(() => {
202
+ if (!show_browser_rendering_1.SHOW_BROWSER_RENDERING || renderType === 'server-render') {
203
+ openServerRenderModal();
204
+ }
205
+ else {
206
+ openClientRenderModal();
207
+ }
208
+ }, [renderType, openServerRenderModal, openClientRenderModal]);
209
+ const onHideDropdown = (0, react_1.useCallback)(() => {
210
+ setDropdownOpened(false);
211
+ }, []);
212
+ const handleRenderTypeChange = (0, react_1.useCallback)((newType) => {
213
+ setRenderType(newType);
214
+ try {
215
+ localStorage.setItem(RENDER_TYPE_STORAGE_KEY, newType);
216
+ }
217
+ catch (_a) {
218
+ // localStorage might not be available
219
+ }
220
+ setDropdownOpened(false);
221
+ if (newType === 'server-render') {
222
+ openServerRenderModal();
223
+ }
224
+ else {
225
+ openClientRenderModal();
226
+ }
227
+ }, [openServerRenderModal, openClientRenderModal]);
228
+ const dropdownValues = (0, react_1.useMemo)(() => {
229
+ return [
230
+ {
231
+ type: 'item',
232
+ id: 'server-render',
233
+ label: 'Server-side render',
234
+ value: 'server-render',
235
+ onClick: () => handleRenderTypeChange('server-render'),
236
+ keyHint: null,
237
+ leftItem: null,
238
+ subMenu: null,
239
+ quickSwitcherLabel: null,
240
+ },
241
+ {
242
+ type: 'item',
243
+ id: 'client-render',
244
+ label: 'Client-side render',
245
+ value: 'client-render',
246
+ onClick: () => handleRenderTypeChange('client-render'),
247
+ keyHint: null,
248
+ leftItem: null,
249
+ subMenu: null,
250
+ quickSwitcherLabel: null,
251
+ },
252
+ ];
253
+ }, [handleRenderTypeChange]);
254
+ (0, react_1.useEffect)(() => {
255
+ const { current } = dropdownRef;
256
+ if (!current) {
257
+ return;
258
+ }
259
+ const onPointerDown = () => {
260
+ return setDropdownOpened((o) => {
261
+ if (!o) {
262
+ refresh === null || refresh === void 0 ? void 0 : refresh();
263
+ }
264
+ return !o;
265
+ });
266
+ };
267
+ const onClickDropdown = (e) => {
268
+ e.stopPropagation();
269
+ const isKeyboardInitiated = e.detail === 0;
270
+ if (!isKeyboardInitiated) {
271
+ return;
272
+ }
273
+ return setDropdownOpened((o) => {
274
+ if (!o) {
275
+ refresh === null || refresh === void 0 ? void 0 : refresh();
276
+ window.addEventListener('pointerup', (evt) => {
277
+ if (!(0, is_menu_item_1.isMenuItem)(evt.target)) {
278
+ setDropdownOpened(false);
279
+ }
280
+ }, {
281
+ once: true,
282
+ });
283
+ }
284
+ return !o;
285
+ });
286
+ };
287
+ current.addEventListener('pointerdown', onPointerDown);
288
+ current.addEventListener('click', onClickDropdown);
289
+ return () => {
290
+ current.removeEventListener('pointerdown', onPointerDown);
291
+ current.removeEventListener('click', onClickDropdown);
292
+ };
293
+ }, [refresh]);
294
+ const spaceToBottom = (0, react_1.useMemo)(() => {
295
+ const margin = 10;
296
+ if (size && dropdownOpened) {
297
+ return size.windowSize.height - (size.top + size.height) - margin;
298
+ }
299
+ return 0;
300
+ }, [dropdownOpened, size]);
301
+ const spaceToTop = (0, react_1.useMemo)(() => {
302
+ const margin = 10;
303
+ if (size && dropdownOpened) {
304
+ return size.top - margin;
305
+ }
306
+ return 0;
307
+ }, [dropdownOpened, size]);
308
+ const derivedMaxHeight = (0, react_1.useMemo)(() => {
309
+ return spaceToTop > spaceToBottom ? spaceToTop : spaceToBottom;
310
+ }, [spaceToBottom, spaceToTop]);
311
+ const portalStyle = (0, react_1.useMemo)(() => {
312
+ if (!dropdownOpened || !size) {
313
+ return null;
314
+ }
315
+ const verticalLayout = spaceToTop > spaceToBottom ? 'bottom' : 'top';
316
+ return {
317
+ ...(verticalLayout === 'top'
318
+ ? {
319
+ ...styles_1.menuContainerTowardsBottom,
320
+ top: size.top + size.height,
321
+ }
322
+ : {
323
+ ...styles_1.menuContainerTowardsTop,
324
+ bottom: size.windowSize.height - size.top,
325
+ }),
326
+ right: size.windowSize.width - size.left - size.width,
327
+ };
328
+ }, [dropdownOpened, size, spaceToBottom, spaceToTop]);
329
+ const containerStyle = (0, react_1.useMemo)(() => {
330
+ return {
331
+ ...splitButtonContainer,
332
+ borderColor: colors_1.INPUT_BORDER_COLOR_UNHOVERED,
333
+ opacity: connectionStatus !== 'connected' ? 0.7 : 1,
334
+ cursor: connectionStatus !== 'connected' ? 'inherit' : 'pointer',
335
+ };
336
+ }, [connectionStatus]);
337
+ const renderLabel = renderType === 'server-render' ? 'Render' : 'Render on web';
338
+ const shouldShowDropdown = (0, react_1.useMemo)(() => {
339
+ // Server render is not available
340
+ if (readOnlyStudio) {
341
+ return false;
342
+ }
343
+ // client render is not available
344
+ if (!show_browser_rendering_1.SHOW_BROWSER_RENDERING) {
345
+ return false;
346
+ }
347
+ return true;
348
+ }, [readOnlyStudio]);
104
349
  if (!video) {
105
350
  return null;
106
351
  }
107
- return ((0, jsx_runtime_1.jsx)(Button_1.Button, { id: "render-modal-button", title: tooltip, onClick: onClick, buttonContainerStyle: button, disabled: connectionStatus !== 'connected', children: (0, jsx_runtime_1.jsxs)(layout_1.Row, { align: "center", children: [(0, jsx_runtime_1.jsx)(render_1.RenderIcon, { svgProps: iconStyle }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 }), (0, jsx_runtime_1.jsx)("span", { style: label, children: "Render" })] }) }));
352
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { style: { display: 'none' }, id: "render-modal-button-server", disabled: connectionStatus !== 'connected' && renderType === 'server-render', onClick: openServerRenderModal, type: "button" }), ' ', (0, jsx_runtime_1.jsx)("button", { style: { display: 'none' }, id: "render-modal-button-client", disabled: connectionStatus !== 'connected' && renderType === 'server-render', onClick: openClientRenderModal, type: "button" }), (0, jsx_runtime_1.jsxs)("div", { ref: containerRef, style: containerStyle, title: tooltip, children: [(0, jsx_runtime_1.jsx)("button", { type: "button", style: mainButtonStyle, onClick: onClick, id: "render-modal-button", disabled: connectionStatus !== 'connected' && renderType === 'server-render', children: (0, jsx_runtime_1.jsxs)(layout_1.Row, { align: "center", style: mainButtonContent, children: [(0, jsx_runtime_1.jsx)(render_1.ThinRenderIcon, { fill: "currentcolor", svgProps: iconStyle }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 }), (0, jsx_runtime_1.jsx)("span", { style: label, children: renderLabel })] }) }), shouldShowDropdown ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: dividerStyle }), (0, jsx_runtime_1.jsx)("button", { ref: dropdownRef, type: "button", style: dropdownTriggerStyle, disabled: connectionStatus !== 'connected', className: is_menu_item_1.MENU_INITIATOR_CLASSNAME, children: (0, jsx_runtime_1.jsx)(caret_1.CaretDown, {}) })] })) : null] }), portalStyle
353
+ ? react_dom_1.default.createPortal((0, jsx_runtime_1.jsx)("div", { style: styles_1.fullScreenOverlay, children: (0, jsx_runtime_1.jsx)("div", { style: styles_1.outerPortal, className: "css-reset", children: (0, jsx_runtime_1.jsx)(z_index_1.HigherZIndex, { onOutsideClick: onHideDropdown, onEscape: onHideDropdown, children: (0, jsx_runtime_1.jsx)("div", { style: portalStyle, children: (0, jsx_runtime_1.jsx)(MenuContent_1.MenuContent, { onNextMenu: () => { }, onPreviousMenu: () => { }, values: dropdownValues, onHide: onHideDropdown, leaveLeftSpace: false, preselectIndex: dropdownValues.findIndex((v) => v.id === renderType), topItemCanBeUnselected: false, fixedHeight: derivedMaxHeight }) }) }) }) }), (0, portals_1.getPortal)(currentZIndex))
354
+ : null] }));
108
355
  };
109
356
  exports.RenderButton = RenderButton;
@@ -8,7 +8,6 @@ const react_1 = require("react");
8
8
  const prores_labels_1 = require("../../helpers/prores-labels");
9
9
  const use_file_existence_1 = require("../../helpers/use-file-existence");
10
10
  const Checkmark_1 = require("../../icons/Checkmark");
11
- const Checkbox_1 = require("../Checkbox");
12
11
  const ComboBox_1 = require("../NewComposition/ComboBox");
13
12
  const InputDragger_1 = require("../NewComposition/InputDragger");
14
13
  const RemInput_1 = require("../NewComposition/RemInput");
@@ -18,6 +17,7 @@ const FrameRangeSetting_1 = require("./FrameRangeSetting");
18
17
  const OptionExplainerBubble_1 = require("./OptionExplainerBubble");
19
18
  const RenderModalOutputName_1 = require("./RenderModalOutputName");
20
19
  const human_readable_codec_1 = require("./human-readable-codec");
20
+ const human_readable_loglevel_1 = require("./human-readable-loglevel");
21
21
  const layout_2 = require("./layout");
22
22
  const container = {
23
23
  flex: 1,
@@ -76,9 +76,21 @@ const RenderModalBasic = ({ renderMode, imageFormatOptions, outName, codec, setV
76
76
  const onValueChange = (0, react_1.useCallback)((e) => {
77
77
  setOutName(e.target.value);
78
78
  }, [setOutName]);
79
- const onVerboseLoggingChanged = (0, react_1.useCallback)((e) => {
80
- setVerboseLogging(e.target.checked ? 'verbose' : 'info');
81
- }, [setVerboseLogging]);
82
- return ((0, jsx_runtime_1.jsxs)("div", { style: container, children: [renderMode === 'still' || renderMode === 'sequence' ? ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Format" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: imageFormatOptions, needsWrapping: true }) })] })) : ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Codec", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 }), (0, jsx_runtime_1.jsx)(OptionExplainerBubble_1.OptionExplainerBubble, { id: "videoCodecOption" })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: videoCodecOptions, selectedId: codec, title: "Codec" }) })] })), renderMode === 'still' && resolvedComposition.durationInFrames > 1 ? ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Frame" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(RemInput_1.RightAlignInput, { children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: frame, onTextChange: onFrameChanged, placeholder: `0-${resolvedComposition.durationInFrames - 1}`, onValueChange: onFrameSetDirectly, name: "frame", step: 1, min: 0, status: "ok", max: resolvedComposition.durationInFrames - 1, rightAlign: true }) }) })] })) : null, renderMode === 'video' && codec === 'prores' ? ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "ProRes profile" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { title: 'proResProfile', selectedId: proResProfile, values: proResProfileOptions }) })] })) : null, renderMode === 'still' ? null : ((0, jsx_runtime_1.jsx)(FrameRangeSetting_1.FrameRangeSetting, { durationInFrames: resolvedComposition.durationInFrames, endFrame: endFrame, setEndFrame: setEndFrame, setStartFrame: setStartFrame, startFrame: startFrame })), (0, jsx_runtime_1.jsx)(RenderModalOutputName_1.RenderModalOutputName, { existence: existence, inputStyle: layout_2.input, outName: outName, onValueChange: onValueChange, validationMessage: validationMessage, label: renderMode === 'sequence' ? 'Folder name' : 'Output name' }), (0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Verbose logging ", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 }), (0, jsx_runtime_1.jsx)(OptionExplainerBubble_1.OptionExplainerBubble, { id: "logLevelOption" })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: logLevel === 'verbose', onChange: onVerboseLoggingChanged, name: "verbose-logging" }) })] })] }));
79
+ const logLevelOptions = (0, react_1.useMemo)(() => {
80
+ return ['trace', 'verbose', 'info', 'warn', 'error'].map((level) => {
81
+ return {
82
+ label: (0, human_readable_loglevel_1.humanReadableLogLevel)(level),
83
+ onClick: () => setVerboseLogging(level),
84
+ leftItem: logLevel === level ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
85
+ id: level,
86
+ keyHint: null,
87
+ quickSwitcherLabel: null,
88
+ subMenu: null,
89
+ type: 'item',
90
+ value: level,
91
+ };
92
+ });
93
+ }, [logLevel, setVerboseLogging]);
94
+ return ((0, jsx_runtime_1.jsxs)("div", { style: container, children: [renderMode === 'still' || renderMode === 'sequence' ? ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Format" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: imageFormatOptions, needsWrapping: true }) })] })) : ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Codec", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 }), (0, jsx_runtime_1.jsx)(OptionExplainerBubble_1.OptionExplainerBubble, { id: "videoCodecOption" })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: videoCodecOptions, selectedId: codec, title: "Codec" }) })] })), renderMode === 'still' && resolvedComposition.durationInFrames > 1 ? ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Frame" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(RemInput_1.RightAlignInput, { children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: frame, onTextChange: onFrameChanged, placeholder: `0-${resolvedComposition.durationInFrames - 1}`, onValueChange: onFrameSetDirectly, name: "frame", step: 1, min: 0, status: "ok", max: resolvedComposition.durationInFrames - 1, rightAlign: true }) }) })] })) : null, renderMode === 'video' && codec === 'prores' ? ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "ProRes profile" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { title: 'proResProfile', selectedId: proResProfile, values: proResProfileOptions }) })] })) : null, renderMode === 'still' ? null : ((0, jsx_runtime_1.jsx)(FrameRangeSetting_1.FrameRangeSetting, { durationInFrames: resolvedComposition.durationInFrames, endFrame: endFrame, setEndFrame: setEndFrame, setStartFrame: setStartFrame, startFrame: startFrame })), (0, jsx_runtime_1.jsx)(RenderModalOutputName_1.RenderModalOutputName, { existence: existence, inputStyle: layout_2.input, outName: outName, onValueChange: onValueChange, validationMessage: validationMessage, label: renderMode === 'sequence' ? 'Folder name' : 'Output name' }), (0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Log Level ", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 }), (0, jsx_runtime_1.jsx)(OptionExplainerBubble_1.OptionExplainerBubble, { id: "logLevelOption" })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: logLevelOptions, selectedId: logLevel, title: "Log Level" }) })] })] }));
83
95
  };
84
96
  exports.RenderModalBasic = RenderModalBasic;
@@ -6,6 +6,7 @@ const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const web_renderer_1 = require("@remotion/web-renderer");
7
7
  const react_1 = require("react");
8
8
  const ShortcutHint_1 = require("../../error-overlay/remotion-overlay/ShortcutHint");
9
+ const audio_1 = require("../../icons/audio");
9
10
  const data_1 = require("../../icons/data");
10
11
  const file_1 = require("../../icons/file");
11
12
  const frame_1 = require("../../icons/frame");
@@ -20,6 +21,7 @@ const get_string_before_suffix_1 = require("./get-string-before-suffix");
20
21
  const render_modals_1 = require("./render-modals");
21
22
  const ResolveCompositionBeforeModal_1 = require("./ResolveCompositionBeforeModal");
22
23
  const WebRenderModalAdvanced_1 = require("./WebRenderModalAdvanced");
24
+ const WebRenderModalAudio_1 = require("./WebRenderModalAudio");
23
25
  const WebRenderModalBasic_1 = require("./WebRenderModalBasic");
24
26
  const WebRenderModalPicture_1 = require("./WebRenderModalPicture");
25
27
  const invalidCharacters = ['?', '*', '+', ':', '%'];
@@ -70,17 +72,22 @@ const validateOutnameForStill = ({ outName, stillImageFormat, }) => {
70
72
  // TODO: Shortcut: Shift + R
71
73
  // TODO: Apply defaultCodec
72
74
  // TODO: Apply defaultOutName
73
- const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark, }) => {
75
+ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark, initialLogLevel, }) => {
74
76
  const context = (0, react_1.useContext)(ResolveCompositionBeforeModal_1.ResolvedCompositionContext);
75
77
  if (!context) {
76
78
  throw new Error('Should not be able to render without resolving comp first');
77
79
  }
78
80
  const { resolved: { result: resolvedComposition }, unresolved: unresolvedComposition, } = context;
79
- const [renderMode, setRenderMode] = (0, react_1.useState)('video');
81
+ const [isVideo] = (0, react_1.useState)(() => {
82
+ return typeof resolvedComposition.durationInFrames === 'undefined'
83
+ ? true
84
+ : resolvedComposition.durationInFrames > 1;
85
+ });
86
+ const [renderMode, setRenderMode] = (0, react_1.useState)(isVideo ? 'video' : 'still');
80
87
  const [tab, setTab] = (0, react_1.useState)('general');
81
88
  const [imageFormat, setImageFormat] = (0, react_1.useState)('png');
82
89
  const [frame, setFrame] = (0, react_1.useState)(() => initialFrame);
83
- const [logLevel, setLogLevel] = (0, react_1.useState)('info');
90
+ const [logLevel, setLogLevel] = (0, react_1.useState)(() => initialLogLevel);
84
91
  const [inputProps, setInputProps] = (0, react_1.useState)(() => defaultProps);
85
92
  const [delayRenderTimeout, setDelayRenderTimeout] = (0, react_1.useState)(30000);
86
93
  const [mediaCacheSizeInBytes, setMediaCacheSizeInBytes] = (0, react_1.useState)(null);
@@ -95,6 +102,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
95
102
  const [endFrame, setEndFrame] = (0, react_1.useState)(() => outFrameMark !== null && outFrameMark !== void 0 ? outFrameMark : null);
96
103
  const [renderProgress, setRenderProgress] = (0, react_1.useState)(null);
97
104
  const [transparent, setTransparent] = (0, react_1.useState)(false);
105
+ const [muted, setMuted] = (0, react_1.useState)(false);
98
106
  const finalEndFrame = (0, react_1.useMemo)(() => {
99
107
  if (endFrame === null) {
100
108
  return resolvedComposition.durationInFrames - 1;
@@ -116,7 +124,11 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
116
124
  const [initialOutName] = (0, react_1.useState)(() => {
117
125
  return (0, studio_shared_1.getDefaultOutLocation)({
118
126
  compositionName: resolvedComposition.id,
119
- defaultExtension: container,
127
+ defaultExtension: renderMode === 'still'
128
+ ? imageFormat
129
+ : isVideo
130
+ ? container
131
+ : imageFormat,
120
132
  type: 'asset',
121
133
  compositionDefaultOutName: resolvedComposition.defaultOutName,
122
134
  clientSideRender: true,
@@ -235,7 +247,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
235
247
  }
236
248
  }, [outName, imageFormat, renderMode, container]);
237
249
  const onRenderStill = (0, react_1.useCallback)(async () => {
238
- const blob = await (0, web_renderer_1.renderStillOnWeb)({
250
+ const { blob } = await (0, web_renderer_1.renderStillOnWeb)({
239
251
  composition: {
240
252
  component: unresolvedComposition.component,
241
253
  width: resolvedComposition.width,
@@ -307,6 +319,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
307
319
  setRenderProgress(progress);
308
320
  },
309
321
  transparent,
322
+ muted,
310
323
  outputTarget: 'web-fs',
311
324
  });
312
325
  setRenderProgress(null);
@@ -339,6 +352,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
339
352
  resolvedComposition.fps,
340
353
  outName,
341
354
  transparent,
355
+ muted,
342
356
  resolvedComposition.defaultProps,
343
357
  resolvedComposition.id,
344
358
  unresolvedComposition.calculateMetadata,
@@ -353,7 +367,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
353
367
  }, [renderMode, onRenderStill, onRenderVideo]);
354
368
  return ((0, jsx_runtime_1.jsxs)("div", { style: render_modals_1.outerModalStyle, children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.ModalHeader, { title: `Render ${resolvedComposition.id}` }), (0, jsx_runtime_1.jsxs)("div", { style: render_modals_1.container, children: [(0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: renderTabOptions, needsWrapping: false }), (0, jsx_runtime_1.jsx)("div", { style: render_modals_1.flexer }), (0, jsx_runtime_1.jsxs)(Button_1.Button, { autoFocus: true, onClick: onRender, style: render_modals_1.buttonStyle, disabled: !outnameValidation.valid, children: [renderProgress
355
369
  ? `Rendering... ${renderProgress.renderedFrames}/${finalEndFrame}`
356
- : `Render ${renderMode}`, (0, jsx_runtime_1.jsx)(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: true })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: render_modals_1.horizontalLayout, children: [(0, jsx_runtime_1.jsxs)("div", { style: render_modals_1.leftSidebar, children: [(0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'general', onClick: () => setTab('general'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(file_1.FileIcon, { style: render_modals_1.icon }) }), "General"] }), (0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'data', onClick: () => setTab('data'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(data_1.DataIcon, { style: render_modals_1.icon }) }), "Input Props"] }), renderMode === 'video' ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'picture', onClick: () => setTab('picture'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(frame_1.PicIcon, { style: render_modals_1.icon }) }), "Picture"] })) : null, (0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'advanced', onClick: () => setTab('advanced'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(file_1.FileIcon, { style: render_modals_1.icon }) }), "Advanced"] })] }), (0, jsx_runtime_1.jsx)("div", { style: render_modals_1.optionsPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: tab === 'general' ? ((0, jsx_runtime_1.jsx)(WebRenderModalBasic_1.WebRenderModalBasic, { renderMode: renderMode, resolvedComposition: resolvedComposition, imageFormat: imageFormat, setStillFormat: setStillFormat, frame: frame, onFrameChanged: onFrameChanged, onFrameSetDirectly: onFrameSetDirectly, container: container, setContainerFormat: setContainerFormat, codec: codec, setCodec: setCodec, startFrame: finalStartFrame, setStartFrame: setStartFrame, endFrame: finalEndFrame, setEndFrame: setEndFrame, outName: outName, onOutNameChange: onOutNameChange, validationMessage: outnameValidation.valid ? null : outnameValidation.error.message, logLevel: logLevel, setLogLevel: setLogLevel })) : tab === 'data' ? ((0, jsx_runtime_1.jsx)(DataEditor_1.DataEditor, { defaultProps: inputProps, setDefaultProps: setInputProps, unresolvedComposition: unresolvedComposition, mayShowSaveButton: false, propsEditType: "input-props", saving: saving, setSaving: setSaving, readOnlyStudio: false })) : tab === 'picture' ? ((0, jsx_runtime_1.jsx)(WebRenderModalPicture_1.WebRenderModalPicture, { renderMode: renderMode, videoBitrate: videoBitrate, setVideoBitrate: setVideoBitrate, keyframeIntervalInSeconds: keyframeIntervalInSeconds, setKeyframeIntervalInSeconds: setKeyframeIntervalInSeconds, transparent: transparent, setTransparent: setTransparent })) : ((0, jsx_runtime_1.jsx)(WebRenderModalAdvanced_1.WebRenderModalAdvanced, { renderMode: renderMode, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration })) })] })] }));
370
+ : `Render ${renderMode}`, (0, jsx_runtime_1.jsx)(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: true })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: render_modals_1.horizontalLayout, children: [(0, jsx_runtime_1.jsxs)("div", { style: render_modals_1.leftSidebar, children: [(0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'general', onClick: () => setTab('general'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(file_1.FileIcon, { style: render_modals_1.icon }) }), "General"] }), (0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'data', onClick: () => setTab('data'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(data_1.DataIcon, { style: render_modals_1.icon }) }), "Input Props"] }), renderMode === 'video' ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'picture', onClick: () => setTab('picture'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(frame_1.PicIcon, { style: render_modals_1.icon }) }), "Picture"] })) : null, renderMode === 'video' ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'audio', onClick: () => setTab('audio'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(audio_1.AudioIcon, { style: render_modals_1.icon }) }), "Audio"] })) : null, (0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'advanced', onClick: () => setTab('advanced'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(file_1.FileIcon, { style: render_modals_1.icon }) }), "Advanced"] })] }), (0, jsx_runtime_1.jsx)("div", { style: render_modals_1.optionsPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: tab === 'general' ? ((0, jsx_runtime_1.jsx)(WebRenderModalBasic_1.WebRenderModalBasic, { renderMode: renderMode, resolvedComposition: resolvedComposition, imageFormat: imageFormat, setStillFormat: setStillFormat, frame: frame, onFrameChanged: onFrameChanged, onFrameSetDirectly: onFrameSetDirectly, container: container, setContainerFormat: setContainerFormat, codec: codec, setCodec: setCodec, startFrame: finalStartFrame, setStartFrame: setStartFrame, endFrame: finalEndFrame, setEndFrame: setEndFrame, outName: outName, onOutNameChange: onOutNameChange, validationMessage: outnameValidation.valid ? null : outnameValidation.error.message, logLevel: logLevel, setLogLevel: setLogLevel })) : tab === 'data' ? ((0, jsx_runtime_1.jsx)(DataEditor_1.DataEditor, { defaultProps: inputProps, setDefaultProps: setInputProps, unresolvedComposition: unresolvedComposition, mayShowSaveButton: false, propsEditType: "input-props", saving: saving, setSaving: setSaving, readOnlyStudio: false })) : tab === 'picture' ? ((0, jsx_runtime_1.jsx)(WebRenderModalPicture_1.WebRenderModalPicture, { renderMode: renderMode, videoBitrate: videoBitrate, setVideoBitrate: setVideoBitrate, keyframeIntervalInSeconds: keyframeIntervalInSeconds, setKeyframeIntervalInSeconds: setKeyframeIntervalInSeconds, transparent: transparent, setTransparent: setTransparent })) : tab === 'audio' ? ((0, jsx_runtime_1.jsx)(WebRenderModalAudio_1.WebRenderModalAudio, { muted: muted, setMuted: setMuted })) : ((0, jsx_runtime_1.jsx)(WebRenderModalAdvanced_1.WebRenderModalAdvanced, { renderMode: renderMode, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration })) })] })] }));
357
371
  };
358
372
  const WebRenderModalWithLoader = (props) => {
359
373
  return ((0, jsx_runtime_1.jsx)(DismissableModal_1.DismissableModal, { children: (0, jsx_runtime_1.jsx)(ResolveCompositionBeforeModal_1.ResolveCompositionBeforeModal, { compositionId: props.compositionId, children: (0, jsx_runtime_1.jsx)(WebRenderModal, { ...props }) }) }));
@@ -0,0 +1,5 @@
1
+ import type React from 'react';
2
+ export declare const WebRenderModalAudio: React.FC<{
3
+ readonly muted: boolean;
4
+ readonly setMuted: React.Dispatch<React.SetStateAction<boolean>>;
5
+ }>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebRenderModalAudio = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const is_menu_item_1 = require("../Menu/is-menu-item");
6
+ const MutedSetting_1 = require("./MutedSetting");
7
+ const container = {
8
+ flex: 1,
9
+ overflowY: 'auto',
10
+ };
11
+ const WebRenderModalAudio = ({ muted, setMuted }) => {
12
+ return ((0, jsx_runtime_1.jsx)("div", { style: container, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: (0, jsx_runtime_1.jsx)(MutedSetting_1.MutedSetting, { enforceAudioTrack: false, muted: muted, setMuted: setMuted }) }));
13
+ };
14
+ exports.WebRenderModalAudio = WebRenderModalAudio;
@@ -4,13 +4,13 @@ exports.WebRenderModalBasic = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const Checkmark_1 = require("../../icons/Checkmark");
7
- const Checkbox_1 = require("../Checkbox");
8
7
  const layout_1 = require("../layout");
9
8
  const ComboBox_1 = require("../NewComposition/ComboBox");
10
9
  const InputDragger_1 = require("../NewComposition/InputDragger");
11
10
  const RemInput_1 = require("../NewComposition/RemInput");
12
11
  const SegmentedControl_1 = require("../SegmentedControl");
13
12
  const FrameRangeSetting_1 = require("./FrameRangeSetting");
13
+ const human_readable_loglevel_1 = require("./human-readable-loglevel");
14
14
  const layout_2 = require("./layout");
15
15
  const OptionExplainerBubble_1 = require("./OptionExplainerBubble");
16
16
  const RenderModalOutputName_1 = require("./RenderModalOutputName");
@@ -40,6 +40,21 @@ const WebRenderModalBasic = ({ renderMode, resolvedComposition, imageFormat, set
40
40
  },
41
41
  ];
42
42
  }, [imageFormat, setStillFormat]);
43
+ const logLevelOptions = (0, react_1.useMemo)(() => {
44
+ return ['trace', 'verbose', 'info', 'warn', 'error'].map((level) => {
45
+ return {
46
+ label: (0, human_readable_loglevel_1.humanReadableLogLevel)(level),
47
+ onClick: () => setLogLevel(level),
48
+ leftItem: logLevel === level ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
49
+ id: level,
50
+ keyHint: null,
51
+ quickSwitcherLabel: null,
52
+ subMenu: null,
53
+ type: 'item',
54
+ value: level,
55
+ };
56
+ });
57
+ }, [logLevel, setLogLevel]);
43
58
  const containerOptions = (0, react_1.useMemo)(() => {
44
59
  return [
45
60
  {
@@ -125,9 +140,6 @@ const WebRenderModalBasic = ({ renderMode, resolvedComposition, imageFormat, set
125
140
  },
126
141
  ];
127
142
  }, [codec, setCodec]);
128
- const onVerboseLoggingChanged = (0, react_1.useCallback)((e) => {
129
- setLogLevel(e.target.checked ? 'verbose' : 'info');
130
- }, [setLogLevel]);
131
- return ((0, jsx_runtime_1.jsxs)("div", { style: tabContainer, children: [renderMode === 'still' ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Format" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: imageFormatOptions, needsWrapping: true }) })] }), resolvedComposition.durationInFrames > 1 ? ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Frame" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(RemInput_1.RightAlignInput, { children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: frame, onTextChange: onFrameChanged, placeholder: `0-${resolvedComposition.durationInFrames - 1}`, onValueChange: onFrameSetDirectly, name: "frame", step: 1, min: 0, status: "ok", max: resolvedComposition.durationInFrames - 1, rightAlign: true }) }) })] })) : null] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Container" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: containerOptions, selectedId: container, title: "Container" }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Codec", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 }), (0, jsx_runtime_1.jsx)(OptionExplainerBubble_1.OptionExplainerBubble, { id: "videoCodecOption" })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: codecOptions, selectedId: codec, title: "Codec" }) })] }), (0, jsx_runtime_1.jsx)(FrameRangeSetting_1.FrameRangeSetting, { durationInFrames: resolvedComposition.durationInFrames, startFrame: startFrame !== null && startFrame !== void 0 ? startFrame : 0, endFrame: endFrame !== null && endFrame !== void 0 ? endFrame : resolvedComposition.durationInFrames - 1, setStartFrame: setStartFrame, setEndFrame: setEndFrame })] })), (0, jsx_runtime_1.jsx)(RenderModalOutputName_1.RenderModalOutputName, { existence: false, inputStyle: layout_2.input, outName: outName, onValueChange: onOutNameChange, validationMessage: validationMessage, label: "Download name" }), (0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Verbose logging ", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 }), (0, jsx_runtime_1.jsx)(OptionExplainerBubble_1.OptionExplainerBubble, { id: "logLevelOption" })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: logLevel === 'verbose', onChange: onVerboseLoggingChanged, name: "verbose-logging" }) })] })] }));
143
+ return ((0, jsx_runtime_1.jsxs)("div", { style: tabContainer, children: [renderMode === 'still' ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Format" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: imageFormatOptions, needsWrapping: true }) })] }), resolvedComposition.durationInFrames > 1 ? ((0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Frame" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(RemInput_1.RightAlignInput, { children: (0, jsx_runtime_1.jsx)(InputDragger_1.InputDragger, { value: frame, onTextChange: onFrameChanged, placeholder: `0-${resolvedComposition.durationInFrames - 1}`, onValueChange: onFrameSetDirectly, name: "frame", step: 1, min: 0, status: "ok", max: resolvedComposition.durationInFrames - 1, rightAlign: true }) }) })] })) : null] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsx)("div", { style: layout_2.label, children: "Container" }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: containerOptions, selectedId: container, title: "Container" }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Codec", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 }), (0, jsx_runtime_1.jsx)(OptionExplainerBubble_1.OptionExplainerBubble, { id: "videoCodecOption" })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: codecOptions, selectedId: codec, title: "Codec" }) })] }), (0, jsx_runtime_1.jsx)(FrameRangeSetting_1.FrameRangeSetting, { durationInFrames: resolvedComposition.durationInFrames, startFrame: startFrame !== null && startFrame !== void 0 ? startFrame : 0, endFrame: endFrame !== null && endFrame !== void 0 ? endFrame : resolvedComposition.durationInFrames - 1, setStartFrame: setStartFrame, setEndFrame: setEndFrame })] })), (0, jsx_runtime_1.jsx)(RenderModalOutputName_1.RenderModalOutputName, { existence: false, inputStyle: layout_2.input, outName: outName, onValueChange: onOutNameChange, validationMessage: validationMessage, label: "Download name" }), (0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Log Level ", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 }), (0, jsx_runtime_1.jsx)(OptionExplainerBubble_1.OptionExplainerBubble, { id: "logLevelOption" })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: logLevelOptions, selectedId: logLevel, title: "Log Level" }) })] })] }));
132
144
  };
133
145
  exports.WebRenderModalBasic = WebRenderModalBasic;
@@ -0,0 +1,2 @@
1
+ import type { LogLevel } from 'remotion';
2
+ export declare const humanReadableLogLevel: (logLevel: LogLevel) => "Trace" | "Verbose" | "Info" | "Warn" | "Error";