@remotion/studio 4.0.465 → 4.0.466

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.
Files changed (48) hide show
  1. package/dist/components/CompositionSelectorItem.js +16 -79
  2. package/dist/components/EditorContent.js +1 -3
  3. package/dist/components/Menu/MenuItem.d.ts +1 -1
  4. package/dist/components/Modals.js +1 -1
  5. package/dist/components/NewComposition/MenuContent.js +1 -0
  6. package/dist/components/RenderButton.js +1 -0
  7. package/dist/components/RenderModal/RenderModalAdvanced.d.ts +1 -11
  8. package/dist/components/RenderModal/RenderModalAdvanced.js +4 -50
  9. package/dist/components/RenderModal/RenderModalEncoding.d.ts +37 -0
  10. package/dist/components/RenderModal/RenderModalEncoding.js +165 -0
  11. package/dist/components/RenderModal/RenderModalPicture.d.ts +1 -22
  12. package/dist/components/RenderModal/RenderModalPicture.js +6 -84
  13. package/dist/components/RenderModal/ServerRenderModal.d.ts +1 -0
  14. package/dist/components/RenderModal/ServerRenderModal.js +16 -4
  15. package/dist/components/RenderQueue/actions.d.ts +2 -1
  16. package/dist/components/RenderQueue/actions.js +2 -1
  17. package/dist/components/SidebarRenderButton.js +1 -0
  18. package/dist/components/Timeline/Timeline.js +6 -4
  19. package/dist/components/Timeline/TimelineEffectFieldRow.js +2 -1
  20. package/dist/components/Timeline/TimelineEffectGroupRow.d.ts +1 -0
  21. package/dist/components/Timeline/TimelineEffectGroupRow.js +18 -2
  22. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -1
  23. package/dist/components/Timeline/TimelineExpandedRow.js +1 -1
  24. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.d.ts +7 -0
  25. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.js +123 -0
  26. package/dist/components/Timeline/TimelineSchemaField.js +2 -1
  27. package/dist/components/Timeline/TimelineStack/index.js +7 -47
  28. package/dist/components/Timeline/TimelineTracks.js +2 -16
  29. package/dist/components/Timeline/get-timeline-keyframes.d.ts +6 -0
  30. package/dist/components/Timeline/get-timeline-keyframes.js +22 -0
  31. package/dist/components/composition-menu-items.d.ts +12 -0
  32. package/dist/components/composition-menu-items.js +166 -0
  33. package/dist/esm/{chunk-pqk2qd0d.js → chunk-sa3dm85y.js} +3694 -3257
  34. package/dist/esm/internals.mjs +3694 -3257
  35. package/dist/esm/previewEntry.mjs +3443 -3006
  36. package/dist/esm/renderEntry.mjs +1 -1
  37. package/dist/helpers/make-render-command.d.ts +2 -2
  38. package/dist/helpers/make-render-command.js +2 -1
  39. package/dist/helpers/open-in-editor.d.ts +8 -0
  40. package/dist/helpers/open-in-editor.js +58 -1
  41. package/dist/helpers/render-modal-sections.d.ts +1 -1
  42. package/dist/helpers/render-modal-sections.js +35 -5
  43. package/dist/helpers/retry-payload.js +3 -0
  44. package/dist/helpers/timeline-layout.d.ts +1 -0
  45. package/dist/helpers/timeline-layout.js +6 -1
  46. package/dist/helpers/use-menu-structure.js +43 -0
  47. package/dist/state/modals.d.ts +1 -0
  48. package/package.json +10 -10
@@ -2,98 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RenderModalPicture = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const client_1 = require("@remotion/renderer/client");
6
- const react_1 = require("react");
7
- const Checkmark_1 = require("../../icons/Checkmark");
8
- const Checkbox_1 = require("../Checkbox");
9
- const layout_1 = require("../layout");
10
5
  const is_menu_item_1 = require("../Menu/is-menu-item");
11
- const ComboBox_1 = require("../NewComposition/ComboBox");
12
- const RemInput_1 = require("../NewComposition/RemInput");
13
6
  const SegmentedControl_1 = require("../SegmentedControl");
14
- const CrfSetting_1 = require("./CrfSetting");
15
7
  const JpegQualitySetting_1 = require("./JpegQualitySetting");
16
- const layout_2 = require("./layout");
17
- const OptionExplainerBubble_1 = require("./OptionExplainerBubble");
8
+ const layout_1 = require("./layout");
18
9
  const RenderModalHr_1 = require("./RenderModalHr");
19
10
  const ScaleSetting_1 = require("./ScaleSetting");
20
- const qualityControlModes = ['crf', 'bitrate'];
21
11
  const container = {
22
12
  flex: 1,
23
13
  overflowY: 'auto',
24
14
  };
25
- const RenderModalPicture = ({ renderMode, scale, setScale, pixelFormat, imageFormatOptions, setQualityControl, qualityControlType, videoImageFormat, setJpegQuality, jpegQuality, maxCrf, minCrf, setCrf, shouldDisplayQualityControlPicker, setCustomTargetVideoBitrateValue, crf, customTargetVideoBitrate, stillImageFormat, colorSpace, setColorSpace, pixelFormatOptions, encodingBufferSize, encodingMaxRate, setEncodingBufferSize, setEncodingMaxRate, compositionWidth, compositionHeight, }) => {
26
- const colorSpaceOptions = (0, react_1.useMemo)(() => {
27
- return client_1.BrowserSafeApis.validColorSpaces.map((option) => {
28
- return {
29
- label: option,
30
- onClick: () => setColorSpace(option),
31
- key: option,
32
- id: option,
33
- keyHint: null,
34
- leftItem: colorSpace === option ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
35
- quickSwitcherLabel: null,
36
- subMenu: null,
37
- type: 'item',
38
- value: option,
39
- };
40
- });
41
- }, [colorSpace, setColorSpace]);
42
- const qualityControlOptions = (0, react_1.useMemo)(() => {
43
- return qualityControlModes.map((option) => {
44
- return {
45
- label: option === 'crf' ? 'CRF' : 'Bitrate',
46
- onClick: () => setQualityControl(option),
47
- key: option,
48
- selected: qualityControlType === option,
49
- };
50
- });
51
- }, [qualityControlType, setQualityControl]);
52
- const onTargetVideoBitrateChanged = (0, react_1.useCallback)((e) => {
53
- setCustomTargetVideoBitrateValue(e.target.value);
54
- }, [setCustomTargetVideoBitrateValue]);
55
- const onEncodingBufferSizeToggled = (0, react_1.useCallback)((e) => {
56
- setEncodingBufferSize(e.target.checked ? '10000k' : null);
57
- }, [setEncodingBufferSize]);
58
- const onEncodingMaxRateToggled = (0, react_1.useCallback)((e) => {
59
- setEncodingMaxRate(e.target.checked ? '5000k' : null);
60
- }, [setEncodingMaxRate]);
61
- const onEncodingBufferSizeChanged = (0, react_1.useCallback)((e) => {
62
- setEncodingBufferSize(e.target.value);
63
- }, [setEncodingBufferSize]);
64
- const onEncodingMaxRateChanged = (0, react_1.useCallback)((e) => {
65
- setEncodingMaxRate(e.target.value);
66
- }, [setEncodingMaxRate]);
67
- return (jsx_runtime_1.jsxs("div", { style: container, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: [renderMode === 'video' ? (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
68
- jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Image Format" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(SegmentedControl_1.SegmentedControl, { items: imageFormatOptions, needsWrapping: false }) })
69
- ] })) : null, renderMode === 'video' && videoImageFormat === 'jpeg' && (jsx_runtime_1.jsx(JpegQualitySetting_1.JpegQualitySetting, { jpegQuality: jpegQuality, setJpegQuality: setJpegQuality })), renderMode === 'still' && stillImageFormat === 'jpeg' && (jsx_runtime_1.jsx(JpegQualitySetting_1.JpegQualitySetting, { jpegQuality: jpegQuality, setJpegQuality: setJpegQuality })), renderMode === 'video' && qualityControlType !== null ? (jsx_runtime_1.jsx(RenderModalHr_1.RenderModalHr, {})) : null, shouldDisplayQualityControlPicker && renderMode === 'video' ? (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
70
- jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Quality control" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(SegmentedControl_1.SegmentedControl, { items: qualityControlOptions, needsWrapping: true }) })
71
- ] })) : null, qualityControlType === 'crf' &&
72
- renderMode !== 'still' &&
73
- renderMode !== 'sequence' &&
74
- crf !== null ? (jsx_runtime_1.jsx(CrfSetting_1.CrfSetting, { crf: crf, min: minCrf, max: maxCrf, setCrf: setCrf, option: "crfOption" })) : null, qualityControlType === 'bitrate' && renderMode === 'video' ? (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
75
- jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Target video bitrate",
76
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.OptionExplainerBubble, { id: "videoBitrateOption" })
77
- ] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx("div", { children: jsx_runtime_1.jsx(RemInput_1.RemotionInput, { style: layout_2.input, value: customTargetVideoBitrate, onChange: onTargetVideoBitrateChanged, status: "ok", rightAlign: true }) }) })
78
- ] })) : null, renderMode === 'video' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
79
- jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
80
- jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Custom FFmpeg -bufsize",
81
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.OptionExplainerBubble, { id: "encodingBufferSizeOption" })
82
- ] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: encodingBufferSize !== null, onChange: onEncodingBufferSizeToggled, name: "encoding-buffer-size" }) })
83
- ] }), encodingBufferSize === null ? null : (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
84
- jsx_runtime_1.jsx("div", { style: layout_2.label, children: "-bufsize value" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx("div", { children: jsx_runtime_1.jsx(RemInput_1.RemotionInput, { style: layout_2.input, value: encodingBufferSize, onChange: onEncodingBufferSizeChanged, status: "ok", rightAlign: true }) }) })
85
- ] })), jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
86
- jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Custom FFmpeg -maxrate",
87
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.OptionExplainerBubble, { id: "encodingMaxRateOption" })
88
- ] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: encodingMaxRate !== null, onChange: onEncodingMaxRateToggled, name: "encoding-max-rate" }) })
89
- ] }), encodingMaxRate === null ? null : (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
90
- jsx_runtime_1.jsx("div", { style: layout_2.label, children: "-maxrate value" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx("div", { children: jsx_runtime_1.jsx(RemInput_1.RemotionInput, { style: layout_2.input, value: encodingMaxRate, onChange: onEncodingMaxRateChanged, status: "ok", rightAlign: true }) }) })
91
- ] }))] })) : null, renderMode === 'video' ? jsx_runtime_1.jsx(RenderModalHr_1.RenderModalHr, {}) : null, jsx_runtime_1.jsx(ScaleSetting_1.ScaleSetting, { scale: scale, setScale: setScale, compositionWidth: compositionWidth, compositionHeight: compositionHeight }), renderMode === 'video' ? jsx_runtime_1.jsx(RenderModalHr_1.RenderModalHr, {}) : null, renderMode === 'video' ? (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
92
- jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Pixel format" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: pixelFormatOptions, selectedId: pixelFormat, title: "Pixel Format" }) })
93
- ] })) : null, renderMode === 'video' ? (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
94
- jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Color space",
95
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.OptionExplainerBubble, { id: "colorSpaceOption" })
96
- ] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: colorSpaceOptions, selectedId: colorSpace, title: "Color Space" }) })
97
- ] })) : null] }));
15
+ const RenderModalPicture = ({ renderMode, scale, setScale, imageFormatOptions, videoImageFormat, setJpegQuality, jpegQuality, stillImageFormat, compositionWidth, compositionHeight, }) => {
16
+ return (jsx_runtime_1.jsxs("div", { style: container, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: [renderMode === 'video' ? (jsx_runtime_1.jsxs("div", { style: layout_1.optionRow, children: [
17
+ jsx_runtime_1.jsx("div", { style: layout_1.label, children: "Image Format" }), jsx_runtime_1.jsx("div", { style: layout_1.rightRow, children: jsx_runtime_1.jsx(SegmentedControl_1.SegmentedControl, { items: imageFormatOptions, needsWrapping: false }) })
18
+ ] })) : null, renderMode === 'video' && videoImageFormat === 'jpeg' ? (jsx_runtime_1.jsx(JpegQualitySetting_1.JpegQualitySetting, { jpegQuality: jpegQuality, setJpegQuality: setJpegQuality })) : null, renderMode === 'still' && stillImageFormat === 'jpeg' ? (jsx_runtime_1.jsx(JpegQualitySetting_1.JpegQualitySetting, { jpegQuality: jpegQuality, setJpegQuality: setJpegQuality })) : null, renderMode === 'video' ? jsx_runtime_1.jsx(RenderModalHr_1.RenderModalHr, {}) : null, jsx_runtime_1.jsx(ScaleSetting_1.ScaleSetting, { scale: scale, setScale: setScale, compositionWidth: compositionWidth, compositionHeight: compositionHeight })
19
+ ] }));
98
20
  };
99
21
  exports.RenderModalPicture = RenderModalPicture;
@@ -20,6 +20,7 @@ type RenderModalProps = {
20
20
  readonly initialEnforceAudioTrack: boolean;
21
21
  readonly initialProResProfile: _InternalTypes['ProResProfile'] | null;
22
22
  readonly initialx264Preset: X264Preset;
23
+ readonly initialGopSize: number | null;
23
24
  readonly initialPixelFormat: PixelFormat | null;
24
25
  readonly initialVideoBitrate: string | null;
25
26
  readonly initialAudioBitrate: string | null;
@@ -19,6 +19,7 @@ const file_1 = require("../../icons/file");
19
19
  const frame_1 = require("../../icons/frame");
20
20
  const gear_1 = require("../../icons/gear");
21
21
  const gif_1 = require("../../icons/gif");
22
+ const video_1 = require("../../icons/video");
22
23
  const modals_1 = require("../../state/modals");
23
24
  const sidebar_1 = require("../../state/sidebar");
24
25
  const Button_1 = require("../Button");
@@ -39,6 +40,8 @@ const render_modals_1 = require("./render-modals");
39
40
  const RenderModalAdvanced_1 = require("./RenderModalAdvanced");
40
41
  const RenderModalAudio_1 = require("./RenderModalAudio");
41
42
  const RenderModalBasic_1 = require("./RenderModalBasic");
43
+ const RenderModalEncoding_1 = require("./RenderModalEncoding");
44
+ const RenderModalEnvironmentVariables_1 = require("./RenderModalEnvironmentVariables");
42
45
  const RenderModalGif_1 = require("./RenderModalGif");
43
46
  const RenderModalPicture_1 = require("./RenderModalPicture");
44
47
  const ResolveCompositionBeforeModal_1 = require("./ResolveCompositionBeforeModal");
@@ -61,7 +64,7 @@ const reducer = (state, action) => {
61
64
  }
62
65
  return state;
63
66
  };
64
- const RenderModal = ({ readOnlyStudio, 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, initialDarkMode, initialUserAgent, defaultProps, inFrameMark, outFrameMark, initialColorSpace, initialMultiProcessOnLinux, defaultConfigurationAudioCodec, defaultConfigurationVideoCodec, initialBeep, initialRepro, initialForSeamlessAacConcatenation, renderTypeOfLastRender, initialHardwareAcceleration, initialSampleRate, defaultMetadata, initialChromeMode, renderDefaults, }) => {
67
+ const RenderModal = ({ readOnlyStudio, initialFrame, initialVideoImageFormat, initialStillImageFormat, initialJpegQuality, initialScale, initialLogLevel, initialConcurrency, maxConcurrency, minConcurrency, initialMuted, initialEnforceAudioTrack, initialProResProfile, initialx264Preset, initialGopSize, initialPixelFormat, initialVideoBitrate, initialAudioBitrate, initialEveryNthFrame, initialNumberOfGifLoops, initialDelayRenderTimeout, initialOffthreadVideoCacheSizeInBytes, initialEnvVariables, initialDisableWebSecurity, initialGl, initialHeadless, initialIgnoreCertificateErrors, initialEncodingBufferSize, initialEncodingMaxRate, initialOffthreadVideoThreads, initialMediaCacheSizeInBytes, initialDarkMode, initialUserAgent, defaultProps, inFrameMark, outFrameMark, initialColorSpace, initialMultiProcessOnLinux, defaultConfigurationAudioCodec, defaultConfigurationVideoCodec, initialBeep, initialRepro, initialForSeamlessAacConcatenation, renderTypeOfLastRender, initialHardwareAcceleration, initialSampleRate, defaultMetadata, initialChromeMode, renderDefaults, }) => {
65
68
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
66
69
  const context = (0, react_1.useContext)(ResolveCompositionBeforeModal_1.ResolvedCompositionContext);
67
70
  if (!context) {
@@ -159,6 +162,7 @@ const RenderModal = ({ readOnlyStudio, initialFrame, initialVideoImageFormat, in
159
162
  return (_a = initialProResProfile !== null && initialProResProfile !== void 0 ? initialProResProfile : resolvedComposition.defaultProResProfile) !== null && _a !== void 0 ? _a : 'hq';
160
163
  });
161
164
  const [x264PresetSetting, setx264Preset] = (0, react_1.useState)(() => initialx264Preset);
165
+ const [gopSize, setGopSize] = (0, react_1.useState)(() => initialGopSize);
162
166
  const [hardwareAcceleration, setHardwareAcceleration] = (0, react_1.useState)(() => initialHardwareAcceleration);
163
167
  const [userPreferredPixelFormat, setPixelFormat] = (0, react_1.useState)(() => {
164
168
  var _a;
@@ -450,6 +454,7 @@ const RenderModal = ({ readOnlyStudio, initialFrame, initialVideoImageFormat, in
450
454
  hardwareAcceleration !== 'required'
451
455
  ? crf
452
456
  : null,
457
+ gopSize,
453
458
  endFrame,
454
459
  startFrame,
455
460
  muted,
@@ -529,6 +534,7 @@ const RenderModal = ({ readOnlyStudio, initialFrame, initialVideoImageFormat, in
529
534
  beepOnFinish,
530
535
  repro,
531
536
  forSeamlessAacConcatenation,
537
+ gopSize,
532
538
  separateAudioTo,
533
539
  setSelectedModal,
534
540
  metadata,
@@ -798,6 +804,7 @@ const RenderModal = ({ readOnlyStudio, initialFrame, initialVideoImageFormat, in
798
804
  hardwareAcceleration !== 'required'
799
805
  ? crf
800
806
  : null,
807
+ gopSize,
801
808
  videoBitrate,
802
809
  audioBitrate,
803
810
  audioCodec,
@@ -852,6 +859,7 @@ const RenderModal = ({ readOnlyStudio, initialFrame, initialVideoImageFormat, in
852
859
  everyNthFrame,
853
860
  frame,
854
861
  forSeamlessAacConcatenation,
862
+ gopSize,
855
863
  hardwareAcceleration,
856
864
  headless,
857
865
  ignoreCertificateErrors,
@@ -990,13 +998,17 @@ const RenderModal = ({ readOnlyStudio, initialFrame, initialVideoImageFormat, in
990
998
  jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(audio_1.AudioIcon, { style: render_modals_1.icon }) }),
991
999
  "Audio"] })) : null, shownTabs.includes('gif') ? (jsx_runtime_1.jsxs(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'gif', onClick: () => setTab('gif'), children: [
992
1000
  jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(gif_1.GifIcon, { style: render_modals_1.icon }) }),
993
- "GIF"] })) : null, shownTabs.includes('advanced') ? (jsx_runtime_1.jsxs(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'advanced', onClick: () => setTab('advanced'), children: [
1001
+ "GIF"] })) : null, shownTabs.includes('encoding') ? (jsx_runtime_1.jsxs(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'encoding', onClick: () => setTab('encoding'), children: [
1002
+ jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(video_1.FilmIcon, { style: render_modals_1.icon, color: "currentcolor" }) }),
1003
+ "Encoding"] })) : null, shownTabs.includes('environment') ? (jsx_runtime_1.jsxs(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'environment', onClick: () => setTab('environment'), children: [
1004
+ jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(data_1.DataIcon, { style: render_modals_1.icon }) }),
1005
+ "Environment"] })) : null, shownTabs.includes('advanced') ? (jsx_runtime_1.jsxs(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'advanced', onClick: () => setTab('advanced'), children: [
994
1006
  jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(gear_1.GearIcon, { style: render_modals_1.icon }) }),
995
- "Other"] })) : null] }), jsx_runtime_1.jsx("div", { style: render_modals_1.optionsPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: tab === 'general' ? (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, showOutputName: !readOnlyStudio, startFrame: startFrame, validationMessage: outnameValidation.valid ? null : outnameValidation.error.message })) : tab === 'picture' ? (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' ? (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, sampleRate: sampleRate, setSampleRate: setSampleRate })) : tab === 'gif' ? (jsx_runtime_1.jsx(RenderModalGif_1.RenderModalGif, { everyNthFrame: everyNthFrame, limitNumberOfGifLoops: limitNumberOfGifLoops, numberOfGifLoopsSetting: numberOfGifLoopsSetting, setEveryNthFrameSetting: setEveryNthFrameSetting, setLimitNumberOfGifLoops: setLimitNumberOfGifLoops, setNumberOfGifLoopsSetting: setNumberOfGifLoopsSetting })) : tab === 'data' ? (jsx_runtime_1.jsx(DataEditor_1.DataEditor, { defaultProps: inputProps, setDefaultProps: setInputProps, unresolvedComposition: unresolvedComposition, propsEditType: "input-props", canSaveDefaultProps: {
1007
+ "Other"] })) : null] }), jsx_runtime_1.jsx("div", { style: render_modals_1.optionsPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: tab === 'general' ? (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, showOutputName: !readOnlyStudio, startFrame: startFrame, validationMessage: outnameValidation.valid ? null : outnameValidation.error.message })) : tab === 'picture' ? (jsx_runtime_1.jsx(RenderModalPicture_1.RenderModalPicture, { renderMode: renderMode, scale: scale, setScale: setScale, imageFormatOptions: imageFormatOptions, jpegQuality: jpegQuality, setJpegQuality: setJpegQuality, videoImageFormat: videoImageFormat, stillImageFormat: stillImageFormat, compositionWidth: resolvedComposition.width, compositionHeight: resolvedComposition.height })) : tab === 'audio' ? (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, sampleRate: sampleRate, setSampleRate: setSampleRate })) : tab === 'gif' ? (jsx_runtime_1.jsx(RenderModalGif_1.RenderModalGif, { everyNthFrame: everyNthFrame, limitNumberOfGifLoops: limitNumberOfGifLoops, numberOfGifLoopsSetting: numberOfGifLoopsSetting, setEveryNthFrameSetting: setEveryNthFrameSetting, setLimitNumberOfGifLoops: setLimitNumberOfGifLoops, setNumberOfGifLoopsSetting: setNumberOfGifLoopsSetting })) : tab === 'encoding' ? (jsx_runtime_1.jsx(RenderModalEncoding_1.RenderModalEncoding, { renderMode: renderMode, codec: codec, qualityControlType: qualityControlType, setQualityControl: setQualityControl, shouldDisplayQualityControlPicker: supportsBothQualityControls, crf: crf, setCrf: setCrf, maxCrf: maxCrf, minCrf: minCrf, customTargetVideoBitrate: customTargetVideoBitrate, setCustomTargetVideoBitrateValue: setCustomTargetVideoBitrateValue, encodingBufferSize: encodingBufferSize, setEncodingBufferSize: setEncodingBufferSize, encodingMaxRate: encodingMaxRate, setEncodingMaxRate: setEncodingMaxRate, pixelFormat: pixelFormat, pixelFormatOptions: pixelFormatOptions, colorSpace: colorSpace, setColorSpace: setColorSpace, x264Preset: x264Preset, setx264Preset: setx264Preset, gopSize: gopSize, setGopSize: setGopSize, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration, disallowParallelEncoding: disallowParallelEncoding, setDisallowParallelEncoding: setDisallowParallelEncoding })) : tab === 'environment' ? (jsx_runtime_1.jsx(RenderModalEnvironmentVariables_1.RenderModalEnvironmentVariables, { envVariables: envVariables, setEnvVariables: setEnvVariables })) : tab === 'data' ? (jsx_runtime_1.jsx(DataEditor_1.DataEditor, { defaultProps: inputProps, setDefaultProps: setInputProps, unresolvedComposition: unresolvedComposition, propsEditType: "input-props", canSaveDefaultProps: {
996
1008
  canUpdate: false,
997
1009
  reason: 'render dialogue',
998
1010
  determined: false,
999
- } })) : (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, darkMode: darkMode, setDarkMode: setDarkMode })) })
1011
+ } })) : (jsx_runtime_1.jsx(RenderModalAdvanced_1.RenderModalAdvanced, { concurrency: concurrency, maxConcurrency: maxConcurrency, minConcurrency: minConcurrency, renderMode: renderMode, setConcurrency: setConcurrency, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, setDisableWebSecurity: setDisableWebSecurity, setIgnoreCertificateErrors: setIgnoreCertificateErrors, setHeadless: setHeadless, headless: headless, ignoreCertificateErrors: ignoreCertificateErrors, disableWebSecurity: disableWebSecurity, openGlOption: openGlOption, setOpenGlOption: setOpenGlOption, offthreadVideoCacheSizeInBytes: offthreadVideoCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setOffthreadVideoCacheSizeInBytes: setOffthreadVideoCacheSizeInBytes, offthreadVideoThreads: offthreadVideoThreads, setOffthreadVideoThreads: setOffthreadVideoThreads, enableMultiProcessOnLinux: multiProcessOnLinux, setChromiumMultiProcessOnLinux: setChromiumMultiProcessOnLinux, userAgent: userAgent, setUserAgent: setUserAgent, setBeep: setBeepOnFinish, beep: beepOnFinish, repro: repro, setRepro: setRepro, chromeModeOption: chromeMode, setChromeModeOption: setChromeMode, darkMode: darkMode, setDarkMode: setDarkMode })) })
1000
1012
  ] })
1001
1013
  ] }));
1002
1014
  };
@@ -43,7 +43,7 @@ export declare const addSequenceRenderJob: ({ compositionId, outName, imageForma
43
43
  chromeMode: "chrome-for-testing" | "headless-shell";
44
44
  mediaCacheSizeInBytes: number | null;
45
45
  }) => Promise<undefined>;
46
- export declare const addVideoRenderJob: ({ compositionId, outName, imageFormat, jpegQuality, scale, logLevel, codec, concurrency, crf, startFrame, endFrame, muted, enforceAudioTrack, proResProfile, x264Preset, pixelFormat, audioBitrate, videoBitrate, everyNthFrame, numberOfGifLoops, delayRenderTimeout, audioCodec, disallowParallelEncoding, chromiumOptions, envVariables, inputProps, offthreadVideoCacheSizeInBytes, offthreadVideoThreads, colorSpace, multiProcessOnLinux, encodingMaxRate, encodingBufferSize, beepOnFinish, repro, forSeamlessAacConcatenation, separateAudioTo, metadata, hardwareAcceleration, chromeMode, mediaCacheSizeInBytes, sampleRate, }: {
46
+ export declare const addVideoRenderJob: ({ compositionId, outName, imageFormat, jpegQuality, scale, logLevel, codec, concurrency, crf, gopSize, startFrame, endFrame, muted, enforceAudioTrack, proResProfile, x264Preset, pixelFormat, audioBitrate, videoBitrate, everyNthFrame, numberOfGifLoops, delayRenderTimeout, audioCodec, disallowParallelEncoding, chromiumOptions, envVariables, inputProps, offthreadVideoCacheSizeInBytes, offthreadVideoThreads, colorSpace, multiProcessOnLinux, encodingMaxRate, encodingBufferSize, beepOnFinish, repro, forSeamlessAacConcatenation, separateAudioTo, metadata, hardwareAcceleration, chromeMode, mediaCacheSizeInBytes, sampleRate, }: {
47
47
  compositionId: string;
48
48
  outName: string;
49
49
  imageFormat: "jpeg" | "none" | "png";
@@ -53,6 +53,7 @@ export declare const addVideoRenderJob: ({ compositionId, outName, imageFormat,
53
53
  codec: "aac" | "av1" | "gif" | "h264" | "h264-mkv" | "h264-ts" | "h265" | "mp3" | "prores" | "vp8" | "vp9" | "wav";
54
54
  concurrency: number;
55
55
  crf: number | null;
56
+ gopSize: number | null;
56
57
  startFrame: number;
57
58
  endFrame: number;
58
59
  muted: boolean;
@@ -63,7 +63,7 @@ const addSequenceRenderJob = ({ compositionId, outName, imageFormat, startFrame,
63
63
  });
64
64
  };
65
65
  exports.addSequenceRenderJob = addSequenceRenderJob;
66
- const addVideoRenderJob = ({ compositionId, outName, imageFormat, jpegQuality, scale, logLevel, codec, concurrency, crf, startFrame, endFrame, muted, enforceAudioTrack, proResProfile, x264Preset, pixelFormat, audioBitrate, videoBitrate, everyNthFrame, numberOfGifLoops, delayRenderTimeout, audioCodec, disallowParallelEncoding, chromiumOptions, envVariables, inputProps, offthreadVideoCacheSizeInBytes, offthreadVideoThreads, colorSpace, multiProcessOnLinux, encodingMaxRate, encodingBufferSize, beepOnFinish, repro, forSeamlessAacConcatenation, separateAudioTo, metadata, hardwareAcceleration, chromeMode, mediaCacheSizeInBytes, sampleRate, }) => {
66
+ const addVideoRenderJob = ({ compositionId, outName, imageFormat, jpegQuality, scale, logLevel, codec, concurrency, crf, gopSize, startFrame, endFrame, muted, enforceAudioTrack, proResProfile, x264Preset, pixelFormat, audioBitrate, videoBitrate, everyNthFrame, numberOfGifLoops, delayRenderTimeout, audioCodec, disallowParallelEncoding, chromiumOptions, envVariables, inputProps, offthreadVideoCacheSizeInBytes, offthreadVideoThreads, colorSpace, multiProcessOnLinux, encodingMaxRate, encodingBufferSize, beepOnFinish, repro, forSeamlessAacConcatenation, separateAudioTo, metadata, hardwareAcceleration, chromeMode, mediaCacheSizeInBytes, sampleRate, }) => {
67
67
  return (0, call_api_1.callApi)('/api/render', {
68
68
  compositionId,
69
69
  type: 'video',
@@ -75,6 +75,7 @@ const addVideoRenderJob = ({ compositionId, outName, imageFormat, jpegQuality, s
75
75
  codec,
76
76
  concurrency,
77
77
  crf,
78
+ gopSize,
78
79
  endFrame,
79
80
  startFrame,
80
81
  muted,
@@ -47,6 +47,7 @@ const SidebarRenderButton = ({ composition, visible }) => {
47
47
  initialEnforceAudioTrack: defaults.enforceAudioTrack,
48
48
  initialProResProfile: defaults.proResProfile,
49
49
  initialx264Preset: defaults.x264Preset,
50
+ initialGopSize: defaults.gopSize,
50
51
  initialPixelFormat: null,
51
52
  initialAudioBitrate: defaults.audioBitrate,
52
53
  initialVideoBitrate: defaults.videoBitrate,
@@ -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 is_current_selected_still_1 = require("../../helpers/is-current-selected-still");
43
44
  const is_menu_item_1 = require("../Menu/is-menu-item");
44
45
  const SplitterContainer_1 = require("../Splitter/SplitterContainer");
45
46
  const SplitterElement_1 = require("../Splitter/SplitterElement");
@@ -73,6 +74,7 @@ const TimelineInner = () => {
73
74
  var _a;
74
75
  const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
75
76
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
77
+ const isStill = (0, is_current_selected_still_1.useIsStill)();
76
78
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
77
79
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
78
80
  const previewConnected = previewServerState.type === 'connected';
@@ -101,13 +103,13 @@ const TimelineInner = () => {
101
103
  return null;
102
104
  }
103
105
  return (jsx_runtime_1.jsx(SubscribeToNodePaths_1.SubscribeToNodePaths, { overrideId: sequence.controls.overrideId, schema: sequence.controls.schema, getStack: sequence.getStack, effects: sequence.effects }, sequence.id));
104
- }), jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}), jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
105
- jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, children: jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, children: [
106
+ }), jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}), 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: [
107
+ 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: [
106
108
  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: [
107
109
  jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
108
110
  ] }) })
109
- ] }) })
110
- ] })
111
+ ] })
112
+ ] })) })
111
113
  ] }));
112
114
  };
113
115
  exports.Timeline = react_1.default.memo(TimelineInner);
@@ -8,6 +8,7 @@ const remotion_1 = require("remotion");
8
8
  const client_id_1 = require("../../helpers/client-id");
9
9
  const timeline_layout_1 = require("../../helpers/timeline-layout");
10
10
  const call_api_1 = require("../call-api");
11
+ const get_timeline_keyframes_1 = require("./get-timeline-keyframes");
11
12
  const save_prop_queue_1 = require("./save-prop-queue");
12
13
  const timeline_field_row_layout_1 = require("./timeline-field-row-layout");
13
14
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
@@ -130,7 +131,7 @@ const Value = ({ field, nodePath, validatedLocation }) => {
130
131
  }
131
132
  if (propStatus === null || !propStatus.canUpdate) {
132
133
  if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.reason) === 'computed') {
133
- return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "computed" });
134
+ return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: (0, get_timeline_keyframes_1.getComputedStatusLabel)(propStatus) });
134
135
  }
135
136
  return null;
136
137
  }
@@ -8,6 +8,7 @@ export declare const TimelineEffectGroupRow: React.FC<{
8
8
  readonly nodePathInfo: SequenceNodePathInfo;
9
9
  readonly effectIndex: number;
10
10
  readonly effectSchema: SequenceSchema;
11
+ readonly documentationLink: string | null;
11
12
  readonly nodePath: SequencePropsSubscriptionKey;
12
13
  readonly validatedLocation: CodePosition;
13
14
  readonly rowDepth: number;
@@ -18,9 +18,10 @@ const rowLabel = {
18
18
  color: 'rgba(255, 255, 255, 0.8)',
19
19
  userSelect: 'none',
20
20
  };
21
- const TimelineEffectGroupRow = ({ label, nodePathInfo, effectIndex, effectSchema, nodePath, validatedLocation, rowDepth, getIsExpanded, toggleTrack, }) => {
21
+ const TimelineEffectGroupRow = ({ label, nodePathInfo, effectIndex, effectSchema, documentationLink, nodePath, validatedLocation, rowDepth, getIsExpanded, toggleTrack, }) => {
22
22
  var _a;
23
23
  var _b;
24
+ const [labelHovered, setLabelHovered] = (0, react_1.useState)(false);
24
25
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
25
26
  const previewConnected = previewServerState.type === 'connected';
26
27
  const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
@@ -122,7 +123,22 @@ const TimelineEffectGroupRow = ({ label, nodePathInfo, effectIndex, effectSchema
122
123
  height: timeline_layout_1.TREE_GROUP_ROW_HEIGHT,
123
124
  paddingRight: timeline_layout_1.EXPANDED_SECTION_PADDING_RIGHT,
124
125
  }), []);
125
- const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: canToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: "effect", hidden: isDisabled, onInvoked: onToggle })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(nodePathInfo), label: `${label} section`, disabled: false }), style: rowStyle, children: jsx_runtime_1.jsx("span", { style: rowLabel, children: label }) }));
126
+ const labelStyle = (0, react_1.useMemo)(() => {
127
+ const hoverEffect = labelHovered && documentationLink !== null;
128
+ return {
129
+ ...rowLabel,
130
+ textDecoration: hoverEffect ? 'underline' : 'none',
131
+ textUnderlineOffset: 2,
132
+ cursor: hoverEffect ? 'pointer' : undefined,
133
+ };
134
+ }, [documentationLink, labelHovered]);
135
+ const onClickLabel = (0, react_1.useCallback)(() => {
136
+ if (documentationLink === null) {
137
+ return;
138
+ }
139
+ window.open(documentationLink, '_blank', 'noopener,noreferrer');
140
+ }, [documentationLink]);
141
+ const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: canToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: "effect", hidden: isDisabled, onInvoked: onToggle })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(nodePathInfo), label: `${label} section`, disabled: false }), style: rowStyle, children: jsx_runtime_1.jsx("span", { onPointerEnter: () => setLabelHovered(true), onPointerLeave: () => setLabelHovered(false), onClick: onClickLabel, title: documentationLink ? `Open documentation: ${documentationLink}` : label, style: labelStyle, children: label }) }));
126
142
  return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, children: row })) : (row);
127
143
  };
128
144
  exports.TimelineEffectGroupRow = TimelineEffectGroupRow;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { SequenceSchema, SequencePropsSubscriptionKey } from 'remotion';
2
+ import type { SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
3
3
  import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
4
4
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
5
5
  import type { TimelineTreeNode } from '../../helpers/timeline-layout';
@@ -19,7 +19,7 @@ const TimelineExpandedRow = ({ node, depth, nestedDepth, getIsExpanded, toggleTr
19
19
  const rowDepth = (0, timeline_row_layout_1.getExpandedRowDepth)({ nestedDepth, treeDepth: depth });
20
20
  if (node.kind === 'group') {
21
21
  if (node.effectInfo) {
22
- return (jsx_runtime_1.jsx(TimelineEffectGroupRow_1.TimelineEffectGroupRow, { label: node.label, nodePathInfo: node.nodePathInfo, effectIndex: node.effectInfo.effectIndex, effectSchema: node.effectInfo.effectSchema, nodePath: nodePath, validatedLocation: validatedLocation, rowDepth: rowDepth, getIsExpanded: getIsExpanded, toggleTrack: toggleTrack }));
22
+ return (jsx_runtime_1.jsx(TimelineEffectGroupRow_1.TimelineEffectGroupRow, { label: node.label, nodePathInfo: node.nodePathInfo, effectIndex: node.effectInfo.effectIndex, effectSchema: node.effectInfo.effectSchema, documentationLink: node.effectInfo.documentationLink, nodePath: nodePath, validatedLocation: validatedLocation, rowDepth: rowDepth, getIsExpanded: getIsExpanded, toggleTrack: toggleTrack }));
23
23
  }
24
24
  const isExpanded = getIsExpanded(node.nodePathInfo);
25
25
  return (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {}), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(node.nodePathInfo), label: `${node.label} section`, disabled: false }), style: {
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { type TSequence } from 'remotion';
3
+ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
4
+ export declare const TimelineExpandedTrackKeyframes: React.NamedExoticComponent<{
5
+ readonly sequence: TSequence;
6
+ readonly nodePathInfo: SequenceNodePathInfo;
7
+ }>;
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TimelineExpandedTrackKeyframes = void 0;
37
+ const jsx_runtime_1 = require("react/jsx-runtime");
38
+ const react_1 = __importStar(require("react"));
39
+ const remotion_1 = require("remotion");
40
+ const colors_1 = require("../../helpers/colors");
41
+ const get_left_of_timeline_slider_1 = require("../../helpers/get-left-of-timeline-slider");
42
+ const timeline_layout_1 = require("../../helpers/timeline-layout");
43
+ const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
44
+ const get_timeline_keyframes_1 = require("./get-timeline-keyframes");
45
+ const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
46
+ const row = {
47
+ position: 'relative',
48
+ };
49
+ const separator = {
50
+ height: 1,
51
+ backgroundColor: colors_1.TIMELINE_TRACK_SEPARATOR,
52
+ };
53
+ const section = {
54
+ borderBottom: `1px solid ${colors_1.TIMELINE_TRACK_SEPARATOR}`,
55
+ };
56
+ const diamondBase = {
57
+ position: 'absolute',
58
+ width: 8,
59
+ height: 8,
60
+ backgroundColor: colors_1.LIGHT_TEXT,
61
+ borderRadius: 1,
62
+ boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.4)',
63
+ pointerEvents: 'none',
64
+ };
65
+ const getNodeKeyframes = ({ node, nodePath, codeValues, }) => {
66
+ var _a, _b;
67
+ if (node.kind !== 'field' || node.field === null) {
68
+ return [];
69
+ }
70
+ if (node.field.kind === 'sequence-field') {
71
+ return (0, get_timeline_keyframes_1.getTimelineKeyframes)((_a = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _a === void 0 ? void 0 : _a[node.field.key]);
72
+ }
73
+ const effectStatus = remotion_1.Internals.getEffectCodeValuesCtx({
74
+ codeValues,
75
+ nodePath,
76
+ effectIndex: node.field.effectIndex,
77
+ });
78
+ return (0, get_timeline_keyframes_1.getTimelineKeyframes)(effectStatus.type === 'can-update-effect'
79
+ ? (_b = effectStatus.props) === null || _b === void 0 ? void 0 : _b[node.field.key]
80
+ : null);
81
+ };
82
+ const TimelineExpandedTrackKeyframesInner = ({ nodePathInfo, sequence }) => {
83
+ const videoConfig = (0, remotion_1.useVideoConfig)();
84
+ const timelineWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
85
+ const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
86
+ const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
87
+ const tree = (0, react_1.useMemo)(() => (0, timeline_layout_1.buildTimelineTree)({
88
+ sequence,
89
+ nodePathInfo,
90
+ getDragOverrides: () => ({}),
91
+ codeValues,
92
+ }), [codeValues, nodePathInfo, sequence]);
93
+ const flat = (0, react_1.useMemo)(() => (0, timeline_layout_1.flattenVisibleTreeNodes)({ nodes: tree, getIsExpanded }), [tree, getIsExpanded]);
94
+ const expandedHeight = (0, react_1.useMemo)(() => (0, timeline_layout_1.getExpandedTrackHeight)({
95
+ sequence,
96
+ nodePathInfo,
97
+ getIsExpanded,
98
+ codeValues,
99
+ }), [codeValues, getIsExpanded, nodePathInfo, sequence]);
100
+ const rows = (0, react_1.useMemo)(() => flat.map(({ node }) => ({
101
+ height: (0, timeline_layout_1.getTreeRowHeight)(node),
102
+ keyframes: getNodeKeyframes({
103
+ node,
104
+ nodePath: nodePathInfo.sequenceSubscriptionKey,
105
+ codeValues,
106
+ }),
107
+ key: JSON.stringify(node.nodePathInfo),
108
+ })), [codeValues, flat, nodePathInfo.sequenceSubscriptionKey]);
109
+ return (jsx_runtime_1.jsx("div", { style: {
110
+ height: expandedHeight + timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM,
111
+ }, children: jsx_runtime_1.jsx("div", { style: { ...section, height: expandedHeight }, children: rows.map(({ height, keyframes, key }, i) => {
112
+ return (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [i > 0 ? jsx_runtime_1.jsx("div", { style: separator }) : null, jsx_runtime_1.jsx("div", { style: { ...row, height }, children: timelineWidth === null
113
+ ? null
114
+ : keyframes.map((keyframe) => (jsx_runtime_1.jsx("div", { style: {
115
+ ...diamondBase,
116
+ left: (0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(keyframe.frame, videoConfig.durationInFrames, timelineWidth) - timeline_layout_1.TIMELINE_PADDING,
117
+ top: height / 2,
118
+ transform: 'translate(-50%, -50%) rotate(45deg)',
119
+ }, title: `Keyframe at frame ${keyframe.frame}` }, String(keyframe.frame)))) })
120
+ ] }, key));
121
+ }) }) }));
122
+ };
123
+ exports.TimelineExpandedTrackKeyframes = react_1.default.memo(TimelineExpandedTrackKeyframesInner);
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TimelineFieldValue = exports.TimelineNonEditableStatus = exports.UnsupportedStatus = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const get_timeline_keyframes_1 = require("./get-timeline-keyframes");
5
6
  const TimelineBooleanField_1 = require("./TimelineBooleanField");
6
7
  const TimelineColorField_1 = require("./TimelineColorField");
7
8
  const TimelineEnumField_1 = require("./TimelineEnumField");
@@ -30,7 +31,7 @@ const TimelineNonEditableStatus = ({ propStatus }) => {
30
31
  return null;
31
32
  }
32
33
  if (propStatus.reason === 'computed') {
33
- return jsx_runtime_1.jsx("span", { style: unsupportedLabel, children: "computed" });
34
+ return (jsx_runtime_1.jsx("span", { style: unsupportedLabel, children: (0, get_timeline_keyframes_1.getComputedStatusLabel)(propStatus) }));
34
35
  }
35
36
  throw new Error(`Unsupported prop status: ${propStatus.reason}`);
36
37
  };