@remotion/studio 4.0.409 → 4.0.411

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.
@@ -5,7 +5,7 @@ const writeStaticFile = async ({ contents, filePath, }) => {
5
5
  if (window.remotion_isReadOnlyStudio) {
6
6
  throw new Error('writeStaticFile() is not available in read-only Studio');
7
7
  }
8
- const url = new URL('/api/add-asset', window.location.origin);
8
+ const url = new URL(`${window.remotion_staticBase}/api/add-asset`, window.location.origin);
9
9
  if (filePath.includes('\\')) {
10
10
  return Promise.reject(new Error('File path cannot contain backslashes'));
11
11
  }
@@ -103,24 +103,33 @@ const InstallPackageModal = ({ packageManager }) => {
103
103
  enter.unregister();
104
104
  };
105
105
  }, [disabled, onClick, registerKeybinding]);
106
- return ((0, jsx_runtime_1.jsxs)(DismissableModal_1.DismissableModal, { children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.ModalHeader, { title: "Install packages" }), (0, jsx_runtime_1.jsx)("div", { style: container, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: state.type === 'done' ? ((0, jsx_runtime_1.jsxs)("div", { style: text, children: ["Installed package", selectedPackages.length === 1 ? '' : 's', ' ', "successfully. Restart the server to complete."] })) : state.type === 'restarting' ? ((0, jsx_runtime_1.jsx)("div", { style: text, children: "Restarting the Studio server..." })) : state.type === 'installing' ? ((0, jsx_runtime_1.jsxs)("div", { style: text, children: ["Installing package", selectedPackages.length === 1 ? '' : 's', ". Check your terminal for progress."] })) : ((0, jsx_runtime_1.jsx)("div", { style: text, children: Object.entries(studio_shared_1.installableMap)
107
- .filter(([, install]) => install)
108
- .map(([pkgShort]) => {
109
- var _a, _b;
110
- const pkg = pkgShort === 'core' ? 'remotion' : `@remotion/${pkgShort}`;
111
- const isInstalled = (_b = (_a = window.remotion_installedPackages) === null || _a === void 0 ? void 0 : _a.includes(pkg)) !== null && _b !== void 0 ? _b : false;
112
- const link = studio_shared_1.apiDocs[pkgShort];
113
- const description = studio_shared_1.descriptions[pkgShort];
114
- if (!link) {
115
- throw new Error('No link for ' + pkg);
116
- }
117
- if (!description) {
118
- throw new Error('No description for ' + pkg);
119
- }
120
- return ((0, jsx_runtime_1.jsxs)(layout_1.Row, { align: "center", children: [(0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: map[pkg], name: pkg, onChange: () => {
121
- setMap((prev) => ({ ...prev, [pkg]: !prev[pkg] }));
122
- }, disabled: !canSelectPackages || isInstalled }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1.5 }), (0, jsx_runtime_1.jsx)(InstallablePackage_1.InstallablePackageComp, { description: description, isInstalled: isInstalled, link: link, pkg: pkg })] }, pkg));
123
- }) })) }), (0, jsx_runtime_1.jsx)(ModalFooter_1.ModalFooterContainer, { children: (0, jsx_runtime_1.jsxs)(layout_1.Row, { align: "center", children: [state.type === 'idle' ? ((0, jsx_runtime_1.jsxs)("span", { style: { color: colors_1.LIGHT_TEXT, fontSize: 13, lineHeight: 1.2 }, children: ["This will install ", selectedPackages.length, " package", selectedPackages.length === 1 ? '' : 's', (0, jsx_runtime_1.jsx)("br", {}), "using ", packageManager, ", Remotion v", remotion_1.VERSION] })) : null, (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsxs)(ModalButton_1.ModalButton, { onClick: onClick, disabled: disabled, children: [state.type === 'restarting'
106
+ return ((0, jsx_runtime_1.jsxs)(DismissableModal_1.DismissableModal, { children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.ModalHeader, { title: "Install packages" }), (0, jsx_runtime_1.jsx)("div", { style: container, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: state.type === 'done' ? ((0, jsx_runtime_1.jsxs)("div", { style: text, children: ["Installed package", selectedPackages.length === 1 ? '' : 's', ' ', "successfully. Restart the server to complete."] })) : state.type === 'restarting' ? ((0, jsx_runtime_1.jsx)("div", { style: text, children: "Restarting the Studio server..." })) : state.type === 'installing' ? ((0, jsx_runtime_1.jsxs)("div", { style: text, children: ["Installing package", selectedPackages.length === 1 ? '' : 's', ". Check your terminal for progress."] })) : ((0, jsx_runtime_1.jsxs)("div", { style: text, children: [Object.entries(studio_shared_1.installableMap)
107
+ .filter(([, install]) => install)
108
+ .map(([pkgShort]) => {
109
+ var _a, _b;
110
+ const pkg = pkgShort === 'core' ? 'remotion' : `@remotion/${pkgShort}`;
111
+ const isInstalled = (_b = (_a = window.remotion_installedPackages) === null || _a === void 0 ? void 0 : _a.includes(pkg)) !== null && _b !== void 0 ? _b : false;
112
+ const link = studio_shared_1.apiDocs[pkgShort];
113
+ const description = studio_shared_1.descriptions[pkgShort];
114
+ if (!link) {
115
+ throw new Error('No link for ' + pkg);
116
+ }
117
+ if (!description) {
118
+ throw new Error('No description for ' + pkg);
119
+ }
120
+ return ((0, jsx_runtime_1.jsxs)(layout_1.Row, { align: "center", children: [(0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: map[pkg], name: pkg, onChange: () => {
121
+ setMap((prev) => ({ ...prev, [pkg]: !prev[pkg] }));
122
+ }, disabled: !canSelectPackages || isInstalled }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1.5 }), (0, jsx_runtime_1.jsx)(InstallablePackage_1.InstallablePackageComp, { description: description, isInstalled: isInstalled, link: link, pkg: pkg })] }, pkg));
123
+ }), studio_shared_1.extraPackages.map((extraPkg) => {
124
+ var _a, _b;
125
+ const isInstalled = (_b = (_a = window.remotion_installedPackages) === null || _a === void 0 ? void 0 : _a.includes(extraPkg.name)) !== null && _b !== void 0 ? _b : false;
126
+ return ((0, jsx_runtime_1.jsxs)(layout_1.Row, { align: "center", children: [(0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: map[extraPkg.name], name: extraPkg.name, onChange: () => {
127
+ setMap((prev) => ({
128
+ ...prev,
129
+ [extraPkg.name]: !prev[extraPkg.name],
130
+ }));
131
+ }, disabled: !canSelectPackages || isInstalled }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1.5 }), (0, jsx_runtime_1.jsx)(InstallablePackage_1.InstallablePackageComp, { description: extraPkg.description, isInstalled: isInstalled, link: extraPkg.docsUrl, pkg: `${extraPkg.name}@${extraPkg.version}` })] }, extraPkg.name));
132
+ })] })) }), (0, jsx_runtime_1.jsx)(ModalFooter_1.ModalFooterContainer, { children: (0, jsx_runtime_1.jsxs)(layout_1.Row, { align: "center", children: [state.type === 'idle' ? ((0, jsx_runtime_1.jsxs)("span", { style: { color: colors_1.LIGHT_TEXT, fontSize: 13, lineHeight: 1.2 }, children: ["This will install ", selectedPackages.length, " package", selectedPackages.length === 1 ? '' : 's', (0, jsx_runtime_1.jsx)("br", {}), "using ", packageManager, ", Remotion v", remotion_1.VERSION] })) : null, (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsxs)(ModalButton_1.ModalButton, { onClick: onClick, disabled: disabled, children: [state.type === 'restarting'
124
133
  ? 'Restarting...'
125
134
  : state.type === 'installing'
126
135
  ? 'Installing...'
@@ -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, initialLogLevel: modalContextType.initialLogLevel, initialLicenseKey: modalContextType.initialLicenseKey })), 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, { ...modalContextType })), 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 && modalContextType.type === 'render-progress' && ((0, jsx_runtime_1.jsx)(RenderStatusModal_1.RenderStatusModal, { jobId: modalContextType.jobId })), modalContextType && modalContextType.type === 'update' && ((0, jsx_runtime_1.jsx)(UpdateModal_1.UpdateModal, { info: modalContextType.info, knownBugs: modalContextType.knownBugs })), modalContextType && modalContextType.type === 'install-packages' && ((0, jsx_runtime_1.jsx)(InstallPackage_1.InstallPackageModal, { packageManager: modalContextType.packageManager })), modalContextType && modalContextType.type === 'quick-switcher' && ((0, jsx_runtime_1.jsx)(QuickSwitcher_1.default, { readOnlyStudio: readOnlyStudio, invocationTimestamp: modalContextType.invocationTimestamp, initialMode: modalContextType.mode })), process.env.ASK_AI_ENABLED && (0, jsx_runtime_1.jsx)(AskAiModal_1.AskAiModal, {})] }));
29
29
  };
@@ -102,6 +102,34 @@ const RenderButton = ({ readOnlyStudio, }) => {
102
102
  shouldApplyCssTransforms: true,
103
103
  });
104
104
  const refresh = size === null || size === void 0 ? void 0 : size.refresh;
105
+ const onPointerDown = (0, react_1.useCallback)(() => {
106
+ setDropdownOpened((o) => {
107
+ if (!o) {
108
+ refresh === null || refresh === void 0 ? void 0 : refresh();
109
+ }
110
+ return !o;
111
+ });
112
+ }, [refresh]);
113
+ const onClickDropdown = (0, react_1.useCallback)((e) => {
114
+ e.stopPropagation();
115
+ const isKeyboardInitiated = e.detail === 0;
116
+ if (!isKeyboardInitiated) {
117
+ return;
118
+ }
119
+ setDropdownOpened((o) => {
120
+ if (!o) {
121
+ refresh === null || refresh === void 0 ? void 0 : refresh();
122
+ window.addEventListener('pointerup', (evt) => {
123
+ if (!(0, is_menu_item_1.isMenuItem)(evt.target)) {
124
+ setDropdownOpened(false);
125
+ }
126
+ }, {
127
+ once: true,
128
+ });
129
+ }
130
+ return !o;
131
+ });
132
+ }, [refresh]);
105
133
  const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx)
106
134
  .previewServerState.type;
107
135
  const shortcut = (0, use_keybinding_1.areKeyboardShortcutsDisabled)() ? '' : '(R)';
@@ -197,6 +225,20 @@ const RenderButton = ({ readOnlyStudio, }) => {
197
225
  outFrameMark: outFrame,
198
226
  initialLogLevel: defaults.logLevel,
199
227
  initialLicenseKey: defaults.publicLicenseKey,
228
+ initialStillImageFormat: defaults.stillImageFormat,
229
+ initialScale: defaults.scale,
230
+ initialDelayRenderTimeout: defaults.delayRenderTimeout,
231
+ initialDefaultOutName: null,
232
+ initialContainer: null,
233
+ initialVideoCodec: null,
234
+ initialAudioCodec: null,
235
+ initialAudioBitrate: null,
236
+ initialVideoBitrate: null,
237
+ initialHardwareAcceleration: null,
238
+ initialKeyframeIntervalInSeconds: null,
239
+ initialTransparent: null,
240
+ initialMuted: null,
241
+ initialMediaCacheSizeInBytes: defaults.mediaCacheSizeInBytes,
200
242
  });
201
243
  }, [video, setSelectedModal, getCurrentFrame, props, inFrame, outFrame]);
202
244
  const onClick = (0, react_1.useCallback)(() => {
@@ -252,46 +294,6 @@ const RenderButton = ({ readOnlyStudio, }) => {
252
294
  },
253
295
  ];
254
296
  }, [handleRenderTypeChange]);
255
- (0, react_1.useEffect)(() => {
256
- const { current } = dropdownRef;
257
- if (!current) {
258
- return;
259
- }
260
- const onPointerDown = () => {
261
- return setDropdownOpened((o) => {
262
- if (!o) {
263
- refresh === null || refresh === void 0 ? void 0 : refresh();
264
- }
265
- return !o;
266
- });
267
- };
268
- const onClickDropdown = (e) => {
269
- e.stopPropagation();
270
- const isKeyboardInitiated = e.detail === 0;
271
- if (!isKeyboardInitiated) {
272
- return;
273
- }
274
- return setDropdownOpened((o) => {
275
- if (!o) {
276
- refresh === null || refresh === void 0 ? void 0 : refresh();
277
- window.addEventListener('pointerup', (evt) => {
278
- if (!(0, is_menu_item_1.isMenuItem)(evt.target)) {
279
- setDropdownOpened(false);
280
- }
281
- }, {
282
- once: true,
283
- });
284
- }
285
- return !o;
286
- });
287
- };
288
- current.addEventListener('pointerdown', onPointerDown);
289
- current.addEventListener('click', onClickDropdown);
290
- return () => {
291
- current.removeEventListener('pointerdown', onPointerDown);
292
- current.removeEventListener('click', onClickDropdown);
293
- };
294
- }, [refresh]);
295
297
  const spaceToBottom = (0, react_1.useMemo)(() => {
296
298
  const margin = 10;
297
299
  if (size && dropdownOpened) {
@@ -350,7 +352,7 @@ const RenderButton = ({ readOnlyStudio, }) => {
350
352
  if (!video) {
351
353
  return null;
352
354
  }
353
- 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
355
+ 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", 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, onPointerDown: onPointerDown, onClick: onClickDropdown, children: (0, jsx_runtime_1.jsx)(caret_1.CaretDown, {}) })] })) : null] }), portalStyle
354
356
  ? 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))
355
357
  : null] }));
356
358
  };
@@ -81,7 +81,8 @@ const validateOutnameForStill = ({ outName, stillImageFormat, }) => {
81
81
  // TODO: Shortcut: Shift + R
82
82
  // TODO: Apply defaultCodec
83
83
  // TODO: Apply defaultOutName
84
- const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark, initialLogLevel, initialLicenseKey, }) => {
84
+ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark, initialLogLevel, initialLicenseKey, initialStillImageFormat, initialDefaultOutName, initialScale, initialDelayRenderTimeout, initialMediaCacheSizeInBytes, initialContainer, initialVideoCodec, initialAudioCodec, initialAudioBitrate, initialVideoBitrate, initialHardwareAcceleration, initialKeyframeIntervalInSeconds, initialTransparent, initialMuted, }) => {
85
+ var _a;
85
86
  const context = (0, react_1.useContext)(ResolveCompositionBeforeModal_1.ResolvedCompositionContext);
86
87
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
87
88
  const { setSidebarCollapsedState } = (0, react_1.useContext)(sidebar_1.SidebarContext);
@@ -97,26 +98,26 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
97
98
  });
98
99
  const [renderMode, setRenderMode] = (0, react_1.useState)(isVideo ? 'video' : 'still');
99
100
  const [tab, setTab] = (0, react_1.useState)('general');
100
- const [imageFormat, setImageFormat] = (0, react_1.useState)('png');
101
+ const [imageFormat, setImageFormat] = (0, react_1.useState)(() => initialStillImageFormat !== null && initialStillImageFormat !== void 0 ? initialStillImageFormat : 'png');
101
102
  const [frame, setFrame] = (0, react_1.useState)(() => initialFrame);
102
103
  const [logLevel, setLogLevel] = (0, react_1.useState)(() => initialLogLevel);
103
104
  const [inputProps, setInputProps] = (0, react_1.useState)(() => defaultProps);
104
- const [delayRenderTimeout, setDelayRenderTimeout] = (0, react_1.useState)(30000);
105
- const [mediaCacheSizeInBytes, setMediaCacheSizeInBytes] = (0, react_1.useState)(null);
105
+ const [delayRenderTimeout, setDelayRenderTimeout] = (0, react_1.useState)(initialDelayRenderTimeout !== null && initialDelayRenderTimeout !== void 0 ? initialDelayRenderTimeout : 30000);
106
+ const [mediaCacheSizeInBytes, setMediaCacheSizeInBytes] = (0, react_1.useState)(initialMediaCacheSizeInBytes);
106
107
  const [saving, setSaving] = (0, react_1.useState)(false);
107
108
  // Video-specific state
108
- const [codec, setCodec] = (0, react_1.useState)('h264');
109
- const [container, setContainer] = (0, react_1.useState)('mp4');
110
- const [audioCodec, setAudioCodec] = (0, react_1.useState)('aac');
111
- const [audioBitrate, setAudioBitrate] = (0, react_1.useState)('medium');
112
- const [videoBitrate, setVideoBitrate] = (0, react_1.useState)('high');
113
- const [hardwareAcceleration, setHardwareAcceleration] = (0, react_1.useState)('no-preference');
114
- const [keyframeIntervalInSeconds, setKeyframeIntervalInSeconds] = (0, react_1.useState)(5);
115
- const [startFrame, setStartFrame] = (0, react_1.useState)(() => inFrameMark !== null && inFrameMark !== void 0 ? inFrameMark : null);
116
- const [endFrame, setEndFrame] = (0, react_1.useState)(() => outFrameMark !== null && outFrameMark !== void 0 ? outFrameMark : null);
117
- const [transparent, setTransparent] = (0, react_1.useState)(false);
118
- const [muted, setMuted] = (0, react_1.useState)(false);
119
- const [scale, setScale] = (0, react_1.useState)(1);
109
+ const [codec, setCodec] = (0, react_1.useState)(initialVideoCodec !== null && initialVideoCodec !== void 0 ? initialVideoCodec : 'h264');
110
+ const [container, setContainer] = (0, react_1.useState)(initialContainer !== null && initialContainer !== void 0 ? initialContainer : 'mp4');
111
+ const [audioCodec, setAudioCodec] = (0, react_1.useState)(initialAudioCodec !== null && initialAudioCodec !== void 0 ? initialAudioCodec : 'aac');
112
+ const [audioBitrate, setAudioBitrate] = (0, react_1.useState)(initialAudioBitrate !== null && initialAudioBitrate !== void 0 ? initialAudioBitrate : 'medium');
113
+ const [videoBitrate, setVideoBitrate] = (0, react_1.useState)(initialVideoBitrate !== null && initialVideoBitrate !== void 0 ? initialVideoBitrate : 'high');
114
+ const [hardwareAcceleration, setHardwareAcceleration] = (0, react_1.useState)((_a = initialHardwareAcceleration) !== null && _a !== void 0 ? _a : 'no-preference');
115
+ const [keyframeIntervalInSeconds, setKeyframeIntervalInSeconds] = (0, react_1.useState)(initialKeyframeIntervalInSeconds !== null && initialKeyframeIntervalInSeconds !== void 0 ? initialKeyframeIntervalInSeconds : 5);
116
+ const [startFrame, setStartFrame] = (0, react_1.useState)(() => inFrameMark);
117
+ const [endFrame, setEndFrame] = (0, react_1.useState)(() => outFrameMark);
118
+ const [transparent, setTransparent] = (0, react_1.useState)(initialTransparent !== null && initialTransparent !== void 0 ? initialTransparent : false);
119
+ const [muted, setMuted] = (0, react_1.useState)(initialMuted !== null && initialMuted !== void 0 ? initialMuted : false);
120
+ const [scale, setScale] = (0, react_1.useState)(initialScale !== null && initialScale !== void 0 ? initialScale : 1);
120
121
  const [licenseKey, setLicenseKey] = (0, react_1.useState)(initialLicenseKey);
121
122
  const encodableAudioCodecs = (0, use_encodable_audio_codecs_1.useEncodableAudioCodecs)(container);
122
123
  const encodableVideoCodecs = (0, use_encodable_video_codecs_1.useEncodableVideoCodecs)(container);
@@ -146,7 +147,10 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
146
147
  }
147
148
  return Math.max(0, Math.min(finalEndFrame, startFrame));
148
149
  }, [finalEndFrame, startFrame]);
149
- const [initialOutName] = (0, react_1.useState)(() => {
150
+ const [initialOutNameState] = (0, react_1.useState)(() => {
151
+ if (initialDefaultOutName) {
152
+ return initialDefaultOutName;
153
+ }
150
154
  return (0, studio_shared_1.getDefaultOutLocation)({
151
155
  compositionName: resolvedComposition.id,
152
156
  defaultExtension: renderMode === 'still'
@@ -159,7 +163,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
159
163
  clientSideRender: true,
160
164
  });
161
165
  });
162
- const [outName, setOutName] = (0, react_1.useState)(() => initialOutName);
166
+ const [outName, setOutName] = (0, react_1.useState)(() => initialOutNameState);
163
167
  const setStillFormat = (0, react_1.useCallback)((format) => {
164
168
  setImageFormat(format);
165
169
  setOutName((prev) => {
@@ -1,4 +1,4 @@
1
- import type { RenderStillOnWebImageFormat } from '@remotion/web-renderer';
1
+ import type { RenderStillOnWebImageFormat, WebRendererAudioCodec, WebRendererContainer, WebRendererQuality, WebRendererVideoCodec } from '@remotion/web-renderer';
2
2
  import type { LogLevel } from 'remotion';
3
3
  export type ClientRenderJobProgress = {
4
4
  renderedFrames: number;
@@ -48,13 +48,13 @@ export type ClientStillRenderJob = ClientRenderJobBase & {
48
48
  } & ClientRenderJobDynamicStatus;
49
49
  export type ClientVideoRenderJob = ClientRenderJobBase & {
50
50
  type: 'client-video';
51
- container: string;
52
- videoCodec: string;
53
- audioCodec: string;
51
+ container: WebRendererContainer;
52
+ videoCodec: WebRendererVideoCodec;
53
+ audioCodec: WebRendererAudioCodec;
54
54
  startFrame: number;
55
55
  endFrame: number;
56
- audioBitrate: string;
57
- videoBitrate: string;
56
+ audioBitrate: WebRendererQuality;
57
+ videoBitrate: WebRendererQuality;
58
58
  hardwareAcceleration: string;
59
59
  keyframeIntervalInSeconds: number;
60
60
  transparent: boolean;