@remotion/studio 4.0.401 → 4.0.403

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.
@@ -16,4 +16,5 @@ export declare const MenuSubItem: React.FC<{
16
16
  readonly onNextMenu: () => void;
17
17
  readonly subMenuActivated: SubMenuActivated;
18
18
  readonly setSubMenuActivated: React.Dispatch<React.SetStateAction<SubMenuActivated>>;
19
+ readonly disabled?: boolean;
19
20
  }>;
@@ -44,7 +44,7 @@ const leftSpace = {
44
44
  justifyContent: 'center',
45
45
  alignItems: 'center',
46
46
  };
47
- const MenuSubItem = ({ label, leaveLeftSpace, leftItem, onActionChosen, id, selected, onItemSelected, keyHint, subMenu, onQuitMenu, subMenuActivated, setSubMenuActivated, }) => {
47
+ const MenuSubItem = ({ label, leaveLeftSpace, leftItem, onActionChosen, id, selected, onItemSelected, keyHint, subMenu, onQuitMenu, subMenuActivated, setSubMenuActivated, disabled, }) => {
48
48
  const [hovered, setHovered] = (0, react_1.useState)(false);
49
49
  const ref = (0, react_1.useRef)(null);
50
50
  const size = player_1.PlayerInternals.useElementSize(ref, {
@@ -56,21 +56,29 @@ const MenuSubItem = ({ label, leaveLeftSpace, leftItem, onActionChosen, id, sele
56
56
  const style = (0, react_1.useMemo)(() => {
57
57
  return {
58
58
  ...container,
59
- backgroundColor: selected ? colors_1.CLEAR_HOVER : 'transparent',
59
+ backgroundColor: selected && !disabled ? colors_1.CLEAR_HOVER : 'transparent',
60
+ opacity: disabled ? 0.5 : 1,
61
+ cursor: disabled ? 'not-allowed' : 'default',
60
62
  };
61
- }, [selected]);
63
+ }, [selected, disabled]);
62
64
  const onPointerUp = (0, react_1.useCallback)((e) => {
65
+ if (disabled) {
66
+ return;
67
+ }
63
68
  if (subMenu) {
64
69
  setSubMenuActivated('with-mouse');
65
70
  setHovered(true);
66
71
  return;
67
72
  }
68
73
  onActionChosen(id, e);
69
- }, [id, onActionChosen, setSubMenuActivated, subMenu]);
74
+ }, [disabled, id, onActionChosen, setSubMenuActivated, subMenu]);
70
75
  const onPointerEnter = (0, react_1.useCallback)(() => {
76
+ if (disabled) {
77
+ return;
78
+ }
71
79
  onItemSelected(id);
72
80
  setHovered(true);
73
- }, [id, onItemSelected]);
81
+ }, [disabled, id, onItemSelected]);
74
82
  const onPointerLeave = (0, react_1.useCallback)(() => {
75
83
  setHovered(false);
76
84
  }, []);
@@ -18,6 +18,7 @@ export type SelectionItem = {
18
18
  leftItem: React.ReactNode;
19
19
  subMenu: SubMenu | null;
20
20
  quickSwitcherLabel: string | null;
21
+ disabled?: boolean;
21
22
  };
22
23
  export type ComboboxValue = DividerItem | SelectionItem;
23
24
  export declare const Combobox: React.FC<{
@@ -38,6 +38,9 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
38
38
  const onItemSelected = (0, react_1.useCallback)((id) => {
39
39
  setSelectedItem(id);
40
40
  }, []);
41
+ const isItemSelectable = (0, react_1.useCallback)((v) => {
42
+ return v.type !== 'divider' && !v.disabled;
43
+ }, []);
41
44
  const onArrowUp = (0, react_1.useCallback)(() => {
42
45
  setSelectedItem((prevItem) => {
43
46
  if (prevItem === null) {
@@ -47,34 +50,34 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
47
50
  if ((topItemCanBeUnselected && index === 0) || prevItem === null) {
48
51
  return null;
49
52
  }
50
- const previousItems = values.filter((v, i) => i < index && v.type !== 'divider');
53
+ const previousItems = values.filter((v, i) => i < index && isItemSelectable(v));
51
54
  if (previousItems.length > 0) {
52
55
  return previousItems[previousItems.length - 1].id;
53
56
  }
54
- const firstNonDivider = values.find((v) => v.type !== 'divider');
55
- if (firstNonDivider) {
56
- return firstNonDivider.id;
57
+ const firstSelectable = values.find((v) => isItemSelectable(v));
58
+ if (firstSelectable) {
59
+ return firstSelectable.id;
57
60
  }
58
61
  throw new Error('could not find previous item');
59
62
  });
60
- }, [topItemCanBeUnselected, values]);
63
+ }, [topItemCanBeUnselected, values, isItemSelectable]);
61
64
  const onArrowDown = (0, react_1.useCallback)(() => {
62
65
  setSelectedItem((prevItem) => {
63
66
  const index = values.findIndex((val) => val.id === prevItem);
64
- const nextItem = values.find((v, i) => i > index && v.type !== 'divider');
67
+ const nextItem = values.find((v, i) => i > index && isItemSelectable(v));
65
68
  if (nextItem) {
66
69
  return nextItem.id;
67
70
  }
68
- const lastNonDivider = values
71
+ const lastSelectable = values
69
72
  .slice()
70
73
  .reverse()
71
- .find((v) => v.type !== 'divider');
72
- if (lastNonDivider) {
73
- return lastNonDivider.id;
74
+ .find((v) => isItemSelectable(v));
75
+ if (lastSelectable) {
76
+ return lastSelectable.id;
74
77
  }
75
78
  throw new Error('could not find next item');
76
79
  });
77
- }, [values]);
80
+ }, [values, isItemSelectable]);
78
81
  const onEnter = (0, react_1.useCallback)(() => {
79
82
  if (selectedItem === null) {
80
83
  return onHide();
@@ -86,6 +89,9 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
86
89
  if (item.type === 'divider') {
87
90
  throw new Error('cannot find divider');
88
91
  }
92
+ if (item.disabled) {
93
+ return;
94
+ }
89
95
  if (item.subMenu) {
90
96
  return setSubMenuActivated('without-mouse');
91
97
  }
@@ -249,7 +255,7 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
249
255
  }
250
256
  onHide();
251
257
  };
252
- return ((0, jsx_runtime_1.jsx)(MenuSubItem_1.MenuSubItem, { selected: item.id === selectedItem, onActionChosen: onClick, onItemSelected: onItemSelected, label: item.label, id: item.id, keyHint: item.keyHint, leaveLeftSpace: leaveLeftSpace, leftItem: item.leftItem, subMenu: item.subMenu, onQuitMenu: onHide, onNextMenu: onNextMenu, subMenuActivated: subMenuActivated, setSubMenuActivated: setSubMenuActivated }, item.id));
258
+ return ((0, jsx_runtime_1.jsx)(MenuSubItem_1.MenuSubItem, { selected: item.id === selectedItem, onActionChosen: onClick, onItemSelected: onItemSelected, label: item.label, id: item.id, keyHint: item.keyHint, leaveLeftSpace: leaveLeftSpace, leftItem: item.leftItem, subMenu: item.subMenu, onQuitMenu: onHide, onNextMenu: onNextMenu, subMenuActivated: subMenuActivated, setSubMenuActivated: setSubMenuActivated, disabled: item.disabled }, item.id));
253
259
  }) }));
254
260
  };
255
261
  exports.MenuContent = MenuContent;
@@ -22,6 +22,8 @@ const DataEditor_1 = require("./DataEditor");
22
22
  const get_string_before_suffix_1 = require("./get-string-before-suffix");
23
23
  const render_modals_1 = require("./render-modals");
24
24
  const ResolveCompositionBeforeModal_1 = require("./ResolveCompositionBeforeModal");
25
+ const use_encodable_audio_codecs_1 = require("./use-encodable-audio-codecs");
26
+ const use_encodable_video_codecs_1 = require("./use-encodable-video-codecs");
25
27
  const WebRendererExperimentalBadge_1 = require("./WebRendererExperimentalBadge");
26
28
  const WebRenderModalAdvanced_1 = require("./WebRenderModalAdvanced");
27
29
  const WebRenderModalAudio_1 = require("./WebRenderModalAudio");
@@ -99,6 +101,8 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
99
101
  // Video-specific state
100
102
  const [codec, setCodec] = (0, react_1.useState)('h264');
101
103
  const [container, setContainer] = (0, react_1.useState)('mp4');
104
+ const [audioCodec, setAudioCodec] = (0, react_1.useState)('aac');
105
+ const [audioBitrate, setAudioBitrate] = (0, react_1.useState)('medium');
102
106
  const [videoBitrate, setVideoBitrate] = (0, react_1.useState)('high');
103
107
  const [hardwareAcceleration, setHardwareAcceleration] = (0, react_1.useState)('no-preference');
104
108
  const [keyframeIntervalInSeconds, setKeyframeIntervalInSeconds] = (0, react_1.useState)(5);
@@ -108,6 +112,22 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
108
112
  const [transparent, setTransparent] = (0, react_1.useState)(false);
109
113
  const [muted, setMuted] = (0, react_1.useState)(false);
110
114
  const [licenseKey, setLicenseKey] = (0, react_1.useState)(initialLicenseKey);
115
+ const encodableAudioCodecs = (0, use_encodable_audio_codecs_1.useEncodableAudioCodecs)(container);
116
+ const encodableVideoCodecs = (0, use_encodable_video_codecs_1.useEncodableVideoCodecs)(container);
117
+ const effectiveAudioCodec = (0, react_1.useMemo)(() => {
118
+ var _a;
119
+ if (encodableAudioCodecs.includes(audioCodec)) {
120
+ return audioCodec;
121
+ }
122
+ return (_a = encodableAudioCodecs[0]) !== null && _a !== void 0 ? _a : audioCodec;
123
+ }, [audioCodec, encodableAudioCodecs]);
124
+ const effectiveVideoCodec = (0, react_1.useMemo)(() => {
125
+ var _a;
126
+ if (encodableVideoCodecs.includes(codec)) {
127
+ return codec;
128
+ }
129
+ return (_a = encodableVideoCodecs[0]) !== null && _a !== void 0 ? _a : codec;
130
+ }, [codec, encodableVideoCodecs]);
111
131
  const finalEndFrame = (0, react_1.useMemo)(() => {
112
132
  if (endFrame === null) {
113
133
  return resolvedComposition.durationInFrames - 1;
@@ -149,6 +169,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
149
169
  }, []);
150
170
  const setContainerFormat = (0, react_1.useCallback)((newContainer) => {
151
171
  setContainer(newContainer);
172
+ setAudioCodec((0, web_renderer_1.getDefaultAudioCodecForContainer)(newContainer));
152
173
  setOutName((prev) => {
153
174
  const newFileName = (0, get_string_before_suffix_1.getStringBeforeSuffix)(prev) + '.' + newContainer;
154
175
  return newFileName;
@@ -162,7 +183,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
162
183
  return newFileName;
163
184
  });
164
185
  }
165
- else {
186
+ else if (newMode === 'still') {
166
187
  setOutName((prev) => {
167
188
  const newFileName = (0, get_string_before_suffix_1.getStringBeforeSuffix)(prev) + '.' + imageFormat;
168
189
  return newFileName;
@@ -316,7 +337,9 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
316
337
  delayRenderTimeoutInMilliseconds: delayRenderTimeout,
317
338
  mediaCacheSizeInBytes,
318
339
  logLevel,
319
- videoCodec: codec,
340
+ videoCodec: effectiveVideoCodec,
341
+ audioCodec: effectiveAudioCodec,
342
+ audioBitrate,
320
343
  container,
321
344
  videoBitrate,
322
345
  hardwareAcceleration,
@@ -348,7 +371,9 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
348
371
  delayRenderTimeout,
349
372
  mediaCacheSizeInBytes,
350
373
  logLevel,
351
- codec,
374
+ effectiveVideoCodec,
375
+ effectiveAudioCodec,
376
+ audioBitrate,
352
377
  container,
353
378
  videoBitrate,
354
379
  hardwareAcceleration,
@@ -376,7 +401,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
376
401
  }, [renderMode, onRenderStill, onRenderVideo]);
377
402
  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
378
403
  ? `Rendering... ${renderProgress.renderedFrames}/${finalEndFrame}`
379
- : `Render ${renderMode}`, (0, jsx_runtime_1.jsx)(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: true })] })] }), (0, jsx_runtime_1.jsx)("div", { style: render_modals_1.container, children: (0, jsx_runtime_1.jsx)(WebRendererExperimentalBadge_1.WebRendererExperimentalBadge, {}) }), (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)(gear_1.GearIcon, { style: render_modals_1.icon }) }), "Other"] }), (0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'license', onClick: () => setTab('license'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(certificate_1.CertificateIcon, { style: render_modals_1.icon }) }), "License"] })] }), (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 })) : tab === 'advanced' ? ((0, jsx_runtime_1.jsx)(WebRenderModalAdvanced_1.WebRenderModalAdvanced, { renderMode: renderMode, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration })) : ((0, jsx_runtime_1.jsx)(WebRenderModalLicense_1.WebRenderModalLicense, { licenseKey: licenseKey, setLicenseKey: setLicenseKey, initialPublicLicenseKey: initialLicenseKey })) })] })] }));
404
+ : `Render ${renderMode}`, (0, jsx_runtime_1.jsx)(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: true })] })] }), (0, jsx_runtime_1.jsx)("div", { style: render_modals_1.container, children: (0, jsx_runtime_1.jsx)(WebRendererExperimentalBadge_1.WebRendererExperimentalBadge, {}) }), (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)(gear_1.GearIcon, { style: render_modals_1.icon }) }), "Other"] }), (0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'license', onClick: () => setTab('license'), children: [(0, jsx_runtime_1.jsx)("div", { style: render_modals_1.iconContainer, children: (0, jsx_runtime_1.jsx)(certificate_1.CertificateIcon, { style: render_modals_1.icon }) }), "License"] })] }), (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, setCodec: setCodec, encodableVideoCodecs: encodableVideoCodecs, effectiveVideoCodec: effectiveVideoCodec, 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, audioCodec: audioCodec, setAudioCodec: setAudioCodec, audioBitrate: audioBitrate, setAudioBitrate: setAudioBitrate, container: container, encodableCodecs: encodableAudioCodecs, effectiveAudioCodec: effectiveAudioCodec })) : tab === 'advanced' ? ((0, jsx_runtime_1.jsx)(WebRenderModalAdvanced_1.WebRenderModalAdvanced, { renderMode: renderMode, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration })) : ((0, jsx_runtime_1.jsx)(WebRenderModalLicense_1.WebRenderModalLicense, { licenseKey: licenseKey, setLicenseKey: setLicenseKey, initialPublicLicenseKey: initialLicenseKey })) })] })] }));
380
405
  };
381
406
  const WebRenderModalWithLoader = (props) => {
382
407
  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 }) }) }));
@@ -1,5 +1,13 @@
1
- import type React from 'react';
1
+ import type { WebRendererAudioCodec, WebRendererContainer, WebRendererQuality } from '@remotion/web-renderer';
2
+ import React from 'react';
2
3
  export declare const WebRenderModalAudio: React.FC<{
3
4
  readonly muted: boolean;
4
5
  readonly setMuted: React.Dispatch<React.SetStateAction<boolean>>;
6
+ readonly audioCodec: WebRendererAudioCodec;
7
+ readonly setAudioCodec: React.Dispatch<React.SetStateAction<WebRendererAudioCodec>>;
8
+ readonly audioBitrate: WebRendererQuality;
9
+ readonly setAudioBitrate: React.Dispatch<React.SetStateAction<WebRendererQuality>>;
10
+ readonly container: WebRendererContainer;
11
+ readonly encodableCodecs: WebRendererAudioCodec[];
12
+ readonly effectiveAudioCodec: WebRendererAudioCodec;
5
13
  }>;
@@ -2,13 +2,62 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WebRenderModalAudio = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const web_renderer_1 = require("@remotion/web-renderer");
6
+ const react_1 = require("react");
7
+ const Checkmark_1 = require("../../icons/Checkmark");
5
8
  const is_menu_item_1 = require("../Menu/is-menu-item");
9
+ const ComboBox_1 = require("../NewComposition/ComboBox");
10
+ const layout_1 = require("../layout");
6
11
  const MutedSetting_1 = require("./MutedSetting");
12
+ const RenderModalHr_1 = require("./RenderModalHr");
13
+ const layout_2 = require("./layout");
14
+ const quality_options_1 = require("./quality-options");
7
15
  const container = {
8
16
  flex: 1,
9
17
  overflowY: 'auto',
10
18
  };
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 }) }));
19
+ const fallbackNoticeStyle = {
20
+ backgroundColor: 'rgba(59, 130, 246, 0.15)',
21
+ border: '1px solid rgba(59, 130, 246, 0.4)',
22
+ borderRadius: 4,
23
+ padding: '8px 12px',
24
+ marginLeft: 16,
25
+ marginRight: 16,
26
+ marginTop: 8,
27
+ fontSize: 13,
28
+ lineHeight: 1.4,
29
+ color: '#60a5fa',
30
+ };
31
+ const humanReadableWebAudioCodec = (audioCodec) => {
32
+ switch (audioCodec) {
33
+ case 'aac':
34
+ return 'AAC';
35
+ case 'opus':
36
+ return 'Opus';
37
+ default:
38
+ return audioCodec;
39
+ }
40
+ };
41
+ const WebRenderModalAudio = ({ muted, setMuted, audioCodec, setAudioCodec, audioBitrate, setAudioBitrate, container: videoContainer, encodableCodecs, effectiveAudioCodec, }) => {
42
+ const containerSupported = (0, react_1.useMemo)(() => (0, web_renderer_1.getSupportedAudioCodecsForContainer)(videoContainer), [videoContainer]);
43
+ const audioCodecOptions = (0, react_1.useMemo)(() => {
44
+ return containerSupported.map((codec) => {
45
+ const isEncodable = encodableCodecs.includes(codec);
46
+ return {
47
+ label: humanReadableWebAudioCodec(codec),
48
+ onClick: () => setAudioCodec(codec),
49
+ leftItem: audioCodec === codec ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
50
+ id: codec,
51
+ keyHint: null,
52
+ quickSwitcherLabel: null,
53
+ subMenu: null,
54
+ type: 'item',
55
+ value: codec,
56
+ disabled: !isEncodable,
57
+ };
58
+ });
59
+ }, [containerSupported, encodableCodecs, audioCodec, setAudioCodec]);
60
+ const audioBitrateOptions = (0, react_1.useMemo)(() => (0, quality_options_1.getQualityOptions)(audioBitrate, setAudioBitrate), [audioBitrate, setAudioBitrate]);
61
+ return ((0, jsx_runtime_1.jsxs)("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 }), !muted ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(RenderModalHr_1.RenderModalHr, {}), (0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Audio Quality", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: audioBitrateOptions, selectedId: audioBitrate, title: "Audio Quality" }) })] }), (0, jsx_runtime_1.jsxs)("div", { style: layout_2.optionRow, children: [(0, jsx_runtime_1.jsxs)("div", { style: layout_2.label, children: ["Audio Codec", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 0.5 })] }), (0, jsx_runtime_1.jsx)("div", { style: layout_2.rightRow, children: (0, jsx_runtime_1.jsx)(ComboBox_1.Combobox, { values: audioCodecOptions, selectedId: audioCodec, title: "Audio Codec" }) })] }), effectiveAudioCodec !== audioCodec ? ((0, jsx_runtime_1.jsxs)("div", { style: fallbackNoticeStyle, children: [humanReadableWebAudioCodec(audioCodec), " is not available in this browser. Using ", humanReadableWebAudioCodec(effectiveAudioCodec), ' ', "instead."] })) : null] })) : null] }));
13
62
  };
14
63
  exports.WebRenderModalAudio = WebRenderModalAudio;
@@ -13,8 +13,9 @@ type WebRenderModalBasicProps = {
13
13
  readonly onFrameSetDirectly: (newFrame: number) => void;
14
14
  readonly container: WebRendererContainer;
15
15
  readonly setContainerFormat: (container: WebRendererContainer) => void;
16
- readonly codec: WebRendererVideoCodec;
17
16
  readonly setCodec: (codec: WebRendererVideoCodec) => void;
17
+ readonly encodableVideoCodecs: WebRendererVideoCodec[];
18
+ readonly effectiveVideoCodec: WebRendererVideoCodec;
18
19
  readonly startFrame: number | null;
19
20
  readonly setStartFrame: React.Dispatch<React.SetStateAction<number | null>>;
20
21
  readonly endFrame: number | null;
@@ -17,7 +17,7 @@ const RenderModalOutputName_1 = require("./RenderModalOutputName");
17
17
  const tabContainer = {
18
18
  flex: 1,
19
19
  };
20
- const WebRenderModalBasic = ({ renderMode, resolvedComposition, imageFormat, setStillFormat, frame, onFrameChanged, onFrameSetDirectly, container, setContainerFormat, codec, setCodec, startFrame, setStartFrame, endFrame, setEndFrame, outName, onOutNameChange, validationMessage, logLevel, setLogLevel, }) => {
20
+ const WebRenderModalBasic = ({ renderMode, resolvedComposition, imageFormat, setStillFormat, frame, onFrameChanged, onFrameSetDirectly, container, setContainerFormat, setCodec, encodableVideoCodecs, effectiveVideoCodec, startFrame, setStartFrame, endFrame, setEndFrame, outName, onOutNameChange, validationMessage, logLevel, setLogLevel, }) => {
21
21
  const imageFormatOptions = (0, react_1.useMemo)(() => {
22
22
  return [
23
23
  {
@@ -81,65 +81,26 @@ const WebRenderModalBasic = ({ renderMode, resolvedComposition, imageFormat, set
81
81
  },
82
82
  ];
83
83
  }, [container, setContainerFormat]);
84
+ const codecLabels = (0, react_1.useMemo)(() => ({
85
+ h264: 'H.264',
86
+ h265: 'H.265',
87
+ vp8: 'VP8',
88
+ vp9: 'VP9',
89
+ av1: 'AV1',
90
+ }), []);
84
91
  const codecOptions = (0, react_1.useMemo)(() => {
85
- return [
86
- {
87
- label: 'H.264',
88
- onClick: () => setCodec('h264'),
89
- leftItem: codec === 'h264' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
90
- id: 'h264',
91
- keyHint: null,
92
- quickSwitcherLabel: null,
93
- subMenu: null,
94
- type: 'item',
95
- value: 'h264',
96
- },
97
- {
98
- label: 'H.265',
99
- onClick: () => setCodec('h265'),
100
- leftItem: codec === 'h265' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
101
- id: 'h265',
102
- keyHint: null,
103
- quickSwitcherLabel: null,
104
- subMenu: null,
105
- type: 'item',
106
- value: 'h265',
107
- },
108
- {
109
- label: 'VP8',
110
- onClick: () => setCodec('vp8'),
111
- leftItem: codec === 'vp8' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
112
- id: 'vp8',
113
- keyHint: null,
114
- quickSwitcherLabel: null,
115
- subMenu: null,
116
- type: 'item',
117
- value: 'vp8',
118
- },
119
- {
120
- label: 'VP9',
121
- onClick: () => setCodec('vp9'),
122
- leftItem: codec === 'vp9' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
123
- id: 'vp9',
124
- keyHint: null,
125
- quickSwitcherLabel: null,
126
- subMenu: null,
127
- type: 'item',
128
- value: 'vp9',
129
- },
130
- {
131
- label: 'AV1',
132
- onClick: () => setCodec('av1'),
133
- leftItem: codec === 'av1' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
134
- id: 'av1',
135
- keyHint: null,
136
- quickSwitcherLabel: null,
137
- subMenu: null,
138
- type: 'item',
139
- value: 'av1',
140
- },
141
- ];
142
- }, [codec, setCodec]);
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" }) })] })] }));
92
+ return encodableVideoCodecs.map((c) => ({
93
+ label: codecLabels[c],
94
+ onClick: () => setCodec(c),
95
+ leftItem: effectiveVideoCodec === c ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
96
+ id: c,
97
+ keyHint: null,
98
+ quickSwitcherLabel: null,
99
+ subMenu: null,
100
+ type: 'item',
101
+ value: c,
102
+ }));
103
+ }, [encodableVideoCodecs, effectiveVideoCodec, setCodec, codecLabels]);
104
+ 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: effectiveVideoCodec, 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" }) })] })] }));
144
105
  };
145
106
  exports.WebRenderModalBasic = WebRenderModalBasic;
@@ -3,74 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WebRenderModalPicture = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const Checkmark_1 = require("../../icons/Checkmark");
7
6
  const Checkbox_1 = require("../Checkbox");
8
7
  const ComboBox_1 = require("../NewComposition/ComboBox");
9
8
  const layout_1 = require("./layout");
10
9
  const NumberSetting_1 = require("./NumberSetting");
10
+ const quality_options_1 = require("./quality-options");
11
11
  const tabContainer = {
12
12
  flex: 1,
13
13
  };
14
14
  const WebRenderModalPicture = ({ renderMode, videoBitrate, setVideoBitrate, keyframeIntervalInSeconds, setKeyframeIntervalInSeconds, transparent, setTransparent, }) => {
15
- const qualityOptions = (0, react_1.useMemo)(() => {
16
- return [
17
- {
18
- label: 'Very Low',
19
- onClick: () => setVideoBitrate('very-low'),
20
- leftItem: videoBitrate === 'very-low' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
21
- id: 'very-low',
22
- keyHint: null,
23
- quickSwitcherLabel: null,
24
- subMenu: null,
25
- type: 'item',
26
- value: 'very-low',
27
- },
28
- {
29
- label: 'Low',
30
- onClick: () => setVideoBitrate('low'),
31
- leftItem: videoBitrate === 'low' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
32
- id: 'low',
33
- keyHint: null,
34
- quickSwitcherLabel: null,
35
- subMenu: null,
36
- type: 'item',
37
- value: 'low',
38
- },
39
- {
40
- label: 'Medium',
41
- onClick: () => setVideoBitrate('medium'),
42
- leftItem: videoBitrate === 'medium' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
43
- id: 'medium',
44
- keyHint: null,
45
- quickSwitcherLabel: null,
46
- subMenu: null,
47
- type: 'item',
48
- value: 'medium',
49
- },
50
- {
51
- label: 'High',
52
- onClick: () => setVideoBitrate('high'),
53
- leftItem: videoBitrate === 'high' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
54
- id: 'high',
55
- keyHint: null,
56
- quickSwitcherLabel: null,
57
- subMenu: null,
58
- type: 'item',
59
- value: 'high',
60
- },
61
- {
62
- label: 'Very High',
63
- onClick: () => setVideoBitrate('very-high'),
64
- leftItem: videoBitrate === 'very-high' ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
65
- id: 'very-high',
66
- keyHint: null,
67
- quickSwitcherLabel: null,
68
- subMenu: null,
69
- type: 'item',
70
- value: 'very-high',
71
- },
72
- ];
73
- }, [videoBitrate, setVideoBitrate]);
15
+ const qualityOptions = (0, react_1.useMemo)(() => (0, quality_options_1.getQualityOptions)(videoBitrate, setVideoBitrate), [videoBitrate, setVideoBitrate]);
74
16
  const onTransparentChanged = (0, react_1.useCallback)((e) => {
75
17
  setTransparent(e.target.checked);
76
18
  }, [setTransparent]);
@@ -0,0 +1,3 @@
1
+ import type { WebRendererQuality } from '@remotion/web-renderer';
2
+ import type { ComboboxValue } from '../NewComposition/ComboBox';
3
+ export declare const getQualityOptions: (selectedQuality: WebRendererQuality, setQuality: (quality: WebRendererQuality) => void) => ComboboxValue[];
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getQualityOptions = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const Checkmark_1 = require("../../icons/Checkmark");
6
+ const QUALITY_OPTIONS = [
7
+ { value: 'very-low', label: 'Very Low' },
8
+ { value: 'low', label: 'Low' },
9
+ { value: 'medium', label: 'Medium' },
10
+ { value: 'high', label: 'High' },
11
+ { value: 'very-high', label: 'Very High' },
12
+ ];
13
+ const getQualityOptions = (selectedQuality, setQuality) => {
14
+ return QUALITY_OPTIONS.map(({ value, label }) => ({
15
+ label,
16
+ onClick: () => setQuality(value),
17
+ leftItem: selectedQuality === value ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
18
+ id: value,
19
+ keyHint: null,
20
+ quickSwitcherLabel: null,
21
+ subMenu: null,
22
+ type: 'item',
23
+ value,
24
+ }));
25
+ };
26
+ exports.getQualityOptions = getQualityOptions;
@@ -0,0 +1,2 @@
1
+ import type { WebRendererAudioCodec, WebRendererContainer } from '@remotion/web-renderer';
2
+ export declare const useEncodableAudioCodecs: (container: WebRendererContainer) => WebRendererAudioCodec[];
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useEncodableAudioCodecs = void 0;
4
+ const web_renderer_1 = require("@remotion/web-renderer");
5
+ const react_1 = require("react");
6
+ const useEncodableAudioCodecs = (container) => {
7
+ var _a;
8
+ const cacheRef = (0, react_1.useRef)({});
9
+ const [codecsByContainer, setCodecsByContainer] = (0, react_1.useState)(() => {
10
+ // Initialize with fallback for the current container
11
+ return {
12
+ [container]: (0, web_renderer_1.getSupportedAudioCodecsForContainer)(container),
13
+ };
14
+ });
15
+ (0, react_1.useEffect)(() => {
16
+ const cached = cacheRef.current[container];
17
+ // Already fetched or currently fetching for this container
18
+ if (cached) {
19
+ return;
20
+ }
21
+ const supported = (0, web_renderer_1.getSupportedAudioCodecsForContainer)(container);
22
+ // Mark as fetching to prevent duplicate requests
23
+ cacheRef.current[container] = {
24
+ codecs: supported,
25
+ status: 'fetching',
26
+ };
27
+ (0, web_renderer_1.getEncodableAudioCodecs)(container)
28
+ .then((encodable) => {
29
+ cacheRef.current[container] = {
30
+ codecs: encodable,
31
+ status: 'done',
32
+ };
33
+ setCodecsByContainer((prev) => ({
34
+ ...prev,
35
+ [container]: encodable,
36
+ }));
37
+ })
38
+ .catch(() => {
39
+ // On error, keep using the supported codecs fallback
40
+ cacheRef.current[container] = {
41
+ codecs: supported,
42
+ status: 'done',
43
+ };
44
+ });
45
+ }, [container]);
46
+ // Return codecs for current container, or fall back to supported codecs
47
+ return ((_a = codecsByContainer[container]) !== null && _a !== void 0 ? _a : (0, web_renderer_1.getSupportedAudioCodecsForContainer)(container));
48
+ };
49
+ exports.useEncodableAudioCodecs = useEncodableAudioCodecs;
@@ -0,0 +1,2 @@
1
+ import type { WebRendererContainer, WebRendererVideoCodec } from '@remotion/web-renderer';
2
+ export declare const useEncodableVideoCodecs: (container: WebRendererContainer) => WebRendererVideoCodec[];