@remotion/studio 4.0.487 → 4.0.489

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.
@@ -19,6 +19,8 @@ const use_keybinding_1 = require("../helpers/use-keybinding");
19
19
  const canvas_ref_1 = require("../state/canvas-ref");
20
20
  const editor_guides_1 = require("../state/editor-guides");
21
21
  const editor_zoom_gestures_1 = require("../state/editor-zoom-gestures");
22
+ const call_api_1 = require("./call-api");
23
+ const ConfirmationDialog_1 = require("./ConfirmationDialog");
22
24
  const EditorGuides_1 = __importDefault(require("./EditorGuides"));
23
25
  const EditorRuler_1 = require("./EditorRuler");
24
26
  const use_is_ruler_visible_1 = require("./EditorRuler/use-is-ruler-visible");
@@ -29,6 +31,31 @@ const layout_1 = require("./layout");
29
31
  const Preview_1 = require("./Preview");
30
32
  const ResetZoomButton_1 = require("./ResetZoomButton");
31
33
  const use_resolved_stack_1 = require("./Timeline/use-resolved-stack");
34
+ const elementInstallCompositionIdStyle = {
35
+ fontFamily: 'monospace',
36
+ fontSize: 13,
37
+ };
38
+ const elementInstallCodeDetailsStyle = {
39
+ marginTop: 12,
40
+ fontSize: 13,
41
+ };
42
+ const elementInstallCodeSummaryStyle = {
43
+ cursor: 'pointer',
44
+ fontSize: 13,
45
+ fontWeight: 500,
46
+ };
47
+ const elementInstallCodeBlockStyle = {
48
+ marginTop: 8,
49
+ marginBottom: 0,
50
+ maxHeight: 240,
51
+ overflow: 'auto',
52
+ padding: 12,
53
+ borderRadius: 6,
54
+ backgroundColor: 'rgba(255, 255, 255, 0.06)',
55
+ fontSize: 12,
56
+ lineHeight: 1.5,
57
+ whiteSpace: 'pre',
58
+ };
32
59
  const getContainerStyle = (editorZoomGestures) => ({
33
60
  flex: 1,
34
61
  display: 'flex',
@@ -183,12 +210,20 @@ const Canvas = ({ canvasContent, size }) => {
183
210
  const suppressWheelFromWebKitPinchRef = (0, react_1.useRef)(false);
184
211
  const touchPinchRef = (0, react_1.useRef)(null);
185
212
  const keybindings = (0, use_keybinding_1.useKeybinding)();
213
+ const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
186
214
  const config = remotion_1.Internals.useUnsafeVideoConfig();
187
215
  const areRulersVisible = (0, use_is_ruler_visible_1.useIsRulerVisible)();
188
216
  const { editorShowGuides } = (0, react_1.useContext)(editor_guides_1.EditorShowGuidesContext);
189
217
  const { compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
190
- const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
218
+ const { previewServerState, subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
219
+ const previewServerClientId = previewServerState.type === 'connected'
220
+ ? previewServerState.clientId
221
+ : null;
191
222
  const [isAddingAsset, setIsAddingAsset] = (0, react_1.useState)(false);
223
+ const [installingElementName, setInstallingElementName] = (0, react_1.useState)(null);
224
+ const [pendingElementInstallRequests, setPendingElementInstallRequests] = (0, react_1.useState)([]);
225
+ const [activeElementInstallRequest, setActiveElementInstallRequest] = (0, react_1.useState)(null);
226
+ const lastFocusedAtRef = (0, react_1.useRef)(typeof document === 'undefined' || document.hasFocus() ? Date.now() : null);
192
227
  const [assetResolution, setAssetResolution] = (0, react_1.useState)(null);
193
228
  const currentCompositionId = canvasContent.type === 'composition' ? canvasContent.compositionId : null;
194
229
  const currentComposition = (0, react_1.useMemo)(() => {
@@ -204,12 +239,12 @@ const Canvas = ({ canvasContent, size }) => {
204
239
  compositionFile,
205
240
  compositionId: currentCompositionId,
206
241
  });
207
- const canDropAssets = previewServerState.type === 'connected' &&
242
+ const canInstallElements = previewServerClientId !== null &&
208
243
  !window.remotion_isReadOnlyStudio &&
209
244
  (compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === true &&
210
245
  currentCompositionId !== null &&
211
- compositionFile !== null &&
212
- !isAddingAsset;
246
+ compositionFile !== null;
247
+ const canDropAssets = canInstallElements && !isAddingAsset;
213
248
  const contentDimensions = (0, react_1.useMemo)(() => {
214
249
  if ((canvasContent.type === 'asset' ||
215
250
  canvasContent.type === 'output' ||
@@ -576,6 +611,124 @@ const Canvas = ({ canvasContent, size }) => {
576
611
  (0, react_1.useEffect)(() => {
577
612
  fetchMetadata();
578
613
  }, [fetchMetadata]);
614
+ const updateElementInstallTarget = (0, react_1.useCallback)((requestId) => {
615
+ if (previewServerClientId === null) {
616
+ return;
617
+ }
618
+ (0, call_api_1.callApi)('/api/update-element-install-target', {
619
+ requestId,
620
+ clientId: previewServerClientId,
621
+ compositionFile: canInstallElements ? compositionFile : null,
622
+ compositionId: canInstallElements ? currentCompositionId : null,
623
+ canInstall: canInstallElements,
624
+ lastFocusedAt: lastFocusedAtRef.current,
625
+ readOnly: window.remotion_isReadOnlyStudio,
626
+ }).catch(() => undefined);
627
+ }, [
628
+ canInstallElements,
629
+ compositionFile,
630
+ currentCompositionId,
631
+ previewServerClientId,
632
+ ]);
633
+ (0, react_1.useEffect)(() => {
634
+ const markFocused = () => {
635
+ lastFocusedAtRef.current = Date.now();
636
+ };
637
+ window.addEventListener('focus', markFocused);
638
+ document.addEventListener('pointerdown', markFocused, { capture: true });
639
+ return () => {
640
+ window.removeEventListener('focus', markFocused);
641
+ document.removeEventListener('pointerdown', markFocused, { capture: true });
642
+ };
643
+ }, []);
644
+ (0, react_1.useEffect)(() => {
645
+ return subscribeToEvent('request-element-install-target', (event) => {
646
+ if (event.type !== 'request-element-install-target') {
647
+ return;
648
+ }
649
+ updateElementInstallTarget(event.requestId);
650
+ });
651
+ }, [subscribeToEvent, updateElementInstallTarget]);
652
+ (0, react_1.useEffect)(() => {
653
+ if (installingElementName === null) {
654
+ return;
655
+ }
656
+ const previousTitle = document.title;
657
+ document.title = `📦 Install ${installingElementName} - Remotion Studio`;
658
+ return () => {
659
+ document.title = previousTitle;
660
+ };
661
+ }, [installingElementName]);
662
+ (0, react_1.useEffect)(() => {
663
+ if (previewServerClientId === null) {
664
+ return;
665
+ }
666
+ return subscribeToEvent('element-install-request', (event) => {
667
+ if (event.type !== 'element-install-request' ||
668
+ event.request.clientId !== previewServerClientId) {
669
+ return;
670
+ }
671
+ setPendingElementInstallRequests((requests) => [
672
+ ...requests,
673
+ event.request,
674
+ ]);
675
+ });
676
+ }, [previewServerClientId, subscribeToEvent]);
677
+ (0, react_1.useEffect)(() => {
678
+ if (activeElementInstallRequest !== null ||
679
+ pendingElementInstallRequests.length === 0) {
680
+ return;
681
+ }
682
+ const [nextRequest, ...remainingRequests] = pendingElementInstallRequests;
683
+ if (!nextRequest) {
684
+ throw new Error('Expected pending Element install request');
685
+ }
686
+ setActiveElementInstallRequest(nextRequest);
687
+ setPendingElementInstallRequests(remainingRequests);
688
+ }, [activeElementInstallRequest, pendingElementInstallRequests]);
689
+ (0, react_1.useEffect)(() => {
690
+ if (activeElementInstallRequest === null) {
691
+ return;
692
+ }
693
+ let canceled = false;
694
+ const handleInstallRequest = async () => {
695
+ setInstallingElementName(activeElementInstallRequest.element.displayName);
696
+ const accepted = await confirm({
697
+ title: 'Install Element',
698
+ message: (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: ["Install \u201C", activeElementInstallRequest.element.displayName, "\u201D into", ' ', jsx_runtime_1.jsx("code", { style: elementInstallCompositionIdStyle, children: activeElementInstallRequest.compositionId }), ' ', "composition? This will create an Element source file and update the composition source.",
699
+ jsx_runtime_1.jsxs("details", { style: elementInstallCodeDetailsStyle, children: [
700
+ jsx_runtime_1.jsx("summary", { style: elementInstallCodeSummaryStyle, children: "Preview Element source" }), jsx_runtime_1.jsx("pre", { style: elementInstallCodeBlockStyle, children: jsx_runtime_1.jsx("code", { children: activeElementInstallRequest.element.sourceCode }) })
701
+ ] })
702
+ ] })),
703
+ confirmLabel: 'Install',
704
+ cancelLabel: 'Cancel',
705
+ });
706
+ if (accepted && !canceled) {
707
+ await (0, import_assets_1.insertElement)({
708
+ element: activeElementInstallRequest.element,
709
+ compositionFile: activeElementInstallRequest.compositionFile,
710
+ compositionId: activeElementInstallRequest.compositionId,
711
+ dropPosition: null,
712
+ });
713
+ }
714
+ };
715
+ handleInstallRequest()
716
+ .finally(() => {
717
+ if (canceled) {
718
+ return;
719
+ }
720
+ setInstallingElementName(null);
721
+ setActiveElementInstallRequest(null);
722
+ })
723
+ .catch((err) => {
724
+ setTimeout(() => {
725
+ throw err;
726
+ }, 0);
727
+ });
728
+ return () => {
729
+ canceled = true;
730
+ };
731
+ }, [activeElementInstallRequest, confirm]);
579
732
  const onDragOver = (0, react_1.useCallback)((event) => {
580
733
  if (!canDropAssets ||
581
734
  (!isFileDragEvent(event) &&
@@ -40,6 +40,7 @@ const react_1 = __importStar(require("react"));
40
40
  const remotion_1 = require("remotion");
41
41
  const colors_1 = require("../helpers/colors");
42
42
  const noop_1 = require("../helpers/noop");
43
+ const studio_runtime_config_1 = require("../helpers/studio-runtime-config");
43
44
  const canvas_ref_1 = require("../state/canvas-ref");
44
45
  const scale_lock_1 = require("../state/scale-lock");
45
46
  const timeline_zoom_1 = require("../state/timeline-zoom");
@@ -61,11 +62,7 @@ const background = {
61
62
  flexDirection: 'column',
62
63
  position: 'absolute',
63
64
  };
64
- const DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS = 300;
65
- exports.BUFFER_STATE_DELAY_IN_MILLISECONDS = typeof process.env.BUFFER_STATE_DELAY_IN_MILLISECONDS === 'undefined' ||
66
- process.env.BUFFER_STATE_DELAY_IN_MILLISECONDS === null
67
- ? DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS
68
- : Number(process.env.BUFFER_STATE_DELAY_IN_MILLISECONDS);
65
+ exports.BUFFER_STATE_DELAY_IN_MILLISECONDS = (0, studio_runtime_config_1.getStudioBufferStateDelayInMilliseconds)();
69
66
  const Editor = ({ Root, readOnlyStudio }) => {
70
67
  const [drawElement, setDrawElement] = (0, react_1.useState)(null);
71
68
  const size = player_1.PlayerInternals.useElementSize(drawElement, {
@@ -6,6 +6,7 @@ const remotion_1 = require("remotion");
6
6
  const calculate_timeline_1 = require("../helpers/calculate-timeline");
7
7
  const client_id_1 = require("../helpers/client-id");
8
8
  const show_browser_rendering_1 = require("../helpers/show-browser-rendering");
9
+ const studio_runtime_config_1 = require("../helpers/studio-runtime-config");
9
10
  const timeline_node_path_key_1 = require("../helpers/timeline-node-path-key");
10
11
  const use_keybinding_1 = require("../helpers/use-keybinding");
11
12
  const checkerboard_1 = require("../state/checkerboard");
@@ -134,7 +135,7 @@ const GlobalKeybindings = ({ readOnlyStudio }) => {
134
135
  commandCtrlKey: true,
135
136
  preventDefault: true,
136
137
  });
137
- const cmdIKey = process.env.ASK_AI_ENABLED
138
+ const cmdIKey = (0, studio_runtime_config_1.getStudioAskAIEnabled)()
138
139
  ? keybindings.registerKeybinding({
139
140
  event: 'keydown',
140
141
  key: 'i',
@@ -4,6 +4,7 @@ exports.DefaultInspector = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
+ const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
7
8
  const VisualControls_1 = require("../../visual-controls/VisualControls");
8
9
  const CurrentAsset_1 = require("../CurrentAsset");
9
10
  const CurrentComposition_1 = require("../CurrentComposition");
@@ -27,7 +28,7 @@ const DefaultInspector = ({ composition, currentDefaultProps, readOnlyStudio, se
27
28
  const { handles: visualControlHandles } = (0, react_1.useContext)(VisualControls_1.VisualControlsContext);
28
29
  const [defaultPropsMode, setDefaultPropsMode] = (0, react_1.useState)('schema');
29
30
  const compositionId = (_a = composition === null || composition === void 0 ? void 0 : composition.id) !== null && _a !== void 0 ? _a : null;
30
- const hasVisualControls = Object.keys(visualControlHandles).length > 0;
31
+ const hasVisualControls = interactivity_enabled_1.studioInteractivityEnabled && Object.keys(visualControlHandles).length > 0;
31
32
  (0, react_1.useEffect)(() => {
32
33
  setDefaultPropsMode('schema');
33
34
  }, [compositionId]);
@@ -4,6 +4,7 @@ exports.KeyboardShortcutsExplainer = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ShortcutHint_1 = require("../error-overlay/remotion-overlay/ShortcutHint");
6
6
  const colors_1 = require("../helpers/colors");
7
+ const studio_runtime_config_1 = require("../helpers/studio-runtime-config");
7
8
  const use_keybinding_1 = require("../helpers/use-keybinding");
8
9
  const keys_1 = require("../icons/keys");
9
10
  const layout_1 = require("./layout");
@@ -174,7 +175,7 @@ const KeyboardShortcutsExplainer = () => {
174
175
  jsx_runtime_1.jsxs("div", { style: left, children: [
175
176
  jsx_runtime_1.jsx("kbd", { style: key, children: "Del" }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "\u232B" })
176
177
  ] }), jsx_runtime_1.jsx("div", { style: right, children: "Delete / reset selection" })
177
- ] }), process.env.ASK_AI_ENABLED && (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
178
+ ] }), (0, studio_runtime_config_1.getStudioAskAIEnabled)() && (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
178
179
  jsx_runtime_1.jsx("br", {}), jsx_runtime_1.jsx("div", { style: title, children: "AI" }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
179
180
  jsx_runtime_1.jsxs("div", { style: left, children: [
180
181
  jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "I" })
@@ -7,6 +7,7 @@ exports.Modals = void 0;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const react_1 = require("react");
9
9
  const client_id_1 = require("../helpers/client-id");
10
+ const studio_runtime_config_1 = require("../helpers/studio-runtime-config");
10
11
  const modals_1 = require("../state/modals");
11
12
  const AskAiModal_1 = require("./AskAiModal");
12
13
  const ConfirmationDialog_1 = require("./ConfirmationDialog");
@@ -34,6 +35,6 @@ const Modals = ({ readOnlyStudio }) => {
34
35
  'connected';
35
36
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [modalContextType && modalContextType.type === 'new-comp' && (jsx_runtime_1.jsx(NewComposition_1.NewComposition, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'new-folder' && (jsx_runtime_1.jsx(NewFolder_1.NewFolder, { parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'duplicate-comp' && (jsx_runtime_1.jsx(DuplicateComposition_1.DuplicateComposition, { compositionType: modalContextType.compositionType, compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-comp' && (jsx_runtime_1.jsx(DeleteComposition_1.DeleteComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'rename-comp' && (jsx_runtime_1.jsx(RenameComposition_1.RenameComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-folder' && (jsx_runtime_1.jsx(DeleteFolder_1.DeleteFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-folder' && (jsx_runtime_1.jsx(RenameFolder_1.RenameFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-static-file' && (jsx_runtime_1.jsx(RenameStaticFile_1.RenameStaticFileModal, { relativePath: modalContextType.relativePath })), modalContextType && modalContextType.type === 'input-props-override' && (jsx_runtime_1.jsx(OverrideInputProps_1.OverrideInputPropsModal, {})), modalContextType && modalContextType.type === 'keyframe-settings' && (jsx_runtime_1.jsx(KeyframeSettingsModal_1.KeyframeSettingsModal, { state: modalContextType })), modalContextType && modalContextType.type === 'web-render' && (jsx_runtime_1.jsx(WebRenderModal_1.WebRenderModalWithLoader, { ...modalContextType })), modalContextType &&
36
37
  modalContextType.type === 'server-render' &&
37
- (canRender || modalContextType.readOnlyStudio) ? (jsx_runtime_1.jsx(ServerRenderModal_1.RenderModalWithLoader, { readOnlyStudio: (_a = modalContextType.readOnlyStudio) !== null && _a !== void 0 ? _a : false, initialFrame: modalContextType.initialFrame, initialDarkMode: modalContextType.initialDarkMode, compositionId: modalContextType.compositionId, initialVideoImageFormat: modalContextType.initialVideoImageFormat, initialJpegQuality: modalContextType.initialJpegQuality, initialScale: modalContextType.initialScale, initialLogLevel: modalContextType.initialLogLevel, initialOffthreadVideoCacheSizeInBytes: modalContextType.initialOffthreadVideoCacheSizeInBytes, initialOffthreadVideoThreads: modalContextType.initialOffthreadVideoThreads, initialMediaCacheSizeInBytes: modalContextType.initialMediaCacheSizeInBytes, initialConcurrency: modalContextType.initialConcurrency, maxConcurrency: modalContextType.maxConcurrency, minConcurrency: modalContextType.minConcurrency, initialStillImageFormat: modalContextType.initialStillImageFormat, initialMuted: modalContextType.initialMuted, initialEnforceAudioTrack: modalContextType.initialEnforceAudioTrack, initialProResProfile: modalContextType.initialProResProfile, initialx264Preset: modalContextType.initialx264Preset, initialGopSize: modalContextType.initialGopSize, initialPixelFormat: modalContextType.initialPixelFormat, initialAudioBitrate: modalContextType.initialAudioBitrate, initialVideoBitrate: modalContextType.initialVideoBitrate, initialEveryNthFrame: modalContextType.initialEveryNthFrame, initialNumberOfGifLoops: modalContextType.initialNumberOfGifLoops, initialDelayRenderTimeout: modalContextType.initialDelayRenderTimeout, initialEnvVariables: modalContextType.initialEnvVariables, initialDisableWebSecurity: modalContextType.initialDisableWebSecurity, initialGl: modalContextType.initialOpenGlRenderer, initialHeadless: modalContextType.initialHeadless, initialIgnoreCertificateErrors: modalContextType.initialIgnoreCertificateErrors, initialEncodingBufferSize: modalContextType.initialEncodingBufferSize, initialEncodingMaxRate: modalContextType.initialEncodingMaxRate, initialUserAgent: modalContextType.initialUserAgent, initialColorSpace: modalContextType.initialColorSpace, initialMultiProcessOnLinux: modalContextType.initialMultiProcessOnLinux, initialRepro: modalContextType.initialRepro, initialBeep: modalContextType.initialBeep, initialForSeamlessAacConcatenation: modalContextType.initialForSeamlessAacConcatenation, defaultProps: modalContextType.defaultProps, inFrameMark: modalContextType.inFrameMark, outFrameMark: modalContextType.outFrameMark, defaultConfigurationAudioCodec: modalContextType.defaultConfigurationAudioCodec, defaultConfigurationVideoCodec: modalContextType.defaultConfigurationVideoCodec, renderTypeOfLastRender: modalContextType.renderTypeOfLastRender, defaultMetadata: modalContextType.defaulMetadata, initialHardwareAcceleration: modalContextType.initialHardwareAcceleration, initialSampleRate: modalContextType.initialSampleRate, initialChromeMode: modalContextType.initialChromeMode, renderDefaults: modalContextType.renderDefaults })) : null, modalContextType && modalContextType.type === 'render-progress' && (jsx_runtime_1.jsx(RenderStatusModal_1.RenderStatusModal, { jobId: modalContextType.jobId })), modalContextType && modalContextType.type === 'update' && (jsx_runtime_1.jsx(UpdateModal_1.UpdateModal, { info: modalContextType.info, knownBugs: modalContextType.knownBugs })), modalContextType && modalContextType.type === 'install-packages' && (jsx_runtime_1.jsx(InstallPackage_1.InstallPackageModal, { packageManager: modalContextType.packageManager })), modalContextType && modalContextType.type === 'quick-switcher' && (jsx_runtime_1.jsx(QuickSwitcher_1.default, { readOnlyStudio: readOnlyStudio, invocationTimestamp: modalContextType.invocationTimestamp, initialMode: modalContextType.mode })), modalContextType && modalContextType.type === 'add-effect' && (jsx_runtime_1.jsx(EffectPickerModal_1.EffectPickerModal, { state: modalContextType })), modalContextType && modalContextType.type === 'confirmation-dialog' && (jsx_runtime_1.jsx(ConfirmationDialog_1.ConfirmationDialog, { state: modalContextType })), process.env.ASK_AI_ENABLED && jsx_runtime_1.jsx(AskAiModal_1.AskAiModal, {})] }));
38
+ (canRender || modalContextType.readOnlyStudio) ? (jsx_runtime_1.jsx(ServerRenderModal_1.RenderModalWithLoader, { readOnlyStudio: (_a = modalContextType.readOnlyStudio) !== null && _a !== void 0 ? _a : false, initialFrame: modalContextType.initialFrame, initialDarkMode: modalContextType.initialDarkMode, compositionId: modalContextType.compositionId, initialVideoImageFormat: modalContextType.initialVideoImageFormat, initialJpegQuality: modalContextType.initialJpegQuality, initialScale: modalContextType.initialScale, initialLogLevel: modalContextType.initialLogLevel, initialOffthreadVideoCacheSizeInBytes: modalContextType.initialOffthreadVideoCacheSizeInBytes, initialOffthreadVideoThreads: modalContextType.initialOffthreadVideoThreads, initialMediaCacheSizeInBytes: modalContextType.initialMediaCacheSizeInBytes, initialConcurrency: modalContextType.initialConcurrency, maxConcurrency: modalContextType.maxConcurrency, minConcurrency: modalContextType.minConcurrency, initialStillImageFormat: modalContextType.initialStillImageFormat, initialMuted: modalContextType.initialMuted, initialEnforceAudioTrack: modalContextType.initialEnforceAudioTrack, initialProResProfile: modalContextType.initialProResProfile, initialx264Preset: modalContextType.initialx264Preset, initialGopSize: modalContextType.initialGopSize, initialPixelFormat: modalContextType.initialPixelFormat, initialAudioBitrate: modalContextType.initialAudioBitrate, initialVideoBitrate: modalContextType.initialVideoBitrate, initialEveryNthFrame: modalContextType.initialEveryNthFrame, initialNumberOfGifLoops: modalContextType.initialNumberOfGifLoops, initialDelayRenderTimeout: modalContextType.initialDelayRenderTimeout, initialEnvVariables: modalContextType.initialEnvVariables, initialDisableWebSecurity: modalContextType.initialDisableWebSecurity, initialGl: modalContextType.initialOpenGlRenderer, initialHeadless: modalContextType.initialHeadless, initialIgnoreCertificateErrors: modalContextType.initialIgnoreCertificateErrors, initialEncodingBufferSize: modalContextType.initialEncodingBufferSize, initialEncodingMaxRate: modalContextType.initialEncodingMaxRate, initialUserAgent: modalContextType.initialUserAgent, initialColorSpace: modalContextType.initialColorSpace, initialMultiProcessOnLinux: modalContextType.initialMultiProcessOnLinux, initialRepro: modalContextType.initialRepro, initialBeep: modalContextType.initialBeep, initialForSeamlessAacConcatenation: modalContextType.initialForSeamlessAacConcatenation, defaultProps: modalContextType.defaultProps, inFrameMark: modalContextType.inFrameMark, outFrameMark: modalContextType.outFrameMark, defaultConfigurationAudioCodec: modalContextType.defaultConfigurationAudioCodec, defaultConfigurationVideoCodec: modalContextType.defaultConfigurationVideoCodec, renderTypeOfLastRender: modalContextType.renderTypeOfLastRender, defaultMetadata: modalContextType.defaulMetadata, initialHardwareAcceleration: modalContextType.initialHardwareAcceleration, initialSampleRate: modalContextType.initialSampleRate, initialChromeMode: modalContextType.initialChromeMode, renderDefaults: modalContextType.renderDefaults })) : null, modalContextType && modalContextType.type === 'render-progress' && (jsx_runtime_1.jsx(RenderStatusModal_1.RenderStatusModal, { jobId: modalContextType.jobId })), modalContextType && modalContextType.type === 'update' && (jsx_runtime_1.jsx(UpdateModal_1.UpdateModal, { info: modalContextType.info, knownBugs: modalContextType.knownBugs })), modalContextType && modalContextType.type === 'install-packages' && (jsx_runtime_1.jsx(InstallPackage_1.InstallPackageModal, { packageManager: modalContextType.packageManager })), modalContextType && modalContextType.type === 'quick-switcher' && (jsx_runtime_1.jsx(QuickSwitcher_1.default, { readOnlyStudio: readOnlyStudio, invocationTimestamp: modalContextType.invocationTimestamp, initialMode: modalContextType.mode })), modalContextType && modalContextType.type === 'add-effect' && (jsx_runtime_1.jsx(EffectPickerModal_1.EffectPickerModal, { state: modalContextType })), modalContextType && modalContextType.type === 'confirmation-dialog' && (jsx_runtime_1.jsx(ConfirmationDialog_1.ConfirmationDialog, { state: modalContextType })), (0, studio_runtime_config_1.getStudioAskAIEnabled)() && jsx_runtime_1.jsx(AskAiModal_1.AskAiModal, {})] }));
38
39
  };
39
40
  exports.Modals = Modals;
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const colors_1 = require("../../helpers/colors");
7
7
  const mobile_layout_1 = require("../../helpers/mobile-layout");
8
+ const studio_runtime_config_1 = require("../../helpers/studio-runtime-config");
8
9
  const use_keybinding_1 = require("../../helpers/use-keybinding");
9
10
  const is_menu_item_1 = require("../Menu/is-menu-item");
10
11
  const MenuDivider_1 = require("../Menu/MenuDivider");
@@ -168,8 +169,7 @@ const MenuContent = ({ onHide, values, preselectIndex, onNextMenu, onPreviousMen
168
169
  return containerStyles;
169
170
  }, [fixedHeight, isMobileLayout]);
170
171
  (0, react_1.useEffect)(() => {
171
- if (!keybindings.isHighestContext ||
172
- !process.env.KEYBOARD_SHORTCUTS_ENABLED) {
172
+ if (!keybindings.isHighestContext || !(0, studio_runtime_config_1.getStudioKeyboardShortcutsEnabled)()) {
173
173
  return;
174
174
  }
175
175
  const onKeyDown = (event) => {
@@ -40,6 +40,7 @@ const react_1 = __importStar(require("react"));
40
40
  const remotion_1 = require("remotion");
41
41
  const no_react_1 = require("remotion/no-react");
42
42
  const client_id_1 = require("../helpers/client-id");
43
+ const interactivity_enabled_1 = require("../helpers/interactivity-enabled");
43
44
  const use_keybinding_1 = require("../helpers/use-keybinding");
44
45
  const editor_guides_1 = require("../state/editor-guides");
45
46
  const editor_outlines_1 = require("../state/editor-outlines");
@@ -158,7 +159,7 @@ const SelectedOutlineOverlay = ({ compositionHeight, compositionWidth, scale, tr
158
159
  selectItem(item, interaction, undefined, { reveal: true });
159
160
  }, [selectItem]);
160
161
  const outlineTargets = (0, react_1.useMemo)(() => {
161
- if (!editorShowOutlines) {
162
+ if (!interactivity_enabled_1.studioInteractivityEnabled || !editorShowOutlines) {
162
163
  return [];
163
164
  }
164
165
  const selectedSequenceKeys = (0, selected_outline_measurement_1.getSelectedSequenceKeys)(selectedItems);
@@ -2,13 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MaxTimelineTracksReached = exports.MAX_TIMELINE_TRACKS_NOTICE_HEIGHT = exports.MAX_TIMELINE_TRACKS = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const studio_shared_1 = require("@remotion/studio-shared");
6
5
  const colors_1 = require("../../helpers/colors");
6
+ const studio_runtime_config_1 = require("../../helpers/studio-runtime-config");
7
7
  const timeline_layout_1 = require("../../helpers/timeline-layout");
8
- exports.MAX_TIMELINE_TRACKS = typeof process.env.MAX_TIMELINE_TRACKS === 'undefined' ||
9
- process.env.MAX_TIMELINE_TRACKS === null
10
- ? studio_shared_1.DEFAULT_TIMELINE_TRACKS
11
- : Number(process.env.MAX_TIMELINE_TRACKS);
8
+ exports.MAX_TIMELINE_TRACKS = (0, studio_runtime_config_1.getStudioMaxTimelineTracks)();
12
9
  exports.MAX_TIMELINE_TRACKS_NOTICE_HEIGHT = 24;
13
10
  const container = {
14
11
  height: exports.MAX_TIMELINE_TRACKS_NOTICE_HEIGHT,
@@ -40,6 +40,7 @@ const remotion_1 = require("remotion");
40
40
  const calculate_timeline_1 = require("../../helpers/calculate-timeline");
41
41
  const client_id_1 = require("../../helpers/client-id");
42
42
  const colors_1 = require("../../helpers/colors");
43
+ const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
43
44
  const is_current_selected_still_1 = require("../../helpers/is-current-selected-still");
44
45
  const open_in_editor_1 = require("../../helpers/open-in-editor");
45
46
  const call_api_1 = require("../call-api");
@@ -88,6 +89,7 @@ const TimelineContextMenuArea = ({ children }) => {
88
89
  const [isAddingAsset, setIsAddingAsset] = (0, react_1.useState)(false);
89
90
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
90
91
  const previewConnected = previewServerState.type === 'connected';
92
+ const previewInteractive = previewConnected && interactivity_enabled_1.studioInteractivityEnabled;
91
93
  const currentCompositionId = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? canvasContent.compositionId : null;
92
94
  const currentComposition = (0, react_1.useMemo)(() => {
93
95
  var _a;
@@ -102,13 +104,13 @@ const TimelineContextMenuArea = ({ children }) => {
102
104
  compositionFile,
103
105
  compositionId: currentCompositionId,
104
106
  });
105
- const canInsertSolid = previewConnected &&
107
+ const canInsertSolid = previewInteractive &&
106
108
  (compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === true &&
107
109
  currentCompositionId !== null &&
108
110
  compositionFile !== null &&
109
111
  videoConfig !== null &&
110
112
  !isAddingSolid;
111
- const canInsertAsset = previewConnected &&
113
+ const canInsertAsset = previewInteractive &&
112
114
  !window.remotion_isReadOnlyStudio &&
113
115
  (compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === true &&
114
116
  currentCompositionId !== null &&
@@ -207,6 +209,7 @@ const TimelineInner = () => {
207
209
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
208
210
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
209
211
  const previewConnected = previewServerState.type === 'connected';
212
+ const previewInteractive = previewConnected && interactivity_enabled_1.studioInteractivityEnabled;
210
213
  const videoConfigIsNull = videoConfig === null;
211
214
  const timeline = (0, react_1.useMemo)(() => {
212
215
  if (videoConfigIsNull) {
@@ -228,15 +231,14 @@ const TimelineInner = () => {
228
231
  }, [filtered]);
229
232
  const hasBeenCut = filtered.length > shown.length;
230
233
  return (jsx_runtime_1.jsxs(TimelineContextMenuArea, { children: [sequences.map((sequence) => {
231
- if (!(0, should_subscribe_to_sequence_props_1.shouldSubscribeToSequenceProps)(sequence, previewConnected)) {
234
+ if (!(0, should_subscribe_to_sequence_props_1.shouldSubscribeToSequenceProps)(sequence, previewInteractive)) {
232
235
  return null;
233
236
  }
234
237
  return (jsx_runtime_1.jsx(SubscribeToNodePaths_1.SubscribeToNodePaths, { overrideId: sequence.controls.overrideId, componentIdentity: sequence.controls.componentIdentity, schema: sequence.controls.schema, getStack: sequence.getStack, effects: sequence.effects }, sequence.id));
235
- }), jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}), jsx_runtime_1.jsx(TimelineKeyframeTracksContext_1.TimelineKeyframeTracksProvider, { tracks: filtered, children: jsx_runtime_1.jsxs(TimelineSelection_1.TimelineSelectableItemsProvider, { timeline: shown, children: [
236
- jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown }), jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown })) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
238
+ }), interactivity_enabled_1.studioInteractivityEnabled ? jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}) : null, jsx_runtime_1.jsx(TimelineKeyframeTracksContext_1.TimelineKeyframeTracksProvider, { tracks: filtered, children: jsx_runtime_1.jsxs(TimelineSelection_1.TimelineSelectableItemsProvider, { timeline: shown, children: [interactivity_enabled_1.studioInteractivityEnabled ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown })) : null, jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown })) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
237
239
  jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, children: [
238
240
  jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "flexer", sticky: jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePlaceholders, {}), children: jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown }) }), jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: "none" }), jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "anti-flexer", sticky: null, children: jsx_runtime_1.jsxs(TimelineScrollable_1.TimelineScrollable, { children: [
239
- jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {}), jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
241
+ jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), interactivity_enabled_1.studioInteractivityEnabled ? (jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {})) : null, jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
240
242
  ] }) })
241
243
  ] })
242
244
  ] })) })
@@ -38,6 +38,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const player_1 = require("@remotion/player");
39
39
  const react_1 = __importStar(require("react"));
40
40
  const remotion_1 = require("remotion");
41
+ const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
41
42
  const timeline_layout_1 = require("../../helpers/timeline-layout");
42
43
  const timeline_zoom_1 = require("../../state/timeline-zoom");
43
44
  const z_index_1 = require("../../state/z-index");
@@ -88,7 +89,7 @@ const TimelineDragHandler = () => {
88
89
  if (!canvasContent || canvasContent.type !== 'composition') {
89
90
  return null;
90
91
  }
91
- return (jsx_runtime_1.jsx("div", { ref: timeline_refs_1.sliderAreaRef, style: containerStyle, [TimelineSelection_1.TIMELINE_SCRUBBER_ATTR]: true, children: video ? jsx_runtime_1.jsx(TimelineDragHandlerInnerMemo, {}) : null }));
92
+ return (jsx_runtime_1.jsx("div", { ref: timeline_refs_1.sliderAreaRef, style: containerStyle, [TimelineSelection_1.TIMELINE_SCRUBBER_ATTR]: true, children: video && interactivity_enabled_1.studioInteractivityEnabled ? (jsx_runtime_1.jsx(TimelineDragHandlerInnerMemo, {})) : null }));
92
93
  };
93
94
  exports.TimelineDragHandler = TimelineDragHandler;
94
95
  const TimelineDragHandlerInner = () => {
@@ -7,6 +7,7 @@ const react_1 = require("react");
7
7
  const remotion_1 = require("remotion");
8
8
  const client_id_1 = require("../../helpers/client-id");
9
9
  const colors_1 = require("../../helpers/colors");
10
+ const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
10
11
  const timeline_layout_1 = require("../../helpers/timeline-layout");
11
12
  const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
12
13
  const use_keybinding_1 = require("../../helpers/use-keybinding");
@@ -557,7 +558,8 @@ const TimelineSelectionProvider = ({ children }) => {
557
558
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
558
559
  const timelineSelectionScope = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? canvasContent.compositionId : null;
559
560
  const { expandParentTracks } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
560
- const canSelect = previewServerState.type === 'connected' &&
561
+ const canSelect = interactivity_enabled_1.studioInteractivityEnabled &&
562
+ previewServerState.type === 'connected' &&
561
563
  !window.remotion_isReadOnlyStudio;
562
564
  const [selectedItems, setSelectedItems] = (0, react_1.useState)([]);
563
565
  const selectionAnchor = (0, react_1.useRef)(null);
@@ -41,6 +41,7 @@ const client_id_1 = require("../../helpers/client-id");
41
41
  const colors_1 = require("../../helpers/colors");
42
42
  const format_file_location_1 = require("../../helpers/format-file-location");
43
43
  const get_timeline_sequence_layout_1 = require("../../helpers/get-timeline-sequence-layout");
44
+ const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
44
45
  const open_in_editor_1 = require("../../helpers/open-in-editor");
45
46
  const timeline_layout_1 = require("../../helpers/timeline-layout");
46
47
  const use_max_media_duration_1 = require("../../helpers/use-max-media-duration");
@@ -177,11 +178,15 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
177
178
  ? remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)
178
179
  : undefined;
179
180
  }, [propStatuses, nodePath]);
180
- const durationCanUpdate = Boolean(((_a = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.durationInFrames) === null || _a === void 0 ? void 0 : _a.status) === 'static');
181
- const fromCanUpdate = Boolean(((_b = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.from) === null || _b === void 0 ? void 0 : _b.status) === 'static');
182
- const trimBeforeCanUpdate = Boolean(((_c = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.trimBefore) === null || _c === void 0 ? void 0 : _c.status) === 'static');
181
+ const durationCanUpdate = Boolean(interactivity_enabled_1.studioInteractivityEnabled &&
182
+ ((_a = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.durationInFrames) === null || _a === void 0 ? void 0 : _a.status) === 'static');
183
+ const fromCanUpdate = Boolean(interactivity_enabled_1.studioInteractivityEnabled &&
184
+ ((_b = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.from) === null || _b === void 0 ? void 0 : _b.status) === 'static');
185
+ const trimBeforeCanUpdate = Boolean(interactivity_enabled_1.studioInteractivityEnabled &&
186
+ ((_c = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.trimBefore) === null || _c === void 0 ? void 0 : _c.status) === 'static');
183
187
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
184
188
  const previewConnected = previewServerState.type === 'connected';
189
+ const previewInteractive = previewConnected && interactivity_enabled_1.studioInteractivityEnabled;
185
190
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
186
191
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
187
192
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
@@ -201,9 +206,9 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
201
206
  });
202
207
  }, [canOpenInEditor, originalLocation]);
203
208
  const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
204
- const deleteDisabled = !previewConnected || !s.controls || !canDeleteFromSource;
209
+ const deleteDisabled = !previewInteractive || !s.controls || !canDeleteFromSource;
205
210
  const duplicateDisabled = deleteDisabled;
206
- const disableInteractivityDisabled = !previewConnected ||
211
+ const disableInteractivityDisabled = !previewInteractive ||
207
212
  !s.showInTimeline ||
208
213
  !nodePath ||
209
214
  !(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source);
@@ -280,7 +285,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
280
285
  validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source,
281
286
  ]);
282
287
  const freezeFrameMenuItem = (0, use_sequence_freeze_frame_menu_item_1.useSequenceFreezeFrameMenuItem)({
283
- clientId: previewServerState.type === 'connected'
288
+ clientId: previewInteractive && previewServerState.type === 'connected'
284
289
  ? previewServerState.clientId
285
290
  : null,
286
291
  nodePath,
@@ -302,7 +307,7 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
302
307
  disableInteractivityDisabled,
303
308
  duplicateDisabled,
304
309
  fileLocation,
305
- includeSourceEditItems: true,
310
+ includeSourceEditItems: interactivity_enabled_1.studioInteractivityEnabled,
306
311
  onDeleteSequenceFromSource,
307
312
  onDisableSequenceInteractivity,
308
313
  onDuplicateSequenceFromSource,
@@ -310,7 +315,9 @@ const TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffs
310
315
  originalLocation,
311
316
  selectAsset,
312
317
  sequence: s,
313
- sourceActions: freezeFrameMenuItem ? [freezeFrameMenuItem] : [],
318
+ sourceActions: interactivity_enabled_1.studioInteractivityEnabled && freezeFrameMenuItem
319
+ ? [freezeFrameMenuItem]
320
+ : [],
314
321
  });
315
322
  }, [
316
323
  assetLinkInfo,