@remotion/studio 4.0.458 → 4.0.460

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 (66) hide show
  1. package/dist/audio-waveform-worker.js +4 -4
  2. package/dist/components/AudioWaveform.js +4 -4
  3. package/dist/components/Checkbox.d.ts +7 -0
  4. package/dist/components/Checkbox.js +38 -24
  5. package/dist/components/Editor.js +10 -9
  6. package/dist/components/ExpandedTracksProvider.d.ts +9 -4
  7. package/dist/components/ExpandedTracksProvider.js +45 -15
  8. package/dist/components/MenuBuildIndicator.js +0 -1
  9. package/dist/components/NewComposition/ComboBox.d.ts +1 -0
  10. package/dist/components/NewComposition/ComboBox.js +14 -5
  11. package/dist/components/SequencePropsSubscriptionProvider.d.ts +3 -0
  12. package/dist/components/SequencePropsSubscriptionProvider.js +26 -0
  13. package/dist/components/Timeline/SequencePropsObserver.d.ts +1 -0
  14. package/dist/components/Timeline/SequencePropsObserver.js +24 -0
  15. package/dist/components/Timeline/SubscribeToNodePaths.d.ts +7 -0
  16. package/dist/components/Timeline/SubscribeToNodePaths.js +15 -0
  17. package/dist/components/Timeline/Timeline.js +28 -48
  18. package/dist/components/Timeline/TimelineBooleanField.js +1 -1
  19. package/dist/components/Timeline/TimelineEnumField.js +18 -10
  20. package/dist/components/Timeline/TimelineExpandArrowButton.d.ts +1 -0
  21. package/dist/components/Timeline/TimelineExpandArrowButton.js +5 -3
  22. package/dist/components/Timeline/TimelineExpandedRow.d.ts +6 -6
  23. package/dist/components/Timeline/TimelineExpandedRow.js +4 -5
  24. package/dist/components/Timeline/TimelineExpandedSection.d.ts +2 -2
  25. package/dist/components/Timeline/TimelineExpandedSection.js +20 -9
  26. package/dist/components/Timeline/TimelineFieldRow.d.ts +2 -3
  27. package/dist/components/Timeline/TimelineFieldRow.js +23 -20
  28. package/dist/components/Timeline/TimelineHeightContainer.d.ts +7 -0
  29. package/dist/components/Timeline/TimelineHeightContainer.js +18 -0
  30. package/dist/components/Timeline/TimelineList.js +1 -1
  31. package/dist/components/Timeline/TimelineListItem.d.ts +2 -0
  32. package/dist/components/Timeline/TimelineListItem.js +27 -13
  33. package/dist/components/Timeline/TimelineSchemaField.js +4 -1
  34. package/dist/components/Timeline/TimelineTracks.js +18 -7
  35. package/dist/components/Timeline/TimelineVideoInfo.js +25 -140
  36. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +10 -13
  37. package/dist/components/Timeline/sequence-props-subscription-store.js +56 -123
  38. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +6 -6
  39. package/dist/components/Timeline/use-sequence-props-subscription.js +25 -55
  40. package/dist/components/Timeline/use-timeline-height.d.ts +5 -0
  41. package/dist/components/Timeline/use-timeline-height.js +48 -0
  42. package/dist/components/draw-peaks.js +7 -0
  43. package/dist/esm/audio-waveform-worker.mjs +9 -14
  44. package/dist/esm/{chunk-261b3aa0.js → chunk-nrgs0ad5.js} +2810 -2975
  45. package/dist/esm/internals.mjs +2810 -2975
  46. package/dist/esm/previewEntry.mjs +2809 -2974
  47. package/dist/esm/renderEntry.mjs +1 -1
  48. package/dist/helpers/calculate-timeline.d.ts +3 -2
  49. package/dist/helpers/calculate-timeline.js +21 -2
  50. package/dist/helpers/get-timeline-sequence-layout.js +3 -3
  51. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +6 -1
  52. package/dist/helpers/timeline-layout.d.ts +18 -9
  53. package/dist/helpers/timeline-layout.js +24 -16
  54. package/dist/icons/Checkmark.d.ts +4 -1
  55. package/dist/icons/Checkmark.js +1 -5
  56. package/dist/icons/caret.d.ts +3 -1
  57. package/dist/icons/caret.js +5 -2
  58. package/package.json +10 -9
  59. package/dist/components/looped-media-timeline.d.ts +0 -6
  60. package/dist/components/looped-media-timeline.js +0 -14
  61. package/dist/helpers/extract-frames.d.ts +0 -18
  62. package/dist/helpers/extract-frames.js +0 -87
  63. package/dist/helpers/frame-database.d.ts +0 -16
  64. package/dist/helpers/frame-database.js +0 -65
  65. package/dist/helpers/resize-video-frame.d.ts +0 -4
  66. package/dist/helpers/resize-video-frame.js +0 -39
@@ -209,7 +209,7 @@ var renderContent = (Root) => {
209
209
  renderToDOM(/* @__PURE__ */ jsx("div", {
210
210
  children: /* @__PURE__ */ jsx(DelayedSpinner, {})
211
211
  }));
212
- import("./chunk-261b3aa0.js").then(({ StudioInternals }) => {
212
+ import("./chunk-nrgs0ad5.js").then(({ StudioInternals }) => {
213
213
  window.remotion_isStudio = true;
214
214
  window.remotion_isReadOnlyStudio = true;
215
215
  window.remotion_inputProps = "{}";
@@ -1,5 +1,6 @@
1
- import type { TSequence } from 'remotion';
1
+ import type { OverrideIdToNodePaths, TSequence } from 'remotion';
2
2
  import type { TrackWithHash } from './get-timeline-sequence-sort-key';
3
- export declare const calculateTimeline: ({ sequences, }: {
3
+ export declare const calculateTimeline: ({ sequences, overrideIdsToNodePaths, }: {
4
4
  sequences: TSequence[];
5
+ overrideIdsToNodePaths: OverrideIdToNodePaths;
5
6
  }) => TrackWithHash[];
@@ -19,7 +19,9 @@ const getInheritedLoopDisplay = (sequence, sequences) => {
19
19
  }
20
20
  return getInheritedLoopDisplay(parent, sequences);
21
21
  };
22
- const calculateTimeline = ({ sequences, }) => {
22
+ const calculateTimeline = ({ sequences, overrideIdsToNodePaths, }) => {
23
+ var _a;
24
+ var _b;
23
25
  const sortedSequences = (0, sort_by_nonce_history_1.sortItemsByNonceHistory)(sequences);
24
26
  const tracks = [];
25
27
  if (sortedSequences.length === 0) {
@@ -41,6 +43,8 @@ const calculateTimeline = ({ sequences, }) => {
41
43
  const cascadedStart = (0, get_sequence_visible_range_1.getCascadedStart)(sequence, sortedSequences);
42
44
  const visibleStart = (0, get_sequence_visible_range_1.getTimelineVisibleStart)(sequence, sortedSequences);
43
45
  const visibleDuration = (0, get_sequence_visible_range_1.getTimelineVisibleDuration)(sequence, sortedSequences);
46
+ const overrideId = (_b = (_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.overrideId) !== null && _b !== void 0 ? _b : null;
47
+ const nodePath = overrideId ? overrideIdsToNodePaths[overrideId] : null;
44
48
  tracks.push({
45
49
  sequence: {
46
50
  ...sequence,
@@ -54,6 +58,7 @@ const calculateTimeline = ({ sequences, }) => {
54
58
  hash: actualHash,
55
59
  cascadedStart,
56
60
  cascadedDuration: sequence.duration,
61
+ nodePathInfo: nodePath ? { nodePath, index: 0 } : null,
57
62
  });
58
63
  }
59
64
  const uniqueTracks = [];
@@ -67,10 +72,24 @@ const calculateTimeline = ({ sequences, }) => {
67
72
  for (let i = 0; i < tracks.length; i++) {
68
73
  nonceRanks.set(tracks[i].sequence.id, i);
69
74
  }
70
- return uniqueTracks.sort((a, b) => {
75
+ const sortedTracks = uniqueTracks.sort((a, b) => {
71
76
  const sortKeyA = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(a, tracks, sameHashes, nonceRanks);
72
77
  const sortKeyB = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(b, tracks, sameHashes, nonceRanks);
73
78
  return sortKeyA.localeCompare(sortKeyB);
74
79
  });
80
+ const nodePathIndexCounters = new Map();
81
+ return sortedTracks.map((track) => {
82
+ var _a;
83
+ if (track.nodePathInfo === null) {
84
+ return track;
85
+ }
86
+ const key = JSON.stringify(track.nodePathInfo.nodePath);
87
+ const index = (_a = nodePathIndexCounters.get(key)) !== null && _a !== void 0 ? _a : 0;
88
+ nodePathIndexCounters.set(key, index + 1);
89
+ return {
90
+ ...track,
91
+ nodePathInfo: { nodePath: track.nodePathInfo.nodePath, index },
92
+ };
93
+ });
75
94
  };
76
95
  exports.calculateTimeline = calculateTimeline;
@@ -8,15 +8,15 @@ const getWidthOfTrack = ({ durationInFrames, lastFrame, windowWidth, spatialDura
8
8
  const base = durationInFrames === Infinity || lastFrame === 0
9
9
  ? fullWidth
10
10
  : (spatialDuration / lastFrame) * fullWidth;
11
- return base - exports.SEQUENCE_BORDER_WIDTH + nonNegativeMarginLeft;
11
+ return Math.max(0, base - exports.SEQUENCE_BORDER_WIDTH + nonNegativeMarginLeft);
12
12
  };
13
13
  const getTimelineSequenceLayout = ({ durationInFrames, startFrom, maxMediaDuration, startFromMedia, video, windowWidth, premountDisplay, postmountDisplay, }) => {
14
14
  var _a;
15
15
  const maxMediaSequenceDuration = (maxMediaDuration !== null && maxMediaDuration !== void 0 ? maxMediaDuration : Infinity) - startFromMedia;
16
16
  const lastFrame = ((_a = video.durationInFrames) !== null && _a !== void 0 ? _a : 1) - 1;
17
- const spatialDuration = Math.min(maxMediaSequenceDuration, durationInFrames - 1, lastFrame - startFrom);
17
+ const spatialDuration = Math.max(0, Math.min(maxMediaSequenceDuration, durationInFrames - 1, lastFrame - startFrom));
18
18
  // Unclipped spatial duration: without the lastFrame - startFrom constraint
19
- const naturalSpatialDuration = Math.min(maxMediaSequenceDuration, durationInFrames - 1);
19
+ const naturalSpatialDuration = Math.max(0, Math.min(maxMediaSequenceDuration, durationInFrames - 1));
20
20
  const marginLeft = lastFrame === 0
21
21
  ? 0
22
22
  : (startFrom / lastFrame) * (windowWidth - timeline_layout_1.TIMELINE_PADDING * 2);
@@ -1,7 +1,12 @@
1
- import type { TSequence } from 'remotion';
1
+ import type { SequenceNodePath, TSequence } from 'remotion';
2
+ export type SequenceNodePathInfo = {
3
+ nodePath: SequenceNodePath;
4
+ index: number;
5
+ };
2
6
  type Track = {
3
7
  sequence: TSequence;
4
8
  depth: number;
9
+ nodePathInfo: SequenceNodePathInfo | null;
5
10
  };
6
11
  export type TrackWithHash = Track & {
7
12
  hash: string;
@@ -1,5 +1,7 @@
1
1
  import { type CodeValues, type DragOverrides, type SchemaFieldInfo, type SequenceControls } from '@remotion/studio-shared';
2
- import type { EffectDefinitionAndStack, TSequence } from 'remotion';
2
+ import type { EffectDefinitionAndStack, GetCodeValues, GetDragOverrides, TSequence } from 'remotion';
3
+ import type { GetIsExpanded } from '../components/ExpandedTracksProvider';
4
+ import type { SequenceNodePathInfo } from './get-timeline-sequence-sort-key';
3
5
  export type { CodeValues, DragOverrides, SchemaFieldInfo, SequenceControls };
4
6
  export { SCHEMA_FIELD_ROW_HEIGHT, UNSUPPORTED_FIELD_ROW_HEIGHT, getFieldsToShow, } from '@remotion/studio-shared';
5
7
  export declare const TIMELINE_PADDING = 16;
@@ -16,31 +18,38 @@ export type EffectSchemaFieldLabel = {
16
18
  export declare const getEffectSchemaLabels: (effect: EffectDefinitionAndStack<unknown>) => EffectSchemaFieldLabel[];
17
19
  export type TimelineTreeNode = {
18
20
  readonly kind: 'group';
19
- readonly id: string;
21
+ readonly nodePathInfo: SequenceNodePathInfo;
20
22
  readonly label: string;
21
23
  readonly children: TimelineTreeNode[];
22
24
  } | {
23
25
  readonly kind: 'field';
24
- readonly id: string;
26
+ readonly nodePathInfo: SequenceNodePathInfo;
25
27
  readonly label: string;
26
28
  readonly field: SchemaFieldInfo | null;
27
29
  };
28
- export declare const buildTimelineTree: ({ sequence, dragOverrides, codeValues, }: {
30
+ export declare const buildTimelineTree: ({ sequence, nodePathInfo, getDragOverrides, getCodeValues, }: {
29
31
  sequence: TSequence;
30
- dragOverrides: DragOverrides;
31
- codeValues: CodeValues;
32
+ nodePathInfo: SequenceNodePathInfo;
33
+ getDragOverrides: GetDragOverrides;
34
+ getCodeValues: GetCodeValues;
32
35
  }) => TimelineTreeNode[];
33
36
  export type FlatTreeRow = {
34
37
  readonly node: TimelineTreeNode;
35
38
  readonly depth: number;
36
39
  };
37
- export declare const flattenVisibleTreeNodes: ({ nodes, expandedTracks, depth, }: {
40
+ export declare const flattenVisibleTreeNodes: ({ nodes, getIsExpanded, depth, }: {
38
41
  nodes: TimelineTreeNode[];
39
- expandedTracks: Record<string, boolean>;
42
+ getIsExpanded: GetIsExpanded;
40
43
  depth?: number | undefined;
41
44
  }) => FlatTreeRow[];
42
45
  export declare const getTreeRowHeight: (node: TimelineTreeNode) => number;
43
- export declare const getExpandedTrackHeight: (sequence: TSequence, expandedTracks: Record<string, boolean>, dragOverrides: DragOverrides, codeValues: CodeValues) => number;
46
+ export declare const getExpandedTrackHeight: ({ sequence, nodePathInfo, getIsExpanded, getDragOverrides, getCodeValues, }: {
47
+ sequence: TSequence;
48
+ nodePathInfo: SequenceNodePathInfo;
49
+ getIsExpanded: GetIsExpanded;
50
+ getDragOverrides: GetDragOverrides;
51
+ getCodeValues: GetCodeValues;
52
+ }) => number;
44
53
  export declare const TIMELINE_LAYER_HEIGHT_VIDEO = 75;
45
54
  export declare const TIMELINE_LAYER_HEIGHT_IMAGE = 50;
46
55
  export declare const TIMELINE_LAYER_HEIGHT_AUDIO = 25;
@@ -23,25 +23,29 @@ const getEffectSchemaLabels = (effect) => {
23
23
  }));
24
24
  };
25
25
  exports.getEffectSchemaLabels = getEffectSchemaLabels;
26
- const buildTimelineTree = ({ sequence, dragOverrides, codeValues, }) => {
26
+ const buildTimelineTree = ({ sequence, nodePathInfo, getDragOverrides, getCodeValues, }) => {
27
27
  var _a;
28
28
  const roots = [];
29
+ const { nodePath, index } = nodePathInfo;
29
30
  if (sequence.effects.length > 0) {
30
31
  roots.push({
31
32
  kind: 'group',
32
- id: `${sequence.id}::effects`,
33
+ nodePathInfo: { nodePath: [...nodePath, 'effects'], index },
33
34
  label: 'Effects',
34
35
  children: sequence.effects.map((effect, i) => {
35
- const effectId = `${sequence.id}::effects::${i}`;
36
+ const effectNodePath = [...nodePath, 'effects', i];
36
37
  return {
37
38
  kind: 'group',
38
- id: effectId,
39
+ nodePathInfo: { nodePath: effectNodePath, index },
39
40
  label: effect.definition.label,
40
41
  children: (0, exports.getEffectSchemaLabels)(effect).map((label) => {
41
42
  var _a;
42
43
  return ({
43
44
  kind: 'field',
44
- id: `${effectId}::${label.key}`,
45
+ nodePathInfo: {
46
+ nodePath: [...effectNodePath, label.key],
47
+ index,
48
+ },
45
49
  label: (_a = label.description) !== null && _a !== void 0 ? _a : label.key,
46
50
  field: null,
47
51
  });
@@ -53,15 +57,15 @@ const buildTimelineTree = ({ sequence, dragOverrides, codeValues, }) => {
53
57
  const controlFields = (0, studio_shared_1.getFieldsToShow)({
54
58
  schema: sequence.controls.schema,
55
59
  currentRuntimeValueDotNotation: sequence.controls.currentRuntimeValueDotNotation,
56
- dragOverrides,
57
- codeValues,
58
- overrideId: sequence.controls.overrideId,
60
+ getDragOverrides,
61
+ getCodeValues,
62
+ nodePath,
59
63
  });
60
64
  if (controlFields && controlFields.length > 0) {
61
65
  for (const f of controlFields) {
62
66
  roots.push({
63
67
  kind: 'field',
64
- id: `${sequence.id}::controls::${f.key}`,
68
+ nodePathInfo: { nodePath: [...nodePath, 'controls', f.key], index },
65
69
  label: (_a = f.description) !== null && _a !== void 0 ? _a : f.key,
66
70
  field: f,
67
71
  });
@@ -70,15 +74,14 @@ const buildTimelineTree = ({ sequence, dragOverrides, codeValues, }) => {
70
74
  return roots;
71
75
  };
72
76
  exports.buildTimelineTree = buildTimelineTree;
73
- const flattenVisibleTreeNodes = ({ nodes, expandedTracks, depth = 0, }) => {
74
- var _a;
77
+ const flattenVisibleTreeNodes = ({ nodes, getIsExpanded, depth = 0, }) => {
75
78
  const out = [];
76
79
  for (const node of nodes) {
77
80
  out.push({ node, depth });
78
- if (node.kind === 'group' && ((_a = expandedTracks[node.id]) !== null && _a !== void 0 ? _a : false)) {
81
+ if (node.kind === 'group' && getIsExpanded(node.nodePathInfo)) {
79
82
  out.push(...(0, exports.flattenVisibleTreeNodes)({
80
83
  nodes: node.children,
81
- expandedTracks,
84
+ getIsExpanded,
82
85
  depth: depth + 1,
83
86
  }));
84
87
  }
@@ -93,9 +96,14 @@ const getTreeRowHeight = (node) => {
93
96
  return exports.TREE_GROUP_ROW_HEIGHT;
94
97
  };
95
98
  exports.getTreeRowHeight = getTreeRowHeight;
96
- const getExpandedTrackHeight = (sequence, expandedTracks, dragOverrides, codeValues) => {
97
- const tree = (0, exports.buildTimelineTree)({ sequence, dragOverrides, codeValues });
98
- const flat = (0, exports.flattenVisibleTreeNodes)({ nodes: tree, expandedTracks });
99
+ const getExpandedTrackHeight = ({ sequence, nodePathInfo, getIsExpanded, getDragOverrides, getCodeValues, }) => {
100
+ const tree = (0, exports.buildTimelineTree)({
101
+ sequence,
102
+ nodePathInfo,
103
+ getDragOverrides,
104
+ getCodeValues,
105
+ });
106
+ const flat = (0, exports.flattenVisibleTreeNodes)({ nodes: tree, getIsExpanded });
99
107
  if (flat.length === 0) {
100
108
  return exports.TIMELINE_TRACK_EXPANDED_HEIGHT;
101
109
  }
@@ -1 +1,4 @@
1
- export declare const Checkmark: () => import("react/jsx-runtime").JSX.Element;
1
+ import React from 'react';
2
+ export declare const Checkmark: React.FC<{
3
+ readonly size?: number;
4
+ }>;
@@ -2,9 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Checkmark = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const style = {
6
- width: 14,
7
- height: 14,
8
- };
9
- const Checkmark = () => (jsx_runtime_1.jsx("svg", { focusable: "false", role: "img", viewBox: "0 0 512 512", style: style, children: jsx_runtime_1.jsx("path", { fill: "currentColor", d: "M435.848 83.466L172.804 346.51l-96.652-96.652c-4.686-4.686-12.284-4.686-16.971 0l-28.284 28.284c-4.686 4.686-4.686 12.284 0 16.971l133.421 133.421c4.686 4.686 12.284 4.686 16.971 0l299.813-299.813c4.686-4.686 4.686-12.284 0-16.971l-28.284-28.284c-4.686-4.686-12.284-4.686-16.97 0z" }) }));
5
+ const Checkmark = ({ size = 14 }) => (jsx_runtime_1.jsx("svg", { focusable: "false", role: "img", viewBox: "0 0 512 512", style: { width: size, height: size }, children: jsx_runtime_1.jsx("path", { fill: "currentColor", d: "M435.848 83.466L172.804 346.51l-96.652-96.652c-4.686-4.686-12.284-4.686-16.971 0l-28.284 28.284c-4.686 4.686-4.686 12.284 0 16.971l133.421 133.421c4.686 4.686 12.284 4.686 16.971 0l299.813-299.813c4.686-4.686 4.686-12.284 0-16.971l-28.284-28.284c-4.686-4.686-12.284-4.686-16.97 0z" }) }));
10
6
  exports.Checkmark = Checkmark;
@@ -1,6 +1,8 @@
1
1
  import React from 'react';
2
2
  export declare const CaretRight: () => import("react/jsx-runtime").JSX.Element;
3
- export declare const CaretDown: () => import("react/jsx-runtime").JSX.Element;
3
+ export declare const CaretDown: React.FC<{
4
+ readonly small?: boolean;
5
+ }>;
4
6
  export declare const AngleDown: React.FC<{
5
7
  readonly down: boolean;
6
8
  }>;
@@ -10,13 +10,16 @@ const caret = {
10
10
  const caretDown = {
11
11
  width: 10,
12
12
  };
13
+ const caretDownSmall = {
14
+ width: 7,
15
+ };
13
16
  const angleDown = {
14
17
  width: 10,
15
18
  };
16
19
  const CaretRight = () => (jsx_runtime_1.jsx("svg", { viewBox: "0 0 192 512", style: caret, children: jsx_runtime_1.jsx("path", { fill: "currentColor", d: "M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z" }) }));
17
20
  exports.CaretRight = CaretRight;
18
- const CaretDown = () => {
19
- return (jsx_runtime_1.jsx("svg", { viewBox: "0 0 320 512", style: caretDown, children: jsx_runtime_1.jsx("path", { fill: "currentColor", d: "M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" }) }));
21
+ const CaretDown = ({ small = false, }) => {
22
+ return (jsx_runtime_1.jsx("svg", { viewBox: "0 0 320 512", style: small ? caretDownSmall : caretDown, children: jsx_runtime_1.jsx("path", { fill: "currentColor", d: "M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" }) }));
20
23
  };
21
24
  exports.CaretDown = CaretDown;
22
25
  const AngleDown = ({ down }) => {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio"
4
4
  },
5
5
  "name": "@remotion/studio",
6
- "version": "4.0.458",
6
+ "version": "4.0.460",
7
7
  "description": "APIs for interacting with the Remotion Studio",
8
8
  "main": "dist",
9
9
  "sideEffects": false,
@@ -26,13 +26,14 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "semver": "7.5.3",
29
- "remotion": "4.0.458",
30
- "@remotion/player": "4.0.458",
31
- "@remotion/media-utils": "4.0.458",
32
- "@remotion/renderer": "4.0.458",
33
- "@remotion/web-renderer": "4.0.458",
34
- "@remotion/studio-shared": "4.0.458",
35
- "@remotion/zod-types": "4.0.458",
29
+ "remotion": "4.0.460",
30
+ "@remotion/player": "4.0.460",
31
+ "@remotion/media-utils": "4.0.460",
32
+ "@remotion/renderer": "4.0.460",
33
+ "@remotion/web-renderer": "4.0.460",
34
+ "@remotion/studio-shared": "4.0.460",
35
+ "@remotion/timeline-utils": "4.0.460",
36
+ "@remotion/zod-types": "4.0.460",
36
37
  "mediabunny": "1.42.0",
37
38
  "memfs": "3.4.3",
38
39
  "source-map": "0.7.3",
@@ -43,7 +44,7 @@
43
44
  "react": "19.2.3",
44
45
  "react-dom": "19.2.3",
45
46
  "@types/semver": "^7.3.4",
46
- "@remotion/eslint-config-internal": "4.0.458",
47
+ "@remotion/eslint-config-internal": "4.0.460",
47
48
  "eslint": "9.19.0",
48
49
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
49
50
  },
@@ -1,6 +0,0 @@
1
- import type { LoopDisplay } from 'remotion';
2
- export declare const shouldTileLoopDisplay: (loopDisplay: LoopDisplay | undefined) => loopDisplay is LoopDisplay;
3
- export declare const getLoopDisplayWidth: ({ visualizationWidth, loopDisplay, }: {
4
- visualizationWidth: number;
5
- loopDisplay: LoopDisplay | undefined;
6
- }) => number;
@@ -1,14 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getLoopDisplayWidth = exports.shouldTileLoopDisplay = void 0;
4
- const shouldTileLoopDisplay = (loopDisplay) => {
5
- return loopDisplay !== undefined && loopDisplay.numberOfTimes > 1;
6
- };
7
- exports.shouldTileLoopDisplay = shouldTileLoopDisplay;
8
- const getLoopDisplayWidth = ({ visualizationWidth, loopDisplay, }) => {
9
- if (!(0, exports.shouldTileLoopDisplay)(loopDisplay)) {
10
- return visualizationWidth;
11
- }
12
- return visualizationWidth / loopDisplay.numberOfTimes;
13
- };
14
- exports.getLoopDisplayWidth = getLoopDisplayWidth;
@@ -1,18 +0,0 @@
1
- import type { VideoSample } from 'mediabunny';
2
- type Options = {
3
- track: {
4
- width: number;
5
- height: number;
6
- };
7
- container: string;
8
- durationInSeconds: number | null;
9
- };
10
- export type ExtractFramesTimestampsInSecondsFn = (options: Options) => Promise<number[]> | number[];
11
- export type ExtractFramesProps = {
12
- src: string;
13
- timestampsInSeconds: number[] | ExtractFramesTimestampsInSecondsFn;
14
- onVideoSample: (sample: VideoSample) => void;
15
- signal?: AbortSignal;
16
- };
17
- export declare function extractFrames({ src, timestampsInSeconds, onVideoSample, signal }: ExtractFramesProps): Promise<void>;
18
- export {};
@@ -1,87 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.extractFrames = extractFrames;
4
- const mediabunny_1 = require("mediabunny");
5
- const get_duration_or_compute_1 = require("./get-duration-or-compute");
6
- async function extractFrames({ src, timestampsInSeconds, onVideoSample, signal, }) {
7
- var _a;
8
- const input = new mediabunny_1.Input({
9
- formats: mediabunny_1.ALL_FORMATS,
10
- source: new mediabunny_1.UrlSource(src),
11
- });
12
- const dispose = () => {
13
- input.dispose();
14
- };
15
- if (signal) {
16
- signal.addEventListener('abort', dispose, { once: true });
17
- }
18
- try {
19
- const [durationInSeconds, format, videoTrack] = await Promise.all([
20
- (0, get_duration_or_compute_1.getDurationOrCompute)(input),
21
- input.getFormat(),
22
- input.getPrimaryVideoTrack(),
23
- ]);
24
- if (!videoTrack) {
25
- throw new Error('No video track found in the input');
26
- }
27
- if (await videoTrack.isLive()) {
28
- throw new Error('Live streams are not currently supported by Remotion. Sorry! Source: ' +
29
- src);
30
- }
31
- if (await videoTrack.isRelativeToUnixEpoch()) {
32
- throw new Error('Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: ' +
33
- src);
34
- }
35
- const timestamps = typeof timestampsInSeconds === 'function'
36
- ? await timestampsInSeconds({
37
- track: {
38
- width: await videoTrack.getDisplayWidth(),
39
- height: await videoTrack.getDisplayHeight(),
40
- },
41
- container: format.name,
42
- durationInSeconds,
43
- })
44
- : timestampsInSeconds;
45
- if (timestamps.length === 0) {
46
- return;
47
- }
48
- const sink = new mediabunny_1.VideoSampleSink(videoTrack);
49
- const sampleIterator = sink.samplesAtTimestamps(timestamps);
50
- try {
51
- for await (const videoSample of sampleIterator) {
52
- if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
53
- videoSample === null || videoSample === void 0 ? void 0 : videoSample.close();
54
- break;
55
- }
56
- if (!videoSample) {
57
- continue;
58
- }
59
- onVideoSample(videoSample);
60
- }
61
- }
62
- finally {
63
- // When input.dispose() causes the iterator to throw
64
- // InputDisposedError, for-await does not call .return() on the
65
- // iterator (it only does so on `break`). Explicitly call it so
66
- // the iterator can close any internally buffered VideoSamples.
67
- try {
68
- await ((_a = sampleIterator.return) === null || _a === void 0 ? void 0 : _a.call(sampleIterator));
69
- }
70
- catch (_b) {
71
- // Iterator already done or input disposed
72
- }
73
- }
74
- }
75
- catch (error) {
76
- if (error instanceof mediabunny_1.InputDisposedError) {
77
- return;
78
- }
79
- throw error;
80
- }
81
- finally {
82
- dispose();
83
- if (signal) {
84
- signal.removeEventListener('abort', dispose);
85
- }
86
- }
87
- }
@@ -1,16 +0,0 @@
1
- export type FrameDatabaseKey = string & {
2
- __brand: 'FrameDatabaseKey';
3
- };
4
- export declare const makeFrameDatabaseKey: (src: string, timestamp: number) => FrameDatabaseKey;
5
- export declare const getFrameDatabaseKeyPrefix: (src: string) => string;
6
- type VideoFrameAndLastUsed = {
7
- frame: VideoFrame;
8
- lastUsed: number;
9
- size: number;
10
- };
11
- export declare const frameDatabase: Map<FrameDatabaseKey, VideoFrameAndLastUsed>;
12
- export declare const aspectRatioCache: Map<string, number>;
13
- export declare const getTimestampFromFrameDatabaseKey: (key: FrameDatabaseKey) => number;
14
- export declare const getAspectRatioFromCache: (src: string) => number | null;
15
- export declare const addFrameToCache: (key: FrameDatabaseKey, frame: VideoFrame) => void;
16
- export {};
@@ -1,65 +0,0 @@
1
- "use strict";
2
- // Cache the thumbnails of the timeline
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.addFrameToCache = exports.getAspectRatioFromCache = exports.getTimestampFromFrameDatabaseKey = exports.aspectRatioCache = exports.frameDatabase = exports.getFrameDatabaseKeyPrefix = exports.makeFrameDatabaseKey = void 0;
5
- const KEY_SEPARATOR = '|';
6
- const makeFrameDatabaseKey = (src, timestamp) => `${src}${KEY_SEPARATOR}${timestamp}`;
7
- exports.makeFrameDatabaseKey = makeFrameDatabaseKey;
8
- const getFrameDatabaseKeyPrefix = (src) => {
9
- return `${src}${KEY_SEPARATOR}`;
10
- };
11
- exports.getFrameDatabaseKeyPrefix = getFrameDatabaseKeyPrefix;
12
- const MAX_CACHE_SIZE_BYTES = 10 * 1024 * 1024; // 10 MB
13
- let totalCacheSize = 0;
14
- exports.frameDatabase = new Map();
15
- exports.aspectRatioCache = new Map();
16
- const getTimestampFromFrameDatabaseKey = (key) => {
17
- const split = key.split(KEY_SEPARATOR);
18
- return Number(split[split.length - 1]);
19
- };
20
- exports.getTimestampFromFrameDatabaseKey = getTimestampFromFrameDatabaseKey;
21
- const getAspectRatioFromCache = (src) => {
22
- const cached = exports.aspectRatioCache.get(src);
23
- if (cached) {
24
- return cached;
25
- }
26
- return null;
27
- };
28
- exports.getAspectRatioFromCache = getAspectRatioFromCache;
29
- const evictLRU = () => {
30
- while (totalCacheSize > MAX_CACHE_SIZE_BYTES && exports.frameDatabase.size > 0) {
31
- let oldestKey;
32
- let oldestTime = Infinity;
33
- for (const [key, candidate] of exports.frameDatabase) {
34
- if (candidate.lastUsed < oldestTime) {
35
- oldestTime = candidate.lastUsed;
36
- oldestKey = key;
37
- }
38
- }
39
- if (!oldestKey) {
40
- break;
41
- }
42
- const entry = exports.frameDatabase.get(oldestKey);
43
- if (entry) {
44
- totalCacheSize -= entry.size;
45
- entry.frame.close();
46
- exports.frameDatabase.delete(oldestKey);
47
- }
48
- }
49
- };
50
- const addFrameToCache = (key, frame) => {
51
- const existing = exports.frameDatabase.get(key);
52
- if (existing) {
53
- totalCacheSize -= existing.size;
54
- existing.frame.close();
55
- }
56
- const size = frame.allocationSize();
57
- totalCacheSize += size;
58
- exports.frameDatabase.set(key, {
59
- frame,
60
- lastUsed: Date.now(),
61
- size,
62
- });
63
- evictLRU();
64
- };
65
- exports.addFrameToCache = addFrameToCache;
@@ -1,4 +0,0 @@
1
- export declare const resizeVideoFrame: ({ frame, scale, }: {
2
- frame: VideoFrame;
3
- scale: number;
4
- }) => VideoFrame;
@@ -1,39 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resizeVideoFrame = void 0;
4
- const calculateNewDimensionsFromScale = ({ width, height, scale, }) => {
5
- const scaledWidth = Math.round(width * scale);
6
- const scaledHeight = Math.round(height * scale);
7
- return {
8
- width: scaledWidth,
9
- height: scaledHeight,
10
- };
11
- };
12
- const resizeVideoFrame = ({ frame, scale, }) => {
13
- var _a;
14
- // No resize, no rotation
15
- if (scale === 1) {
16
- return frame;
17
- }
18
- const { width, height } = calculateNewDimensionsFromScale({
19
- height: frame.displayHeight,
20
- width: frame.displayWidth,
21
- scale,
22
- });
23
- const canvas = new OffscreenCanvas(width, height);
24
- const ctx = canvas.getContext('2d');
25
- if (!ctx) {
26
- throw new Error('Could not get 2d context');
27
- }
28
- canvas.width = width;
29
- canvas.height = height;
30
- ctx.scale(scale, scale);
31
- ctx.drawImage(frame, 0, 0);
32
- return new VideoFrame(canvas, {
33
- displayHeight: height,
34
- displayWidth: width,
35
- duration: (_a = frame.duration) !== null && _a !== void 0 ? _a : undefined,
36
- timestamp: frame.timestamp,
37
- });
38
- };
39
- exports.resizeVideoFrame = resizeVideoFrame;