@remotion/studio 4.0.402 → 4.0.404
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.
- package/dist/components/Menu/MenuSubItem.d.ts +1 -0
- package/dist/components/Menu/MenuSubItem.js +13 -5
- package/dist/components/NewComposition/ComboBox.d.ts +1 -0
- package/dist/components/NewComposition/MenuContent.js +18 -12
- package/dist/components/RenderModal/WebRenderModal.js +29 -4
- package/dist/components/RenderModal/WebRenderModalAudio.d.ts +9 -1
- package/dist/components/RenderModal/WebRenderModalAudio.js +51 -2
- package/dist/components/RenderModal/WebRenderModalBasic.d.ts +2 -1
- package/dist/components/RenderModal/WebRenderModalBasic.js +21 -60
- package/dist/components/RenderModal/WebRenderModalLicense.js +46 -9
- package/dist/components/RenderModal/WebRenderModalLicenseKeyDetails.d.ts +13 -0
- package/dist/components/RenderModal/WebRenderModalLicenseKeyDetails.js +49 -0
- package/dist/components/RenderModal/WebRenderModalPicture.js +2 -60
- package/dist/components/RenderModal/quality-options.d.ts +3 -0
- package/dist/components/RenderModal/quality-options.js +26 -0
- package/dist/components/RenderModal/use-encodable-audio-codecs.d.ts +2 -0
- package/dist/components/RenderModal/use-encodable-audio-codecs.js +49 -0
- package/dist/components/RenderModal/use-encodable-video-codecs.d.ts +2 -0
- package/dist/components/RenderModal/use-encodable-video-codecs.js +49 -0
- package/dist/esm/{chunk-71hmw645.js → chunk-5yga8730.js} +784 -444
- package/dist/esm/internals.mjs +784 -444
- package/dist/esm/previewEntry.mjs +798 -458
- package/dist/esm/renderEntry.mjs +1 -1
- package/dist/icons/check-circle-filled.d.ts +2 -0
- package/dist/icons/check-circle-filled.js +6 -0
- package/package.json +9 -9
|
@@ -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
|
}, []);
|
|
@@ -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
|
|
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
|
|
55
|
-
if (
|
|
56
|
-
return
|
|
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
|
|
67
|
+
const nextItem = values.find((v, i) => i > index && isItemSelectable(v));
|
|
65
68
|
if (nextItem) {
|
|
66
69
|
return nextItem.id;
|
|
67
70
|
}
|
|
68
|
-
const
|
|
71
|
+
const lastSelectable = values
|
|
69
72
|
.slice()
|
|
70
73
|
.reverse()
|
|
71
|
-
.find((v) => v
|
|
72
|
-
if (
|
|
73
|
-
return
|
|
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:
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
|
12
|
-
|
|
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,
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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;
|
|
@@ -8,6 +8,7 @@ const Checkbox_1 = require("../Checkbox");
|
|
|
8
8
|
const RemInput_1 = require("../NewComposition/RemInput");
|
|
9
9
|
const ValidationMessage_1 = require("../NewComposition/ValidationMessage");
|
|
10
10
|
const layout_1 = require("../layout");
|
|
11
|
+
const WebRenderModalLicenseKeyDetails_1 = require("./WebRenderModalLicenseKeyDetails");
|
|
11
12
|
exports.row = {
|
|
12
13
|
display: 'flex',
|
|
13
14
|
flexDirection: 'row',
|
|
@@ -84,12 +85,13 @@ const LICENSE_KEY_LENGTH = 55;
|
|
|
84
85
|
const LICENSE_KEY_PREFIX = 'rm_pub_';
|
|
85
86
|
const validateLicenseKey = (key) => {
|
|
86
87
|
if (key.length === 0) {
|
|
87
|
-
return { valid: false, message: null };
|
|
88
|
+
return { valid: false, message: null, details: null };
|
|
88
89
|
}
|
|
89
90
|
if (!key.startsWith(LICENSE_KEY_PREFIX)) {
|
|
90
91
|
return {
|
|
91
92
|
valid: false,
|
|
92
93
|
message: `License key must start with "${LICENSE_KEY_PREFIX}"`,
|
|
94
|
+
details: null,
|
|
93
95
|
};
|
|
94
96
|
}
|
|
95
97
|
const afterPrefix = key.slice(LICENSE_KEY_PREFIX.length);
|
|
@@ -97,17 +99,58 @@ const validateLicenseKey = (key) => {
|
|
|
97
99
|
return {
|
|
98
100
|
valid: false,
|
|
99
101
|
message: 'License key must contain only alphanumeric characters after the prefix',
|
|
102
|
+
details: null,
|
|
100
103
|
};
|
|
101
104
|
}
|
|
102
105
|
if (key.length !== LICENSE_KEY_LENGTH) {
|
|
103
106
|
return {
|
|
104
107
|
valid: false,
|
|
105
108
|
message: `License key must be ${LICENSE_KEY_LENGTH} characters long`,
|
|
109
|
+
details: null,
|
|
106
110
|
};
|
|
107
111
|
}
|
|
108
|
-
return { valid: true, message: null };
|
|
112
|
+
return { valid: true, message: null, details: null };
|
|
109
113
|
};
|
|
110
114
|
const WebRenderModalLicense = ({ licenseKey, setLicenseKey, initialPublicLicenseKey, }) => {
|
|
115
|
+
const [licenseValidation, setLicenseValidation] = (0, react_1.useState)({ valid: true, message: null, details: null });
|
|
116
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
117
|
+
(0, react_1.useEffect)(() => {
|
|
118
|
+
if (licenseKey === null || licenseKey === 'free-license') {
|
|
119
|
+
return setLicenseValidation({
|
|
120
|
+
valid: true,
|
|
121
|
+
message: null,
|
|
122
|
+
details: null,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const validation = validateLicenseKey(licenseKey);
|
|
126
|
+
if (!validation.valid) {
|
|
127
|
+
return setLicenseValidation(validation);
|
|
128
|
+
}
|
|
129
|
+
setLicenseValidation({ valid: true, message: null, details: null });
|
|
130
|
+
setIsLoading(true);
|
|
131
|
+
(0, WebRenderModalLicenseKeyDetails_1.fetchLicenseKeyDetails)(licenseKey)
|
|
132
|
+
.then((details) => {
|
|
133
|
+
setIsLoading(false);
|
|
134
|
+
if (details.isValid) {
|
|
135
|
+
setLicenseValidation({ valid: true, message: null, details });
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
setLicenseValidation({
|
|
139
|
+
valid: false,
|
|
140
|
+
message: 'License key is invalid or has been reset',
|
|
141
|
+
details: null,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
.catch(() => {
|
|
146
|
+
setIsLoading(false);
|
|
147
|
+
setLicenseValidation({
|
|
148
|
+
valid: false,
|
|
149
|
+
message: 'Failed to fetch license key details',
|
|
150
|
+
details: null,
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}, [licenseKey]);
|
|
111
154
|
const onFreeLicenseChange = (0, react_1.useCallback)(() => {
|
|
112
155
|
setLicenseKey('free-license');
|
|
113
156
|
}, [setLicenseKey]);
|
|
@@ -117,14 +160,8 @@ const WebRenderModalLicense = ({ licenseKey, setLicenseKey, initialPublicLicense
|
|
|
117
160
|
const onLicenseKeyChange = (0, react_1.useCallback)((e) => {
|
|
118
161
|
setLicenseKey(e.target.value);
|
|
119
162
|
}, [setLicenseKey]);
|
|
120
|
-
const licenseValidation = (0, react_1.useMemo)(() => {
|
|
121
|
-
if (licenseKey === null || licenseKey === 'free-license') {
|
|
122
|
-
return { valid: true, message: null };
|
|
123
|
-
}
|
|
124
|
-
return validateLicenseKey(licenseKey);
|
|
125
|
-
}, [licenseKey]);
|
|
126
163
|
return ((0, jsx_runtime_1.jsxs)("div", { style: tabContainer, children: [(0, jsx_runtime_1.jsxs)("div", { style: descriptionStyle, children: ["Remotion is free if you are an individual or company with a headcount of 3 or less. See", ' ', (0, jsx_runtime_1.jsx)("a", { style: descriptionLink, href: "https://remotion.dev/license", children: "LICENSE.md" }), "."] }), (0, jsx_runtime_1.jsx)("div", { style: exports.row, children: (0, jsx_runtime_1.jsxs)("div", { style: justifyCenter, children: [(0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: licenseKey === 'free-license', onChange: onFreeLicenseChange, name: "free-license", rounded: true }), (0, jsx_runtime_1.jsxs)("div", { style: checkboxLabel, onClick: onFreeLicenseChange, children: ["I am eligible for the Free License, ", "don't", " print a warning"] })] }) }), licenseKey === 'free-license' ? ((0, jsx_runtime_1.jsxs)("div", { style: paddedDescriptionStyle, children: ["Enjoy Remotion! Add the following to", ' ', (0, jsx_runtime_1.jsx)("code", { style: codeStyle, children: "remotion.config.ts" }), " to persist this setting:", (0, jsx_runtime_1.jsx)("div", { style: codeLine, children: "Config.setPublicLicenseKey('free-license');" })] })) : null, (0, jsx_runtime_1.jsx)("div", { style: exports.row, children: (0, jsx_runtime_1.jsxs)("div", { style: justifyCenter, children: [(0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: licenseKey !== 'free-license' && licenseKey !== null, onChange: onCompanyLicenseChange, name: "company-license", rounded: true }), (0, jsx_runtime_1.jsx)("div", { style: checkboxLabel, onClick: onCompanyLicenseChange, children: "I have a Company License" })] }) }), licenseKey !== 'free-license' && licenseKey !== null ? ((0, jsx_runtime_1.jsxs)("div", { style: paddedDescriptionStyle, children: ["Add your public license from", ' ', (0, jsx_runtime_1.jsx)("a", { href: "https://remotion.pro/dashboard", target: "_blank", style: descriptionLink, children: "remotion.pro" }), ' ', "key below.", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1, block: true }), (0, jsx_runtime_1.jsx)(RemInput_1.RemotionInput, { value: licenseKey, onChange: onLicenseKeyChange, placeholder: "remotion.pro public license key (starts with rm_pub_)", status: licenseValidation.valid || licenseKey.length === 0
|
|
127
164
|
? 'ok'
|
|
128
|
-
: 'error', rightAlign: false, style: inputStyle, autoFocus: true }), licenseValidation.message ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1, block: true }), (0, jsx_runtime_1.jsx)(ValidationMessage_1.ValidationMessage, { message: licenseValidation.message, align: "flex-start", type: "error" })] })) : null, licenseValidation.valid && licenseKey.length > 0 ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1, block: true }), "Add the following to", ' ', (0, jsx_runtime_1.jsx)("code", { style: codeStyle, children: "remotion.config.ts" }), " to persist this setting:", (0, jsx_runtime_1.jsx)("div", { style: codeLineSmall, children: "Config.setPublicLicenseKey('" + licenseKey + "');" })] })) : null] })) : null, licenseKey === null ? ((0, jsx_runtime_1.jsxs)("div", { style: descriptionStyle, children: ["If you are not eligible for the free license, you need to obtain a", ' ', (0, jsx_runtime_1.jsx)("a", { style: descriptionLink, target: "_blank", href: "https://remotion.pro/license", children: "Company License" }), "."] })) : null] }));
|
|
165
|
+
: 'error', rightAlign: false, style: inputStyle, autoFocus: true }), licenseValidation.message ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1, block: true }), (0, jsx_runtime_1.jsx)(ValidationMessage_1.ValidationMessage, { message: licenseValidation.message, align: "flex-start", type: "error" })] })) : null, licenseValidation.valid && licenseKey.length > 0 ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1, block: true }), "Add the following to", ' ', (0, jsx_runtime_1.jsx)("code", { style: codeStyle, children: "remotion.config.ts" }), " to persist this setting:", (0, jsx_runtime_1.jsx)("div", { style: codeLineSmall, children: "Config.setPublicLicenseKey('" + licenseKey + "');" })] })) : null, isLoading && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1, block: true }), "Loading license key details..."] })), licenseValidation.details && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1, block: true }), (0, jsx_runtime_1.jsx)(WebRenderModalLicenseKeyDetails_1.WebRenderModalLicenseKeyDetails, { details: licenseValidation.details })] }))] })) : null, licenseKey === null ? ((0, jsx_runtime_1.jsxs)("div", { style: descriptionStyle, children: ["If you are not eligible for the free license, you need to obtain a", ' ', (0, jsx_runtime_1.jsx)("a", { style: descriptionLink, target: "_blank", href: "https://remotion.pro/license", children: "Company License" }), "."] })) : null] }));
|
|
129
166
|
};
|
|
130
167
|
exports.WebRenderModalLicense = WebRenderModalLicense;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type LicenseKeyDetails = {
|
|
3
|
+
readonly isValid: boolean;
|
|
4
|
+
readonly hasActiveSubscription: boolean;
|
|
5
|
+
readonly projectName: string;
|
|
6
|
+
readonly projectSlug: string;
|
|
7
|
+
};
|
|
8
|
+
type WebRenderModalLicenseKeyDetailsProps = {
|
|
9
|
+
readonly details: LicenseKeyDetails;
|
|
10
|
+
};
|
|
11
|
+
export declare const fetchLicenseKeyDetails: (licenseKey: string) => Promise<LicenseKeyDetails>;
|
|
12
|
+
export declare const WebRenderModalLicenseKeyDetails: React.FC<WebRenderModalLicenseKeyDetailsProps>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebRenderModalLicenseKeyDetails = exports.fetchLicenseKeyDetails = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const colors_1 = require("../../helpers/colors");
|
|
6
|
+
const check_circle_filled_1 = require("../../icons/check-circle-filled");
|
|
7
|
+
const ValidationMessage_1 = require("../NewComposition/ValidationMessage");
|
|
8
|
+
const textStyle = {
|
|
9
|
+
color: colors_1.LIGHT_TEXT,
|
|
10
|
+
fontSize: 14,
|
|
11
|
+
fontFamily: 'sans-serif',
|
|
12
|
+
lineHeight: 1.5,
|
|
13
|
+
display: 'flex',
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
};
|
|
16
|
+
const linkStyle = {
|
|
17
|
+
fontSize: 14,
|
|
18
|
+
fontFamily: 'sans-serif',
|
|
19
|
+
lineHeight: 1.5,
|
|
20
|
+
cursor: 'pointer',
|
|
21
|
+
};
|
|
22
|
+
const bulletStyle = {
|
|
23
|
+
display: 'flex',
|
|
24
|
+
alignItems: 'center',
|
|
25
|
+
gap: 6,
|
|
26
|
+
};
|
|
27
|
+
const icon = {
|
|
28
|
+
width: 14,
|
|
29
|
+
height: 14,
|
|
30
|
+
flexShrink: 0,
|
|
31
|
+
};
|
|
32
|
+
const PRO_HOST = 'https://remotion.pro';
|
|
33
|
+
const fetchLicenseKeyDetails = async (licenseKey) => {
|
|
34
|
+
const response = await fetch(`${PRO_HOST}/api/validate-license-key`, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
body: JSON.stringify({
|
|
37
|
+
licenseKey,
|
|
38
|
+
}),
|
|
39
|
+
headers: {
|
|
40
|
+
'Content-Type': 'application/json',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
return response.json();
|
|
44
|
+
};
|
|
45
|
+
exports.fetchLicenseKeyDetails = fetchLicenseKeyDetails;
|
|
46
|
+
const WebRenderModalLicenseKeyDetails = ({ details }) => {
|
|
47
|
+
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("div", { style: bulletStyle, children: [(0, jsx_runtime_1.jsx)(check_circle_filled_1.CheckCircleFilled, { style: { ...icon, fill: colors_1.LIGHT_TEXT } }), (0, jsx_runtime_1.jsxs)("div", { style: textStyle, children: ["Belongs to\u00A0", (0, jsx_runtime_1.jsx)("a", { href: `${PRO_HOST}/projects/${details.projectSlug}`, target: "_blank", style: linkStyle, children: details.projectName }), "\u00A0-\u00A0", (0, jsx_runtime_1.jsx)("a", { href: `${PRO_HOST}/projects/${details.projectSlug}/usage#client-renders-usage`, target: "_blank", style: linkStyle, children: "View usage" })] })] }), details.hasActiveSubscription ? ((0, jsx_runtime_1.jsxs)("div", { style: bulletStyle, children: [(0, jsx_runtime_1.jsx)(check_circle_filled_1.CheckCircleFilled, { style: { ...icon, fill: colors_1.LIGHT_TEXT } }), (0, jsx_runtime_1.jsx)("div", { style: textStyle, children: "Active Company License" })] })) : ((0, jsx_runtime_1.jsxs)("div", { style: bulletStyle, children: [(0, jsx_runtime_1.jsx)(ValidationMessage_1.WarningTriangle, { type: "warning", style: { ...icon, fill: colors_1.WARNING_COLOR } }), (0, jsx_runtime_1.jsx)("div", { style: textStyle, children: "No active Company License" })] }))] }));
|
|
48
|
+
};
|
|
49
|
+
exports.WebRenderModalLicenseKeyDetails = WebRenderModalLicenseKeyDetails;
|