@remotion/studio
Version:
APIs for interacting with the Remotion Studio
847 lines (846 loc) • 43.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RenderModalWithLoader = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const client_1 = require("@remotion/renderer/client");
const studio_shared_1 = require("@remotion/studio-shared");
const react_1 = require("react");
const ShortcutHint_1 = require("../../error-overlay/remotion-overlay/ShortcutHint");
const colors_1 = require("../../helpers/colors");
const convert_env_variables_1 = require("../../helpers/convert-env-variables");
const render_modal_sections_1 = require("../../helpers/render-modal-sections");
const use_keybinding_1 = require("../../helpers/use-keybinding");
const Checkmark_1 = require("../../icons/Checkmark");
const audio_1 = require("../../icons/audio");
const data_1 = require("../../icons/data");
const file_1 = require("../../icons/file");
const frame_1 = require("../../icons/frame");
const gear_1 = require("../../icons/gear");
const gif_1 = require("../../icons/gif");
const modals_1 = require("../../state/modals");
const sidebar_1 = require("../../state/sidebar");
const Button_1 = require("../Button");
const is_menu_item_1 = require("../Menu/is-menu-item");
const ModalContainer_1 = require("../ModalContainer");
const ModalHeader_1 = require("../ModalHeader");
const DismissableModal_1 = require("../NewComposition/DismissableModal");
const OptionsPanel_1 = require("../OptionsPanel");
const actions_1 = require("../RenderQueue/actions");
const SegmentedControl_1 = require("../SegmentedControl");
const vertical_1 = require("../Tabs/vertical");
const CrfSetting_1 = require("./CrfSetting");
const DataEditor_1 = require("./DataEditor");
const RenderModalAdvanced_1 = require("./RenderModalAdvanced");
const RenderModalAudio_1 = require("./RenderModalAudio");
const RenderModalBasic_1 = require("./RenderModalBasic");
const RenderModalGif_1 = require("./RenderModalGif");
const RenderModalPicture_1 = require("./RenderModalPicture");
const ResolveCompositionBeforeModal_1 = require("./ResolveCompositionBeforeModal");
const get_default_codecs_1 = require("./get-default-codecs");
const get_string_before_suffix_1 = require("./get-string-before-suffix");
const out_name_checker_1 = require("./out-name-checker");
const initialState = { type: 'idle' };
const reducer = (state, action) => {
if (action.type === 'start') {
return {
type: 'load',
};
}
if (action.type === 'fail') {
return {
type: 'error',
};
}
if (action.type === 'succeed') {
return {
type: 'success',
};
}
return state;
};
const container = {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
padding: '12px 16px',
borderBottom: '1px solid black',
};
const optionsPanel = {
display: 'flex',
width: '100%',
};
const horizontalLayout = {
display: 'flex',
flexDirection: 'row',
overflowY: 'auto',
flex: 1,
};
const leftSidebar = {
padding: 12,
};
const horizontalTab = {
width: 250,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
textAlign: 'left',
fontSize: 16,
fontWeight: 'bold',
paddingLeft: 15,
paddingTop: 12,
paddingBottom: 12,
};
const iconContainer = {
width: 20,
height: 20,
marginRight: 15,
display: 'inline-flex',
justifyContent: 'center',
alignItems: 'center',
};
const icon = {
color: 'currentcolor',
height: 20,
};
const buttonStyle = {
backgroundColor: colors_1.BLUE,
color: 'white',
};
const flexer = {
flex: 1,
};
const outer = {
width: (0, ModalContainer_1.getMaxModalWidth)(1000),
height: (0, ModalContainer_1.getMaxModalHeight)(640),
overflow: 'hidden',
display: 'flex',
flexDirection: 'column',
};
const RenderModal = ({ initialFrame, initialVideoImageFormat, initialStillImageFormat, initialJpegQuality, initialScale, initialLogLevel, initialConcurrency, maxConcurrency, minConcurrency, initialMuted, initialEnforceAudioTrack, initialProResProfile, initialx264Preset, initialPixelFormat, initialVideoBitrate, initialAudioBitrate, initialEveryNthFrame, initialNumberOfGifLoops, initialDelayRenderTimeout, initialOffthreadVideoCacheSizeInBytes, initialEnvVariables, initialDisableWebSecurity, initialGl, initialHeadless, initialIgnoreCertificateErrors, initialEncodingBufferSize, initialEncodingMaxRate, initialOffthreadVideoThreads, initialMediaCacheSizeInBytes, initialUserAgent, defaultProps, inFrameMark, outFrameMark, initialColorSpace, initialMultiProcessOnLinux, defaultConfigurationAudioCodec, defaultConfigurationVideoCodec, initialBeep, initialRepro, initialForSeamlessAacConcatenation, renderTypeOfLastRender, initialHardwareAcceleration, defaultMetadata, initialChromeMode, renderDefaults, }) => {
const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
const context = (0, react_1.useContext)(ResolveCompositionBeforeModal_1.ResolvedCompositionContext);
if (!context) {
throw new Error('Should not be able to render without resolving comp first');
}
const { resolved: { result: resolvedComposition }, unresolved: unresolvedComposition, } = context;
const isMounted = (0, react_1.useRef)(true);
const [isVideo] = (0, react_1.useState)(() => {
return typeof resolvedComposition.durationInFrames === 'undefined'
? true
: resolvedComposition.durationInFrames > 1;
});
const [{ initialAudioCodec, initialRenderType, initialVideoCodec, initialVideoCodecForAudioTab, initialVideoCodecForVideoTab, },] = (0, react_1.useState)(() => {
return (0, get_default_codecs_1.getDefaultCodecs)({
defaultConfigurationVideoCodec,
compositionDefaultVideoCodec: resolvedComposition.defaultCodec,
defaultConfigurationAudioCodec,
renderType: renderTypeOfLastRender !== null && renderTypeOfLastRender !== void 0 ? renderTypeOfLastRender : (isVideo ? 'video' : 'still'),
});
});
const [state, dispatch] = (0, react_1.useReducer)(reducer, initialState);
const [unclampedFrame, setFrame] = (0, react_1.useState)(() => initialFrame);
const [saving, setSaving] = (0, react_1.useState)(false);
const [stillImageFormat, setStillImageFormat] = (0, react_1.useState)(() => initialStillImageFormat);
const [videoImageFormat, setVideoImageFormat] = (0, react_1.useState)(() => {
var _a;
return (_a = initialVideoImageFormat !== null && initialVideoImageFormat !== void 0 ? initialVideoImageFormat : resolvedComposition.defaultVideoImageFormat) !== null && _a !== void 0 ? _a : renderDefaults.videoImageFormat;
});
const [sequenceImageFormat, setSequenceImageFormat] = (0, react_1.useState)(() => initialStillImageFormat === 'jpeg' ? 'jpeg' : 'png');
const [concurrency, setConcurrency] = (0, react_1.useState)(() => initialConcurrency);
const [videoCodecForVideoTab, setVideoCodecForVideoTab] = (0, react_1.useState)(() => initialVideoCodecForVideoTab);
const [userSelectedAudioCodec, setUserSelectedAudioCodec] = (0, react_1.useState)(() => initialAudioCodec);
const [separateAudioTo, setSeparateAudioTo] = (0, react_1.useState)(null);
const [envVariables, setEnvVariables] = (0, react_1.useState)(() => (0, convert_env_variables_1.envVariablesObjectToArray)(initialEnvVariables).filter(([key]) => key !== 'NODE_ENV'));
const [initialOutName] = (0, react_1.useState)(() => {
return (0, studio_shared_1.getDefaultOutLocation)({
compositionName: resolvedComposition.id,
defaultExtension: initialRenderType === 'still'
? initialStillImageFormat
: isVideo
? client_1.BrowserSafeApis.getFileExtensionFromCodec(initialVideoCodec, initialAudioCodec)
: initialStillImageFormat,
type: 'asset',
compositionDefaultOutName: resolvedComposition.defaultOutName,
});
});
const [videoCodecForAudioTab, setVideoCodecForAudioTab] = (0, react_1.useState)(() => initialVideoCodecForAudioTab);
const [mutedState, setMuted] = (0, react_1.useState)(() => initialMuted);
const [repro, setRepro] = (0, react_1.useState)(() => initialRepro);
const [enforceAudioTrackState, setEnforceAudioTrackState] = (0, react_1.useState)(() => initialEnforceAudioTrack);
const [forSeamlessAacConcatenation, setForSeamlessAacConcatenation] = (0, react_1.useState)(() => initialForSeamlessAacConcatenation);
const [renderMode, setRenderModeState] = (0, react_1.useState)(initialRenderType);
const [jpegQuality, setJpegQuality] = (0, react_1.useState)(() => initialJpegQuality);
const [scale, setScale] = (0, react_1.useState)(() => initialScale);
const [logLevel, setLogLevel] = (0, react_1.useState)(() => initialLogLevel);
const [disallowParallelEncoding, setDisallowParallelEncoding] = (0, react_1.useState)(false);
const [disableWebSecurity, setDisableWebSecurity] = (0, react_1.useState)(() => initialDisableWebSecurity);
const [headless, setHeadless] = (0, react_1.useState)(() => initialHeadless);
const [beepOnFinish, setBeepOnFinish] = (0, react_1.useState)(() => initialBeep);
const [ignoreCertificateErrors, setIgnoreCertificateErrors] = (0, react_1.useState)(() => initialIgnoreCertificateErrors);
const [multiProcessOnLinux, setChromiumMultiProcessOnLinux] = (0, react_1.useState)(() => initialMultiProcessOnLinux);
const [openGlOption, setOpenGlOption] = (0, react_1.useState)(() => initialGl !== null && initialGl !== void 0 ? initialGl : 'default');
const [colorSpace, setColorSpace] = (0, react_1.useState)(() => initialColorSpace);
const [userAgent, setUserAgent] = (0, react_1.useState)(() => initialUserAgent === null
? null
: initialUserAgent.trim() === ''
? null
: initialUserAgent);
const chromiumOptions = (0, react_1.useMemo)(() => {
return {
headless,
disableWebSecurity,
ignoreCertificateErrors,
gl: openGlOption === 'default' ? null : openGlOption,
userAgent: userAgent === null ? null : userAgent.trim() === '' ? null : userAgent,
enableMultiProcessOnLinux: multiProcessOnLinux,
};
}, [
headless,
disableWebSecurity,
ignoreCertificateErrors,
openGlOption,
userAgent,
multiProcessOnLinux,
]);
const [outName, setOutName] = (0, react_1.useState)(() => initialOutName);
const [endFrameOrNull, setEndFrame] = (0, react_1.useState)(() => outFrameMark !== null && outFrameMark !== void 0 ? outFrameMark : null);
const [startFrameOrNull, setStartFrame] = (0, react_1.useState)(() => inFrameMark !== null && inFrameMark !== void 0 ? inFrameMark : null);
const [proResProfileSetting, setProResProfile] = (0, react_1.useState)(() => { var _a; return (_a = initialProResProfile !== null && initialProResProfile !== void 0 ? initialProResProfile : resolvedComposition.defaultProResProfile) !== null && _a !== void 0 ? _a : 'hq'; });
const [x264PresetSetting, setx264Preset] = (0, react_1.useState)(() => initialx264Preset);
const [hardwareAcceleration, setHardwareAcceleration] = (0, react_1.useState)(() => initialHardwareAcceleration);
const [userPreferredPixelFormat, setPixelFormat] = (0, react_1.useState)(() => {
var _a;
return (_a = initialPixelFormat !== null && initialPixelFormat !== void 0 ? initialPixelFormat : resolvedComposition.defaultPixelFormat) !== null && _a !== void 0 ? _a : renderDefaults.pixelFormat;
});
const [preferredQualityControlType, setQualityControl] = (0, react_1.useState)(() => initialVideoBitrate === null ? 'crf' : 'bitrate');
const [shouldHaveCustomTargetAudioBitrate, setShouldHaveCustomTargetAudioBitrate,] = (0, react_1.useState)(() => initialAudioBitrate !== null);
const [customTargetAudioBitrate, setCustomTargetAudioBitrateValue] = (0, react_1.useState)(() => initialAudioBitrate !== null && initialAudioBitrate !== void 0 ? initialAudioBitrate : '320K');
const [customTargetVideoBitrate, setCustomTargetVideoBitrateValue] = (0, react_1.useState)(() => initialVideoBitrate !== null && initialVideoBitrate !== void 0 ? initialVideoBitrate : '1M');
const [encodingMaxRate, setEncodingMaxRate] = (0, react_1.useState)(() => initialEncodingMaxRate !== null && initialEncodingMaxRate !== void 0 ? initialEncodingMaxRate : null);
const [encodingBufferSize, setEncodingBufferSize] = (0, react_1.useState)(() => initialEncodingBufferSize !== null && initialEncodingBufferSize !== void 0 ? initialEncodingBufferSize : null);
const [limitNumberOfGifLoops, setLimitNumberOfGifLoops] = (0, react_1.useState)(() => initialNumberOfGifLoops !== null);
const [numberOfGifLoopsSetting, setNumberOfGifLoopsSetting] = (0, react_1.useState)(() => initialNumberOfGifLoops !== null && initialNumberOfGifLoops !== void 0 ? initialNumberOfGifLoops : 0);
const [delayRenderTimeout, setDelayRenderTimeout] = (0, react_1.useState)(() => initialDelayRenderTimeout);
const [chromeMode, setChromeMode] = (0, react_1.useState)(() => initialChromeMode);
const [offthreadVideoCacheSizeInBytes, setOffthreadVideoCacheSizeInBytes] = (0, react_1.useState)(initialOffthreadVideoCacheSizeInBytes);
const [mediaCacheSizeInBytes, setMediaCacheSizeInBytes] = (0, react_1.useState)(initialMediaCacheSizeInBytes);
const [offthreadVideoThreads, setOffthreadVideoThreads] = (0, react_1.useState)(() => initialOffthreadVideoThreads);
const codec = (0, react_1.useMemo)(() => {
if (renderMode === 'audio') {
return videoCodecForAudioTab;
}
return videoCodecForVideoTab;
}, [videoCodecForAudioTab, renderMode, videoCodecForVideoTab]);
const numberOfGifLoops = (0, react_1.useMemo)(() => {
if (codec === 'gif' && limitNumberOfGifLoops) {
return numberOfGifLoopsSetting;
}
return null;
}, [codec, limitNumberOfGifLoops, numberOfGifLoopsSetting]);
const audioBitrate = (0, react_1.useMemo)(() => {
if (shouldHaveCustomTargetAudioBitrate) {
return customTargetAudioBitrate;
}
return null;
}, [customTargetAudioBitrate, shouldHaveCustomTargetAudioBitrate]);
const supportsCrf = client_1.BrowserSafeApis.codecSupportsCrf(codec);
const supportsVideoBitrate = client_1.BrowserSafeApis.codecSupportsVideoBitrate(codec);
const supportsBothQualityControls = (0, react_1.useMemo)(() => {
return supportsCrf && supportsVideoBitrate;
}, [supportsCrf, supportsVideoBitrate]);
const qualityControlType = (0, react_1.useMemo)(() => {
if (supportsBothQualityControls) {
return preferredQualityControlType;
}
if (supportsCrf) {
return 'crf';
}
if (supportsVideoBitrate) {
return 'bitrate';
}
return null;
}, [
preferredQualityControlType,
supportsBothQualityControls,
supportsCrf,
supportsVideoBitrate,
]);
const videoBitrate = (0, react_1.useMemo)(() => {
if (qualityControlType === 'bitrate') {
return customTargetVideoBitrate;
}
return null;
}, [customTargetVideoBitrate, qualityControlType]);
const { crf, maxCrf, minCrf, setCrf } = (0, CrfSetting_1.useCrfState)(codec);
const dispatchIfMounted = (0, react_1.useCallback)((payload) => {
if (isMounted.current === false)
return;
dispatch(payload);
}, []);
const muted = (0, react_1.useMemo)(() => {
if (renderMode === 'video') {
return mutedState;
}
return false;
}, [mutedState, renderMode]);
const enforceAudioTrack = (0, react_1.useMemo)(() => {
if (renderMode === 'video') {
return enforceAudioTrackState;
}
if (renderMode === 'audio') {
return enforceAudioTrackState;
}
return false;
}, [enforceAudioTrackState, renderMode]);
const proResProfile = (0, react_1.useMemo)(() => {
if (renderMode === 'video' && codec === 'prores') {
return proResProfileSetting;
}
return null;
}, [codec, proResProfileSetting, renderMode]);
const x264Preset = (0, react_1.useMemo)(() => {
if (renderMode === 'video' && codec === 'h264') {
return x264PresetSetting;
}
return null;
}, [codec, x264PresetSetting, renderMode]);
const [inputProps, setInputProps] = (0, react_1.useState)(() => defaultProps);
const [metadata] = (0, react_1.useState)(() => defaultMetadata);
const endFrame = (0, react_1.useMemo)(() => {
if (endFrameOrNull === null) {
return resolvedComposition.durationInFrames - 1;
}
return Math.max(0, Math.min(resolvedComposition.durationInFrames - 1, endFrameOrNull));
}, [resolvedComposition.durationInFrames, endFrameOrNull]);
const startFrame = (0, react_1.useMemo)(() => {
if (startFrameOrNull === null) {
return 0;
}
return Math.max(0, Math.min(endFrame - 1, startFrameOrNull));
}, [endFrame, startFrameOrNull]);
const frame = (0, react_1.useMemo)(() => {
const parsed = Math.floor(unclampedFrame);
return Math.max(0, Math.min(resolvedComposition.durationInFrames - 1, parsed));
}, [resolvedComposition.durationInFrames, unclampedFrame]);
const deriveFinalAudioCodec = (0, react_1.useCallback)((passedVideoCodec, passedAudioCodec) => {
if (passedAudioCodec !== null &&
client_1.BrowserSafeApis.supportedAudioCodecs[passedVideoCodec].includes(passedAudioCodec)) {
return passedAudioCodec;
}
return client_1.BrowserSafeApis.defaultAudioCodecs[passedVideoCodec]
.compressed;
}, []);
const setDefaultOutName = (0, react_1.useCallback)((options) => {
if (options.type === 'still') {
setOutName((prev) => {
const newFileName = (0, get_string_before_suffix_1.getStringBeforeSuffix)(prev) + '.' + options.imageFormat;
return newFileName;
});
}
else if (options.type === 'sequence') {
setOutName((prev) => {
const folderName = (0, get_string_before_suffix_1.getStringBeforeSuffix)(prev);
return folderName;
});
}
else {
setOutName((prev) => {
const codecSuffix = client_1.BrowserSafeApis.getFileExtensionFromCodec(options.codec, deriveFinalAudioCodec(options.codec, options.audioCodec));
const newFileName = (0, get_string_before_suffix_1.getStringBeforeSuffix)(prev) + '.' + codecSuffix;
return newFileName;
});
}
}, [deriveFinalAudioCodec]);
const setAudioCodec = (0, react_1.useCallback)((newAudioCodec) => {
setUserSelectedAudioCodec(newAudioCodec);
setDefaultOutName({
type: 'render',
codec: videoCodecForVideoTab,
audioCodec: newAudioCodec,
});
setSeparateAudioTo((prev) => {
if (prev === null) {
return null;
}
const newExtension = client_1.BrowserSafeApis.getExtensionFromAudioCodec(newAudioCodec);
const newFileName = (0, get_string_before_suffix_1.getStringBeforeSuffix)(prev) + '.' + newExtension;
return newFileName;
});
}, [setDefaultOutName, videoCodecForVideoTab]);
const setCodec = (0, react_1.useCallback)((newCodec) => {
if (renderMode === 'audio') {
setVideoCodecForAudioTab(newCodec);
}
else {
setVideoCodecForVideoTab(newCodec);
}
setDefaultOutName({
type: 'render',
codec: newCodec,
audioCodec: deriveFinalAudioCodec(newCodec, userSelectedAudioCodec),
});
}, [
userSelectedAudioCodec,
deriveFinalAudioCodec,
renderMode,
setDefaultOutName,
]);
const setStillFormat = (0, react_1.useCallback)((format) => {
setStillImageFormat(format);
setDefaultOutName({ type: 'still', imageFormat: format });
}, [setDefaultOutName]);
const { setSidebarCollapsedState } = (0, react_1.useContext)(sidebar_1.SidebarContext);
const onClickStill = (0, react_1.useCallback)(() => {
var _a;
setSidebarCollapsedState({ left: null, right: 'expanded' });
(0, OptionsPanel_1.persistSelectedOptionsSidebarPanel)('renders');
(_a = OptionsPanel_1.optionsSidebarTabs.current) === null || _a === void 0 ? void 0 : _a.selectRendersPanel();
dispatchIfMounted({ type: 'start' });
(0, actions_1.addStillRenderJob)({
compositionId: resolvedComposition.id,
outName,
imageFormat: stillImageFormat,
jpegQuality,
frame,
scale,
logLevel,
chromiumOptions,
delayRenderTimeout,
envVariables: (0, convert_env_variables_1.envVariablesArrayToObject)(envVariables),
inputProps,
offthreadVideoCacheSizeInBytes,
multiProcessOnLinux,
beepOnFinish,
metadata,
chromeMode,
offthreadVideoThreads,
mediaCacheSizeInBytes,
})
.then(() => {
dispatchIfMounted({ type: 'succeed' });
setSelectedModal(null);
})
.catch(() => {
dispatchIfMounted({ type: 'fail' });
});
}, [
setSidebarCollapsedState,
dispatchIfMounted,
resolvedComposition.id,
outName,
stillImageFormat,
jpegQuality,
frame,
scale,
logLevel,
chromiumOptions,
delayRenderTimeout,
envVariables,
inputProps,
offthreadVideoCacheSizeInBytes,
multiProcessOnLinux,
beepOnFinish,
setSelectedModal,
metadata,
chromeMode,
offthreadVideoThreads,
mediaCacheSizeInBytes,
]);
const [everyNthFrameSetting, setEveryNthFrameSetting] = (0, react_1.useState)(() => initialEveryNthFrame);
const everyNthFrame = (0, react_1.useMemo)(() => {
if (codec === 'gif') {
return everyNthFrameSetting;
}
return 1;
}, [codec, everyNthFrameSetting]);
const audioCodec = deriveFinalAudioCodec(codec, userSelectedAudioCodec);
const availablePixelFormats = (0, react_1.useMemo)(() => {
return client_1.BrowserSafeApis.validPixelFormatsForCodec(codec);
}, [codec]);
const pixelFormat = (0, react_1.useMemo)(() => {
if (availablePixelFormats.includes(userPreferredPixelFormat)) {
return userPreferredPixelFormat;
}
return availablePixelFormats[0];
}, [availablePixelFormats, userPreferredPixelFormat]);
const onClickVideo = (0, react_1.useCallback)(() => {
var _a;
setSidebarCollapsedState({ left: null, right: 'expanded' });
(0, OptionsPanel_1.persistSelectedOptionsSidebarPanel)('renders');
(_a = OptionsPanel_1.optionsSidebarTabs.current) === null || _a === void 0 ? void 0 : _a.selectRendersPanel();
dispatchIfMounted({ type: 'start' });
(0, actions_1.addVideoRenderJob)({
compositionId: resolvedComposition.id,
outName,
imageFormat: videoImageFormat,
jpegQuality: stillImageFormat === 'jpeg' ? jpegQuality : null,
scale,
logLevel,
codec,
concurrency,
crf: qualityControlType === 'crf' ? crf : null,
endFrame,
startFrame,
muted,
enforceAudioTrack,
proResProfile,
x264Preset,
pixelFormat,
audioBitrate,
videoBitrate,
everyNthFrame,
numberOfGifLoops,
delayRenderTimeout,
audioCodec,
disallowParallelEncoding,
chromiumOptions,
envVariables: (0, convert_env_variables_1.envVariablesArrayToObject)(envVariables),
inputProps,
offthreadVideoCacheSizeInBytes,
colorSpace,
multiProcessOnLinux,
encodingBufferSize,
encodingMaxRate,
beepOnFinish,
repro,
forSeamlessAacConcatenation,
separateAudioTo,
metadata,
hardwareAcceleration,
chromeMode,
offthreadVideoThreads,
mediaCacheSizeInBytes,
})
.then(() => {
dispatchIfMounted({ type: 'succeed' });
setSelectedModal(null);
})
.catch(() => {
dispatchIfMounted({ type: 'fail' });
});
}, [
setSidebarCollapsedState,
dispatchIfMounted,
resolvedComposition.id,
outName,
videoImageFormat,
stillImageFormat,
jpegQuality,
scale,
logLevel,
codec,
concurrency,
qualityControlType,
crf,
endFrame,
startFrame,
muted,
enforceAudioTrack,
proResProfile,
x264Preset,
pixelFormat,
audioBitrate,
videoBitrate,
everyNthFrame,
numberOfGifLoops,
delayRenderTimeout,
audioCodec,
disallowParallelEncoding,
chromiumOptions,
envVariables,
inputProps,
offthreadVideoCacheSizeInBytes,
colorSpace,
multiProcessOnLinux,
encodingBufferSize,
encodingMaxRate,
beepOnFinish,
repro,
forSeamlessAacConcatenation,
separateAudioTo,
setSelectedModal,
metadata,
hardwareAcceleration,
chromeMode,
offthreadVideoThreads,
mediaCacheSizeInBytes,
]);
const onClickSequence = (0, react_1.useCallback)(() => {
var _a;
setSidebarCollapsedState({ left: null, right: 'expanded' });
(0, OptionsPanel_1.persistSelectedOptionsSidebarPanel)('renders');
(_a = OptionsPanel_1.optionsSidebarTabs.current) === null || _a === void 0 ? void 0 : _a.selectRendersPanel();
dispatchIfMounted({ type: 'start' });
(0, actions_1.addSequenceRenderJob)({
compositionId: resolvedComposition.id,
outName,
imageFormat: sequenceImageFormat,
scale,
logLevel,
concurrency,
endFrame,
jpegQuality,
startFrame,
delayRenderTimeout,
chromiumOptions,
envVariables: (0, convert_env_variables_1.envVariablesArrayToObject)(envVariables),
inputProps,
offthreadVideoCacheSizeInBytes,
disallowParallelEncoding,
multiProcessOnLinux,
beepOnFinish,
repro,
metadata,
chromeMode,
offthreadVideoThreads,
mediaCacheSizeInBytes,
})
.then(() => {
dispatchIfMounted({ type: 'succeed' });
setSelectedModal(null);
})
.catch(() => {
dispatchIfMounted({ type: 'fail' });
});
}, [
setSidebarCollapsedState,
dispatchIfMounted,
resolvedComposition.id,
outName,
sequenceImageFormat,
scale,
logLevel,
concurrency,
endFrame,
jpegQuality,
startFrame,
delayRenderTimeout,
chromiumOptions,
envVariables,
inputProps,
offthreadVideoCacheSizeInBytes,
disallowParallelEncoding,
multiProcessOnLinux,
beepOnFinish,
repro,
setSelectedModal,
metadata,
chromeMode,
offthreadVideoThreads,
mediaCacheSizeInBytes,
]);
(0, react_1.useEffect)(() => {
return () => {
isMounted.current = false;
};
}, []);
const imageFormatOptions = (0, react_1.useMemo)(() => {
if (renderMode === 'still') {
return [
{
label: 'PNG',
onClick: () => setStillFormat('png'),
key: 'png',
selected: stillImageFormat === 'png',
},
{
label: 'JPEG',
onClick: () => setStillFormat('jpeg'),
key: 'jpeg',
selected: stillImageFormat === 'jpeg',
},
{
label: 'PDF',
onClick: () => setStillFormat('pdf'),
key: 'pdf',
selected: stillImageFormat === 'pdf',
},
{
label: 'WebP',
onClick: () => setStillFormat('webp'),
key: 'webp',
selected: stillImageFormat === 'webp',
},
];
}
if (renderMode === 'sequence') {
return [
{
label: 'PNG',
onClick: () => setSequenceImageFormat('png'),
key: 'png',
selected: sequenceImageFormat === 'png',
},
{
label: 'JPEG',
onClick: () => setSequenceImageFormat('jpeg'),
key: 'jpeg',
selected: sequenceImageFormat === 'jpeg',
},
];
}
return [
{
label: 'PNG',
onClick: () => setVideoImageFormat('png'),
key: 'png',
selected: videoImageFormat === 'png',
},
{
label: 'JPEG',
onClick: () => setVideoImageFormat('jpeg'),
key: 'jpeg',
selected: videoImageFormat === 'jpeg',
},
];
}, [
renderMode,
videoImageFormat,
stillImageFormat,
setStillFormat,
sequenceImageFormat,
]);
const setRenderMode = (0, react_1.useCallback)((newRenderMode) => {
setRenderModeState(newRenderMode);
if (newRenderMode === 'audio') {
setDefaultOutName({
type: 'render',
codec: videoCodecForAudioTab,
audioCodec: deriveFinalAudioCodec(videoCodecForAudioTab, userSelectedAudioCodec),
});
}
if (newRenderMode === 'video') {
setDefaultOutName({
type: 'render',
codec: videoCodecForVideoTab,
audioCodec: deriveFinalAudioCodec(videoCodecForVideoTab, userSelectedAudioCodec),
});
}
if (newRenderMode === 'still') {
setDefaultOutName({ type: 'still', imageFormat: stillImageFormat });
}
if (newRenderMode === 'sequence') {
setDefaultOutName({ type: 'sequence' });
}
}, [
videoCodecForAudioTab,
userSelectedAudioCodec,
deriveFinalAudioCodec,
setDefaultOutName,
stillImageFormat,
videoCodecForVideoTab,
]);
const renderTabOptions = (0, react_1.useMemo)(() => {
if ((resolvedComposition === null || resolvedComposition === void 0 ? void 0 : resolvedComposition.durationInFrames) < 2) {
return [
{
label: 'Still',
onClick: () => {
setRenderMode('still');
},
key: 'still',
selected: renderMode === 'still',
},
];
}
return [
{
label: 'Still',
onClick: () => {
setRenderMode('still');
},
key: 'still',
selected: renderMode === 'still',
},
{
label: 'Video',
onClick: () => {
setRenderMode('video');
},
key: 'video',
selected: renderMode === 'video',
},
{
label: 'Audio',
onClick: () => {
setRenderMode('audio');
},
key: 'audio',
selected: renderMode === 'audio',
},
{
label: 'Image sequence',
onClick: () => {
setRenderMode('sequence');
},
key: 'sequence',
selected: renderMode === 'sequence',
},
];
}, [resolvedComposition === null || resolvedComposition === void 0 ? void 0 : resolvedComposition.durationInFrames, renderMode, setRenderMode]);
const outnameValidation = (0, out_name_checker_1.validateOutnameGui)({
outName,
codec,
audioCodec,
renderMode,
stillImageFormat,
separateAudioTo,
});
const { tab, setTab, shownTabs } = (0, render_modal_sections_1.useRenderModalSections)(renderMode, codec);
const { registerKeybinding } = (0, use_keybinding_1.useKeybinding)();
const renderDisabled = state.type === 'load' || !outnameValidation.valid;
const trigger = (0, react_1.useCallback)(() => {
if (renderMode === 'still') {
onClickStill();
}
else if (renderMode === 'sequence') {
onClickSequence();
}
else {
onClickVideo();
}
}, [renderMode, onClickStill, onClickSequence, onClickVideo]);
(0, react_1.useEffect)(() => {
if (renderDisabled) {
return;
}
const enter = registerKeybinding({
callback() {
trigger();
},
commandCtrlKey: true,
key: 'Enter',
event: 'keydown',
preventDefault: true,
triggerIfInputFieldFocused: true,
keepRegisteredWhenNotHighestContext: false,
});
return () => {
enter.unregister();
};
}, [registerKeybinding, renderDisabled, trigger]);
const pixelFormatOptions = (0, react_1.useMemo)(() => {
return availablePixelFormats.map((option) => {
return {
label: option,
onClick: () => setPixelFormat(option),
key: option,
id: option,
keyHint: null,
leftItem: pixelFormat === option ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
quickSwitcherLabel: null,
subMenu: null,
type: 'item',
value: option,
};
});
}, [availablePixelFormats, pixelFormat]);
return ((0, jsx_runtime_1.jsxs)("div", { style: outer, children: [(0, jsx_runtime_1.jsx)(ModalHeader_1.ModalHeader, { title: `Render ${resolvedComposition.id}` }), (0, jsx_runtime_1.jsxs)("div", { style: container, children: [(0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: renderTabOptions, needsWrapping: false }), (0, jsx_runtime_1.jsx)("div", { style: flexer }), (0, jsx_runtime_1.jsxs)(Button_1.Button, { autoFocus: true, onClick: trigger, disabled: renderDisabled, style: {
...buttonStyle,
backgroundColor: outnameValidation.valid ? colors_1.BLUE : colors_1.BLUE_DISABLED,
}, children: [state.type === 'idle' ? `Render ${renderMode}` : 'Rendering...', (0, jsx_runtime_1.jsx)(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: true })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: horizontalLayout, children: [(0, jsx_runtime_1.jsxs)("div", { style: leftSidebar, children: [shownTabs.includes('general') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'general', onClick: () => setTab('general'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(file_1.FileIcon, { style: icon }) }), "General"] })) : null, shownTabs.includes('data') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'data', onClick: () => setTab('data'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(data_1.DataIcon, { style: icon }) }), "Input Props"] })) : null, shownTabs.includes('picture') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'picture', onClick: () => setTab('picture'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(frame_1.PicIcon, { style: icon }) }), "Picture"] })) : null, shownTabs.includes('audio') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'audio', onClick: () => setTab('audio'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(audio_1.AudioIcon, { style: icon }) }), "Audio"] })) : null, shownTabs.includes('gif') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'gif', onClick: () => setTab('gif'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(gif_1.GifIcon, { style: icon }) }), "GIF"] })) : null, shownTabs.includes('advanced') ? ((0, jsx_runtime_1.jsxs)(vertical_1.VerticalTab, { style: horizontalTab, selected: tab === 'advanced', onClick: () => setTab('advanced'), children: [(0, jsx_runtime_1.jsx)("div", { style: iconContainer, children: (0, jsx_runtime_1.jsx)(gear_1.GearIcon, { style: icon }) }), "Other"] })) : null] }), (0, jsx_runtime_1.jsx)("div", { style: optionsPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: tab === 'general' ? ((0, jsx_runtime_1.jsx)(RenderModalBasic_1.RenderModalBasic, { codec: codec, resolvedComposition: resolvedComposition, frame: frame, imageFormatOptions: imageFormatOptions, outName: outName, proResProfile: proResProfile, renderMode: renderMode, setVideoCodec: setCodec, setFrame: setFrame, setOutName: setOutName, setProResProfile: setProResProfile, endFrame: endFrame, setEndFrame: setEndFrame, setStartFrame: setStartFrame, setVerboseLogging: setLogLevel, logLevel: logLevel, startFrame: startFrame, validationMessage: outnameValidation.valid ? null : outnameValidation.error.message })) : tab === 'picture' ? ((0, jsx_runtime_1.jsx)(RenderModalPicture_1.RenderModalPicture, { renderMode: renderMode, scale: scale, setScale: setScale, pixelFormat: pixelFormat, pixelFormatOptions: pixelFormatOptions, imageFormatOptions: imageFormatOptions, crf: crf, setCrf: setCrf, customTargetVideoBitrate: customTargetVideoBitrate, maxCrf: maxCrf, minCrf: minCrf, jpegQuality: jpegQuality, qualityControlType: qualityControlType, setJpegQuality: setJpegQuality, setColorSpace: setColorSpace, colorSpace: colorSpace, setCustomTargetVideoBitrateValue: setCustomTargetVideoBitrateValue, setQualityControl: setQualityControl, videoImageFormat: videoImageFormat, stillImageFormat: stillImageFormat, shouldDisplayQualityControlPicker: supportsBothQualityControls, encodingBufferSize: encodingBufferSize, setEncodingBufferSize: setEncodingBufferSize, encodingMaxRate: encodingMaxRate, setEncodingMaxRate: setEncodingMaxRate, compositionWidth: resolvedComposition.width, compositionHeight: resolvedComposition.height })) : tab === 'audio' ? ((0, jsx_runtime_1.jsx)(RenderModalAudio_1.RenderModalAudio, { muted: muted, renderMode: renderMode, setMuted: setMuted, codec: codec, audioCodec: audioCodec, setAudioCodec: setAudioCodec, enforceAudioTrack: enforceAudioTrack, setEnforceAudioTrackState: setEnforceAudioTrackState, customTargetAudioBitrate: customTargetAudioBitrate, setCustomTargetAudioBitrateValue: setCustomTargetAudioBitrateValue, setShouldHaveCustomTargetAudioBitrate: setShouldHaveCustomTargetAudioBitrate, shouldHaveCustomTargetAudioBitrate: shouldHaveCustomTargetAudioBitrate, forSeamlessAacConcatenation: forSeamlessAacConcatenation, setForSeamlessAacConcatenation: setForSeamlessAacConcatenation, separateAudioTo: separateAudioTo, setSeparateAudioTo: setSeparateAudioTo, outName: outName })) : tab === 'gif' ? ((0, jsx_runtime_1.jsx)(RenderModalGif_1.RenderModalGif, { everyNthFrame: everyNthFrame, limitNumberOfGifLoops: limitNumberOfGifLoops, numberOfGifLoopsSetting: numberOfGifLoopsSetting, setEveryNthFrameSetting: setEveryNthFrameSetting, setLimitNumberOfGifLoops: setLimitNumberOfGifLoops, setNumberOfGifLoopsSetting: setNumberOfGifLoopsSetting })) : 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 })) : ((0, jsx_runtime_1.jsx)(RenderModalAdvanced_1.RenderModalAdvanced, { x264Preset: x264Preset, setx264Preset: setx264Preset, concurrency: concurrency, maxConcurrency: maxConcurrency, minConcurrency: minConcurrency, renderMode: renderMode, setConcurrency: setConcurrency, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, disallowParallelEncoding: disallowParallelEncoding, setDisallowParallelEncoding: setDisallowParallelEncoding, setDisableWebSecurity: setDisableWebSecurity, setIgnoreCertificateErrors: setIgnoreCertificateErrors, setHeadless: setHeadless, headless: headless, ignoreCertificateErrors: ignoreCertificateErrors, disableWebSecurity: disableWebSecurity, openGlOption: openGlOption, setOpenGlOption: setOpenGlOption, setEnvVariables: setEnvVariables, envVariables: envVariables, offthreadVideoCacheSizeInBytes: offthreadVideoCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setOffthreadVideoCacheSizeInBytes: setOffthreadVideoCacheSizeInBytes, offthreadVideoThreads: offthreadVideoThreads, setOffthreadVideoThreads: setOffthreadVideoThreads, enableMultiProcessOnLinux: multiProcessOnLinux, setChromiumMultiProcessOnLinux: setChromiumMultiProcessOnLinux, codec: codec, userAgent: userAgent, setUserAgent: setUserAgent, setBeep: setBeepOnFinish, beep: beepOnFinish, repro: repro, setRepro: setRepro, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration, chromeModeOption: chromeMode, setChromeModeOption: setChromeMode })) })] })] }));
};
const RenderModalWithLoader = (props) => {
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)(RenderModal, { ...props }) }) }));
};
exports.RenderModalWithLoader = RenderModalWithLoader;