remotion 4.0.519 → 4.0.521

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 (61) hide show
  1. package/THIRD_PARTY_LICENSES.md +28 -0
  2. package/dist/cjs/AbsoluteFill.d.ts +3 -15
  3. package/dist/cjs/Composition.js +5 -5
  4. package/dist/cjs/CompositionManager.d.ts +2 -3
  5. package/dist/cjs/CompositionManagerContext.d.ts +1 -2
  6. package/dist/cjs/CompositionManagerProvider.js +119 -5
  7. package/dist/cjs/Folder.d.ts +1 -2
  8. package/dist/cjs/Folder.js +6 -5
  9. package/dist/cjs/Img.d.ts +1 -0
  10. package/dist/cjs/Img.js +1 -0
  11. package/dist/cjs/Interactive.d.ts +3 -15
  12. package/dist/cjs/RemotionRoot.js +1 -8
  13. package/dist/cjs/Sequence.js +47 -60
  14. package/dist/cjs/SequenceManager.d.ts +1 -0
  15. package/dist/cjs/SequenceManager.js +85 -3
  16. package/dist/cjs/TimelineContext.d.ts +14 -8
  17. package/dist/cjs/TimelineContext.js +40 -23
  18. package/dist/cjs/animated-image/AnimatedImage.d.ts +1 -0
  19. package/dist/cjs/animated-image/AnimatedImage.js +1 -0
  20. package/dist/cjs/audio/AudioForPreview.js +6 -2
  21. package/dist/cjs/audio/shared-audio-tags.d.ts +1 -0
  22. package/dist/cjs/audio/shared-audio-tags.js +10 -1
  23. package/dist/cjs/audio/wait-until-actually-resumed.d.ts +1 -1
  24. package/dist/cjs/audio/wait-until-actually-resumed.js +16 -14
  25. package/dist/cjs/buffering.d.ts +3 -19
  26. package/dist/cjs/buffering.js +16 -77
  27. package/dist/cjs/canvas-image/CanvasImage.d.ts +1 -0
  28. package/dist/cjs/canvas-image/CanvasImage.js +1 -0
  29. package/dist/cjs/freeze.js +1 -4
  30. package/dist/cjs/index.d.ts +0 -1
  31. package/dist/cjs/interactivity-schema.d.ts +11 -16
  32. package/dist/cjs/interactivity-schema.js +3 -15
  33. package/dist/cjs/internals.d.ts +18 -45
  34. package/dist/cjs/internals.js +12 -4
  35. package/dist/cjs/runtime-value-store.d.ts +7 -7
  36. package/dist/cjs/runtime-value-store.js +1 -1
  37. package/dist/cjs/sequence-order-marker.d.ts +57 -0
  38. package/dist/cjs/sequence-order-marker.js +44 -0
  39. package/dist/cjs/timeline-position-state.d.ts +2 -8
  40. package/dist/cjs/timeline-position-state.js +5 -7
  41. package/dist/cjs/use-buffer-state.js +1 -3
  42. package/dist/cjs/use-buffering.d.ts +1 -0
  43. package/dist/cjs/use-buffering.js +11 -0
  44. package/dist/cjs/use-media-in-timeline.d.ts +0 -1
  45. package/dist/cjs/use-media-in-timeline.js +15 -29
  46. package/dist/cjs/use-media-playback.js +48 -56
  47. package/dist/cjs/use-media-tag.js +25 -3
  48. package/dist/cjs/use-playing.d.ts +1 -0
  49. package/dist/cjs/use-playing.js +14 -0
  50. package/dist/cjs/use-sequence-registration.d.ts +5 -0
  51. package/dist/cjs/use-sequence-registration.js +37 -0
  52. package/dist/cjs/use-sync-external-store.d.ts +28 -0
  53. package/dist/cjs/use-sync-external-store.js +116 -0
  54. package/dist/cjs/version.d.ts +1 -1
  55. package/dist/cjs/version.js +1 -1
  56. package/dist/cjs/video/VideoForPreview.js +5 -1
  57. package/dist/cjs/wrap-remotion-context.d.ts +1 -12
  58. package/dist/cjs/wrap-remotion-context.js +1 -8
  59. package/dist/esm/index.mjs +1145 -919
  60. package/dist/esm/version.mjs +1 -1
  61. package/package.json +3 -3
@@ -3,6 +3,7 @@ import type { TSequence } from './CompositionManager.js';
3
3
  import type { CanUpdateSequencePropStatus, DragOverrideValue, GetDragOverrides, GetEffectDragOverrides, PropStatuses } from './use-schema.js';
4
4
  export type SequenceManagerContext = {
5
5
  registerSequence: (seq: TSequence) => void;
6
+ updateSequence: ((seq: TSequence) => void) | null;
6
7
  unregisterSequence: (id: string) => void;
7
8
  sequences: TSequence[];
8
9
  };
@@ -36,10 +36,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.SequenceManagerProvider = exports.VisualModeSettersContext = exports.VisualModeDragOverridesContext = exports.VisualModePropStatusesRefContext = exports.VisualModePropStatusesContext = exports.makeSequencePropsSubscriptionKey = exports.SequenceRegistrationContext = exports.SequenceManagerRefContext = exports.SequenceManager = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
+ const sequence_order_marker_js_1 = require("./sequence-order-marker.js");
40
+ const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
41
+ const useIsomorphicLayoutEffect = typeof window === 'undefined' ? react_1.default.useEffect : react_1.default.useLayoutEffect;
39
42
  exports.SequenceManager = react_1.default.createContext({
40
43
  registerSequence: () => {
41
44
  throw new Error('SequenceManagerContext not initialized');
42
45
  },
46
+ updateSequence: null,
43
47
  unregisterSequence: () => {
44
48
  throw new Error('SequenceManagerContext not initialized');
45
49
  },
@@ -89,6 +93,10 @@ exports.VisualModeSettersContext = react_1.default.createContext({
89
93
  });
90
94
  const effectDragOverridesKey = (nodePath, effectIndex) => `${(0, exports.makeSequencePropsSubscriptionKey)(nodePath)}.effects.${effectIndex}`;
91
95
  const SequenceManagerProvider = ({ children }) => {
96
+ const { isStudio } = (0, use_remotion_environment_js_1.useRemotionEnvironment)();
97
+ const [sequenceManagerId] = (0, react_1.useState)(() => String(Math.random()));
98
+ const committedOrderRef = (0, react_1.useRef)(null);
99
+ const committedOrderIdsRef = (0, react_1.useRef)(null);
92
100
  const [sequences, setSequences] = (0, react_1.useState)([]);
93
101
  const sequencesRef = (0, react_1.useRef)(sequences);
94
102
  sequencesRef.current = sequences;
@@ -168,9 +176,81 @@ const SequenceManagerProvider = ({ children }) => {
168
176
  return next;
169
177
  });
170
178
  }, []);
179
+ useIsomorphicLayoutEffect(() => {
180
+ if (!isStudio) {
181
+ return;
182
+ }
183
+ let unmounted = false;
184
+ const onCommitOrder = (event) => {
185
+ const { detail } = event;
186
+ const managerOrder = detail.sequenceManagers.find((item) => item.managerId === sequenceManagerId);
187
+ if (!managerOrder) {
188
+ return;
189
+ }
190
+ const previousOrder = committedOrderIdsRef.current;
191
+ if (previousOrder !== null &&
192
+ previousOrder.length === managerOrder.sequenceIds.length &&
193
+ previousOrder.every((sequenceId, index) => sequenceId === managerOrder.sequenceIds[index])) {
194
+ return;
195
+ }
196
+ const order = new Map(managerOrder.sequenceIds.map((sequenceId, index) => [
197
+ sequenceId,
198
+ index,
199
+ ]));
200
+ committedOrderIdsRef.current = managerOrder.sequenceIds;
201
+ committedOrderRef.current = order;
202
+ queueMicrotask(() => {
203
+ if (unmounted) {
204
+ return;
205
+ }
206
+ setSequences((currentSequences) => {
207
+ let changed = false;
208
+ const nextSequences = currentSequences.map((sequence) => {
209
+ var _a;
210
+ const timelineOrder = (_a = order.get(sequence.id)) !== null && _a !== void 0 ? _a : null;
211
+ if (sequence.timelineOrder === timelineOrder) {
212
+ return sequence;
213
+ }
214
+ changed = true;
215
+ return { ...sequence, timelineOrder };
216
+ });
217
+ return changed ? nextSequences : currentSequences;
218
+ });
219
+ });
220
+ };
221
+ window.addEventListener(sequence_order_marker_js_1.COMMIT_ORDER_EVENT, onCommitOrder);
222
+ return () => {
223
+ unmounted = true;
224
+ window.removeEventListener(sequence_order_marker_js_1.COMMIT_ORDER_EVENT, onCommitOrder);
225
+ };
226
+ }, [isStudio, sequenceManagerId]);
171
227
  const registerSequence = (0, react_1.useCallback)((seq) => {
172
228
  setSequences((seqs) => {
173
- return [...seqs, seq];
229
+ var _a;
230
+ var _b;
231
+ return [
232
+ ...seqs,
233
+ {
234
+ ...seq,
235
+ timelineOrder: (_b = (_a = committedOrderRef.current) === null || _a === void 0 ? void 0 : _a.get(seq.id)) !== null && _b !== void 0 ? _b : null,
236
+ },
237
+ ];
238
+ });
239
+ }, []);
240
+ const updateSequence = (0, react_1.useCallback)((seq) => {
241
+ setSequences((seqs) => {
242
+ var _a;
243
+ var _b;
244
+ const index = seqs.findIndex((item) => item.id === seq.id);
245
+ if (index === -1) {
246
+ return seqs;
247
+ }
248
+ const next = [...seqs];
249
+ next[index] = {
250
+ ...seq,
251
+ timelineOrder: (_b = (_a = committedOrderRef.current) === null || _a === void 0 ? void 0 : _a.get(seq.id)) !== null && _b !== void 0 ? _b : null,
252
+ };
253
+ return next;
174
254
  });
175
255
  }, []);
176
256
  const unregisterSequence = (0, react_1.useCallback)((seq) => {
@@ -180,9 +260,10 @@ const SequenceManagerProvider = ({ children }) => {
180
260
  return {
181
261
  registerSequence,
182
262
  sequences,
263
+ updateSequence,
183
264
  unregisterSequence,
184
265
  };
185
- }, [registerSequence, sequences, unregisterSequence]);
266
+ }, [registerSequence, sequences, unregisterSequence, updateSequence]);
186
267
  const getDragOverrides = (0, react_1.useCallback)((nodePath) => {
187
268
  var _a;
188
269
  return (_a = dragOverrides[(0, exports.makeSequencePropsSubscriptionKey)(nodePath)]) !== null && _a !== void 0 ? _a : {};
@@ -219,6 +300,7 @@ const SequenceManagerProvider = ({ children }) => {
219
300
  setPropStatuses,
220
301
  remapPropStatuses,
221
302
  ]);
222
- return (jsx_runtime_1.jsx(exports.SequenceManagerRefContext.Provider, { value: sequencesRef, children: jsx_runtime_1.jsx(exports.SequenceManager.Provider, { value: sequenceContext, children: jsx_runtime_1.jsx(exports.VisualModePropStatusesRefContext.Provider, { value: propStatusesRef, children: jsx_runtime_1.jsx(exports.VisualModePropStatusesContext.Provider, { value: propStatusesContext, children: jsx_runtime_1.jsx(exports.VisualModeDragOverridesContext.Provider, { value: dragOverridesContext, children: jsx_runtime_1.jsx(exports.VisualModeSettersContext.Provider, { value: settersContext, children: children }) }) }) }) }) }));
303
+ const providers = (jsx_runtime_1.jsx(exports.SequenceManagerRefContext.Provider, { value: sequencesRef, children: jsx_runtime_1.jsx(exports.SequenceManager.Provider, { value: sequenceContext, children: jsx_runtime_1.jsx(exports.VisualModePropStatusesRefContext.Provider, { value: propStatusesRef, children: jsx_runtime_1.jsx(exports.VisualModePropStatusesContext.Provider, { value: propStatusesContext, children: jsx_runtime_1.jsx(exports.VisualModeDragOverridesContext.Provider, { value: dragOverridesContext, children: jsx_runtime_1.jsx(exports.VisualModeSettersContext.Provider, { value: settersContext, children: children }) }) }) }) }) }));
304
+ return isStudio ? (jsx_runtime_1.jsx(sequence_order_marker_js_1.SequenceManagerOrderMarker, { managerId: sequenceManagerId, children: providers })) : (providers);
223
305
  };
224
306
  exports.SequenceManagerProvider = SequenceManagerProvider;
@@ -3,26 +3,32 @@ import React from 'react';
3
3
  import { type PlayableMediaTag } from './timeline-position-state';
4
4
  export type TimelineContextValue = {
5
5
  frame: Record<string, number>;
6
- playing: boolean;
7
- imperativePlaying: RefObject<boolean>;
8
- audioAndVideoTags: RefObject<PlayableMediaTag[]>;
9
- };
10
- export type TimelineImperativeContextValue = {
11
- frameRef: RefObject<Record<string, number>>;
12
- imperativePlaying: RefObject<boolean>;
6
+ isPlaying: () => boolean;
13
7
  audioAndVideoTags: RefObject<PlayableMediaTag[]>;
14
8
  };
15
9
  export type PlaybackRateContextValue = {
16
10
  playbackRate: number;
17
11
  setPlaybackRate: (u: React.SetStateAction<number>) => void;
18
12
  };
13
+ export type PlayingState = Readonly<{
14
+ playing: boolean;
15
+ }>;
16
+ export type BufferingState = Readonly<{
17
+ buffering: boolean;
18
+ }>;
19
19
  export type SetTimelineContextValue = {
20
20
  setFrame: (u: React.SetStateAction<Record<string, number>>) => void;
21
21
  setPlaying: (u: React.SetStateAction<boolean>) => void;
22
+ setBuffering: (buffering: boolean) => void;
23
+ subscribePlaying: (listener: (state: PlayingState) => void) => () => void;
24
+ subscribeBuffering: (listener: (state: BufferingState) => void) => () => void;
25
+ isPlaying: () => boolean;
26
+ isBuffering: () => boolean;
27
+ frameRef: RefObject<Record<string, number>>;
28
+ audioAndVideoTags: RefObject<PlayableMediaTag[]>;
22
29
  };
23
30
  export declare const SetTimelineContext: React.Context<SetTimelineContextValue>;
24
31
  export declare const TimelineContext: React.Context<TimelineContextValue | null>;
25
- export declare const TimelineImperativeContext: React.Context<TimelineImperativeContextValue | null>;
26
32
  export declare const PlaybackRateContext: React.Context<PlaybackRateContextValue | null>;
27
33
  export declare const AbsoluteTimeContext: React.Context<TimelineContextValue | null>;
28
34
  export declare const TimelineContextProvider: React.FC<{
@@ -1,31 +1,39 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineContextProvider = exports.AbsoluteTimeContext = exports.PlaybackRateContext = exports.TimelineImperativeContext = exports.TimelineContext = exports.SetTimelineContext = void 0;
3
+ exports.TimelineContextProvider = exports.AbsoluteTimeContext = exports.PlaybackRateContext = exports.TimelineContext = exports.SetTimelineContext = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const runtime_value_store_js_1 = require("./runtime-value-store.js");
6
7
  const timeline_position_state_1 = require("./timeline-position-state");
7
8
  const use_delay_render_1 = require("./use-delay-render");
9
+ const missingSetTimelineContext = () => {
10
+ throw new Error('SetTimelineContext is missing. This is likely caused by a Remotion version mismatch.');
11
+ };
8
12
  exports.SetTimelineContext = (0, react_1.createContext)({
9
- setFrame: () => {
10
- throw new Error('default');
11
- },
12
- setPlaying: () => {
13
- throw new Error('default');
14
- },
13
+ setFrame: missingSetTimelineContext,
14
+ setPlaying: missingSetTimelineContext,
15
+ setBuffering: missingSetTimelineContext,
16
+ subscribePlaying: () => () => undefined,
17
+ subscribeBuffering: () => () => undefined,
18
+ isPlaying: () => false,
19
+ isBuffering: missingSetTimelineContext,
20
+ frameRef: { current: {} },
21
+ audioAndVideoTags: { current: [] },
15
22
  });
16
23
  exports.TimelineContext = (0, react_1.createContext)(null);
17
- exports.TimelineImperativeContext = (0, react_1.createContext)(null);
18
24
  exports.PlaybackRateContext = (0, react_1.createContext)(null);
19
25
  exports.AbsoluteTimeContext = (0, react_1.createContext)(null);
20
26
  const TimelineContextProvider = ({ children, frameState }) => {
21
- const [playing, setPlaying] = (0, react_1.useState)(false);
22
- const imperativePlaying = (0, react_1.useRef)(false);
27
+ const playingStore = (0, react_1.useMemo)(() => (0, runtime_value_store_js_1.createRuntimeValueStore)({ playing: false }), []);
28
+ const bufferingStore = (0, react_1.useMemo)(() => (0, runtime_value_store_js_1.createRuntimeValueStore)({ buffering: false }), []);
23
29
  const [playbackRate, setPlaybackRate] = (0, react_1.useState)(1);
24
30
  const audioAndVideoTags = (0, react_1.useRef)([]);
25
31
  const [_frame, setFrame] = (0, react_1.useState)(() => (0, timeline_position_state_1.getInitialFrameState)());
26
32
  const frame = frameState !== null && frameState !== void 0 ? frameState : _frame;
27
33
  const frameRef = (0, react_1.useRef)(frame);
28
34
  frameRef.current = frame;
35
+ const readIsPlaying = (0, react_1.useCallback)(() => playingStore.store.getSnapshot().playing, [playingStore]);
36
+ const readIsBuffering = (0, react_1.useCallback)(() => bufferingStore.store.getSnapshot().buffering, [bufferingStore]);
29
37
  const { delayRender, continueRender } = (0, use_delay_render_1.useDelayRender)();
30
38
  if (typeof window !== 'undefined') {
31
39
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -61,18 +69,10 @@ const TimelineContextProvider = ({ children, frameState }) => {
61
69
  const timelineContextValue = (0, react_1.useMemo)(() => {
62
70
  return {
63
71
  frame,
64
- playing,
65
- imperativePlaying,
66
- audioAndVideoTags,
67
- };
68
- }, [frame, playing]);
69
- const timelineImperativeContextValue = (0, react_1.useMemo)(() => {
70
- return {
71
- frameRef,
72
- imperativePlaying,
72
+ isPlaying: readIsPlaying,
73
73
  audioAndVideoTags,
74
74
  };
75
- }, []);
75
+ }, [frame, readIsPlaying]);
76
76
  const playbackRateContextValue = (0, react_1.useMemo)(() => {
77
77
  return {
78
78
  playbackRate,
@@ -82,9 +82,26 @@ const TimelineContextProvider = ({ children, frameState }) => {
82
82
  const setTimelineContextValue = (0, react_1.useMemo)(() => {
83
83
  return {
84
84
  setFrame,
85
- setPlaying,
85
+ setPlaying: (updater) => {
86
+ const current = playingStore.store.getSnapshot().playing;
87
+ const next = typeof updater === 'function' ? updater(current) : updater;
88
+ if (current !== next) {
89
+ playingStore.setSnapshot({ playing: next });
90
+ }
91
+ },
92
+ setBuffering: (buffering) => {
93
+ if (readIsBuffering() !== buffering) {
94
+ bufferingStore.setSnapshot({ buffering });
95
+ }
96
+ },
97
+ subscribePlaying: playingStore.store.subscribe,
98
+ subscribeBuffering: bufferingStore.store.subscribe,
99
+ isPlaying: readIsPlaying,
100
+ isBuffering: readIsBuffering,
101
+ frameRef,
102
+ audioAndVideoTags,
86
103
  };
87
- }, []);
88
- return (jsx_runtime_1.jsx(exports.AbsoluteTimeContext.Provider, { value: timelineContextValue, children: jsx_runtime_1.jsx(exports.PlaybackRateContext.Provider, { value: playbackRateContextValue, children: jsx_runtime_1.jsx(exports.TimelineImperativeContext.Provider, { value: timelineImperativeContextValue, children: jsx_runtime_1.jsx(exports.TimelineContext.Provider, { value: timelineContextValue, children: jsx_runtime_1.jsx(exports.SetTimelineContext.Provider, { value: setTimelineContextValue, children: children }) }) }) }) }));
104
+ }, [bufferingStore, playingStore, readIsBuffering, readIsPlaying]);
105
+ return (jsx_runtime_1.jsx(exports.AbsoluteTimeContext.Provider, { value: timelineContextValue, children: jsx_runtime_1.jsx(exports.PlaybackRateContext.Provider, { value: playbackRateContextValue, children: jsx_runtime_1.jsx(exports.TimelineContext.Provider, { value: timelineContextValue, children: jsx_runtime_1.jsx(exports.SetTimelineContext.Provider, { value: setTimelineContextValue, children: children }) }) }) }));
89
106
  };
90
107
  exports.TimelineContextProvider = TimelineContextProvider;
@@ -201,6 +201,7 @@ export declare const animatedImageSchema: {
201
201
  readonly showInTimeline: import("../interactivity-schema.js").HiddenFieldSchema;
202
202
  readonly src: {
203
203
  readonly type: "asset";
204
+ readonly assetType: "image";
204
205
  readonly default: undefined;
205
206
  readonly description: "Source";
206
207
  readonly keyframable: false;
@@ -23,6 +23,7 @@ const resolve_image_source_1 = require("./resolve-image-source");
23
23
  exports.animatedImageSchema = {
24
24
  src: {
25
25
  type: 'asset',
26
+ assetType: 'image',
26
27
  default: undefined,
27
28
  description: 'Source',
28
29
  keyframable: false,
@@ -41,11 +41,13 @@ const get_cross_origin_value_js_1 = require("../get-cross-origin-value.js");
41
41
  const log_level_context_js_1 = require("../log-level-context.js");
42
42
  const prefetch_js_1 = require("../prefetch.js");
43
43
  const random_js_1 = require("../random.js");
44
+ const sequence_order_marker_js_1 = require("../sequence-order-marker.js");
44
45
  const SequenceContext_js_1 = require("../SequenceContext.js");
45
46
  const use_amplification_js_1 = require("../use-amplification.js");
46
47
  const use_media_in_timeline_js_1 = require("../use-media-in-timeline.js");
47
48
  const use_media_playback_js_1 = require("../use-media-playback.js");
48
49
  const use_media_tag_js_1 = require("../use-media-tag.js");
50
+ const use_remotion_environment_js_1 = require("../use-remotion-environment.js");
49
51
  const volume_position_state_js_1 = require("../volume-position-state.js");
50
52
  const volume_prop_js_1 = require("../volume-prop.js");
51
53
  const volume_safeguard_js_1 = require("../volume-safeguard.js");
@@ -73,6 +75,7 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
73
75
  }
74
76
  const preloadedSrc = (0, prefetch_js_1.usePreload)(src);
75
77
  const sequenceContext = (0, react_2.useContext)(SequenceContext_js_1.SequenceContext);
78
+ const { isStudio } = (0, use_remotion_environment_js_1.useRemotionEnvironment)();
76
79
  const [timelineId] = (0, react_2.useState)(() => String(Math.random()));
77
80
  const userPreferredVolume = (0, volume_prop_js_1.evaluateVolume)({
78
81
  frame: volumePropFrame,
@@ -212,8 +215,9 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
212
215
  };
213
216
  }, [audioRef, src]);
214
217
  if (initialShouldPreMountAudioElements) {
215
- return null;
218
+ return isStudio ? (jsx_runtime_1.jsx(sequence_order_marker_js_1.SequenceOrderMarker, { sequenceId: timelineId, children: null })) : null;
216
219
  }
217
- return (jsx_runtime_1.jsx("audio", { ref: audioRef, preload: "metadata", crossOrigin: crossOriginValue, ...propsToPass }));
220
+ const audio = (jsx_runtime_1.jsx("audio", { ref: audioRef, preload: "metadata", crossOrigin: crossOriginValue, ...propsToPass }));
221
+ return isStudio ? (jsx_runtime_1.jsx(sequence_order_marker_js_1.SequenceOrderMarker, { sequenceId: timelineId, children: audio })) : (audio);
218
222
  };
219
223
  exports.AudioForPreview = (0, react_2.forwardRef)(AudioForDevelopmentForwardRefFunction);
@@ -58,6 +58,7 @@ type SharedAudioContextValue = {
58
58
  audioSyncAnchorEmitter: AudioSyncAnchorEmitter;
59
59
  scheduleAudioNode: (options: ScheduleAudioNodeOptions) => ScheduleAudioNodeResult;
60
60
  resume: () => Promise<void>;
61
+ resumeAsAutoPlay: () => Promise<void>;
61
62
  suspend: () => Promise<void>;
62
63
  getIsResumingAudioContext: () => Promise<AudioContextResumeResult> | null;
63
64
  unscheduleAudioNode: (node: AudioBufferSourceNode) => void;
@@ -111,6 +111,7 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
111
111
  }
112
112
  const isResuming = (0, react_1.useRef)(null);
113
113
  const nextResumeAttemptId = (0, react_1.useRef)(0);
114
+ const nextResumeIsAutoPlayAttempt = (0, react_1.useRef)(false);
114
115
  const audioSyncAnchor = (0, react_1.useMemo)(() => ({ value: 0 }), []);
115
116
  const audioSyncAnchorListeners = (0, react_1.useRef)([]);
116
117
  const audioSyncAnchorEmitter = (0, react_1.useMemo)(() => {
@@ -201,6 +202,8 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
201
202
  };
202
203
  }, [ctxAndGain, _experimentalKeepAudioContextAlive, logLevel]);
203
204
  const resume = (0, react_1.useCallback)(() => {
205
+ const isAutoPlayAttempt = nextResumeIsAutoPlayAttempt.current;
206
+ nextResumeIsAutoPlayAttempt.current = false;
204
207
  if (!ctxAndGain) {
205
208
  return Promise.resolve();
206
209
  }
@@ -226,7 +229,7 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
226
229
  const abortController = new AbortController();
227
230
  const resumeAttemptId = nextResumeAttemptId.current++;
228
231
  const waitPromise = new Promise((resolve) => {
229
- (0, wait_until_actually_resumed_js_1.waitUntilActuallyResumed)(ctxAndGain.audioContext, logLevel, abortController.signal).then(resolve);
232
+ (0, wait_until_actually_resumed_js_1.waitUntilActuallyResumed)(ctxAndGain.audioContext, logLevel, abortController.signal, isAutoPlayAttempt).then(resolve);
230
233
  resumePromise.catch((err) => {
231
234
  log_js_1.Log.warn({ logLevel, tag: 'audio' }, 'AudioContext resume rejected, muting playback and continuing without audio', err);
232
235
  abortController.abort();
@@ -248,6 +251,10 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
248
251
  // since callers (e.g. use-playback.ts) do not await this.
249
252
  });
250
253
  }, [ctxAndGain, _experimentalKeepAudioContextAlive, logLevel]);
254
+ const resumeAsAutoPlay = (0, react_1.useCallback)(() => {
255
+ nextResumeIsAutoPlayAttempt.current = true;
256
+ return resume();
257
+ }, [resume]);
251
258
  const getIsResumingAudioContext = (0, react_1.useCallback)(() => {
252
259
  var _a;
253
260
  var _b;
@@ -326,6 +333,7 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
326
333
  audioSyncAnchorEmitter,
327
334
  scheduleAudioNode,
328
335
  resume,
336
+ resumeAsAutoPlay,
329
337
  suspend,
330
338
  getIsResumingAudioContext,
331
339
  unscheduleAudioNode,
@@ -337,6 +345,7 @@ const SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled,
337
345
  audioSyncAnchorEmitter,
338
346
  scheduleAudioNode,
339
347
  resume,
348
+ resumeAsAutoPlay,
340
349
  suspend,
341
350
  getIsResumingAudioContext,
342
351
  unscheduleAudioNode,
@@ -1,2 +1,2 @@
1
1
  export type AudioContextResumeResult = 'resumed' | 'cancelled' | 'failed';
2
- export declare const waitUntilActuallyResumed: (audioContext: AudioContext, logLevel: "error" | "info" | "trace" | "verbose" | "warn", signal: AbortSignal) => Promise<AudioContextResumeResult>;
2
+ export declare const waitUntilActuallyResumed: (audioContext: AudioContext, logLevel: "error" | "info" | "trace" | "verbose" | "warn", signal: AbortSignal, isAutoPlayAttempt: boolean) => Promise<AudioContextResumeResult>;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.waitUntilActuallyResumed = void 0;
4
4
  const log_js_1 = require("../log.js");
5
5
  const RESUME_WAIT_TIMEOUT = 1000;
6
- const waitUntilActuallyResumed = (audioContext, logLevel, signal) => {
6
+ const waitUntilActuallyResumed = (audioContext, logLevel, signal, isAutoPlayAttempt) => {
7
7
  return new Promise((resolve) => {
8
8
  const startCurrentTime = audioContext.currentTime;
9
9
  const start = audioContext.getOutputTimestamp();
@@ -55,19 +55,21 @@ const waitUntilActuallyResumed = (audioContext, logLevel, signal) => {
55
55
  return;
56
56
  }
57
57
  signal.addEventListener('abort', onAbort, { once: true });
58
- timeout = setTimeout(() => {
59
- // The success check is scheduled with requestAnimationFrame, which can
60
- // be starved while the main thread is busy. Re-check once before
61
- // declaring failure so a resume that actually completed is not
62
- // reported as failed - the Player would otherwise mute itself even
63
- // though playback was started by a user gesture and audio is running.
64
- if (hasAudiblyStarted(startOutputPerformanceTime)) {
65
- finish('resumed');
66
- return;
67
- }
68
- log_js_1.Log.warn({ logLevel, tag: 'audio' }, 'WARNING: You enabled autoPlay on an unmuted <Player /> and the browser did not allow the video to be started. Remotion muted the <Player /> so it can play. To properly handle this, either set the `muted` prop or remove the `autoPlay` prop');
69
- finish('failed');
70
- }, RESUME_WAIT_TIMEOUT);
58
+ if (isAutoPlayAttempt) {
59
+ timeout = setTimeout(() => {
60
+ // The success check is scheduled with requestAnimationFrame, which can
61
+ // be starved while the main thread is busy. Re-check once before
62
+ // declaring failure so a resume that actually completed is not
63
+ // reported as failed - the Player would otherwise mute itself even
64
+ // though playback was started by a user gesture and audio is running.
65
+ if (hasAudiblyStarted(startOutputPerformanceTime)) {
66
+ finish('resumed');
67
+ return;
68
+ }
69
+ log_js_1.Log.warn({ logLevel, tag: 'audio' }, 'WARNING: You enabled autoPlay on an unmuted <Player /> and the browser did not allow the video to be started. Remotion muted the <Player /> so it can play. To properly handle this, either set the `muted` prop or remove the `autoPlay` prop');
70
+ finish('failed');
71
+ }, RESUME_WAIT_TIMEOUT);
72
+ }
71
73
  animationFrame = requestAnimationFrame(check);
72
74
  });
73
75
  };
@@ -1,27 +1,11 @@
1
1
  import React from 'react';
2
- type Block = {
3
- id: string;
4
- };
5
- type OnBufferingCallback = () => void;
6
- type OnResumeCallback = () => void;
7
- type ListenForBuffering = (callback: OnBufferingCallback) => {
8
- remove: () => void;
9
- };
10
- type ListenForResume = (callback: OnResumeCallback) => {
11
- remove: () => void;
12
- };
13
- type AddBlock = (block: Block) => {
14
- unblock: () => void;
15
- };
16
2
  type BufferManager = {
17
- addBlock: AddBlock;
18
- listenForBuffering: ListenForBuffering;
19
- listenForResume: ListenForResume;
20
- buffering: React.RefObject<boolean>;
3
+ addBlock: () => {
4
+ unblock: () => void;
5
+ };
21
6
  };
22
7
  export declare const BufferingContextReact: React.Context<BufferManager | null>;
23
8
  export declare const BufferingProvider: React.FC<{
24
9
  readonly children: React.ReactNode;
25
10
  }>;
26
- export declare const useIsPlayerBuffering: (bufferManager: BufferManager) => boolean;
27
11
  export {};
@@ -33,68 +33,35 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.useIsPlayerBuffering = exports.BufferingProvider = exports.BufferingContextReact = void 0;
36
+ exports.BufferingProvider = exports.BufferingContextReact = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const log_level_context_1 = require("./log-level-context");
40
40
  const playback_logging_1 = require("./playback-logging");
41
+ const TimelineContext_js_1 = require("./TimelineContext.js");
41
42
  const use_remotion_environment_1 = require("./use-remotion-environment");
42
- const useBufferManager = (logLevel, mountTime) => {
43
- const [blocks, setBlocks] = (0, react_1.useState)([]);
44
- // Listener registries are refs, not state: `usePlayback` parks its loop
45
- // during buffering and registers its resume listener from a rAF callback.
46
- // With state, that registration only lands after the next React commit -
47
- // if the last block unblocks before then, the resume dispatch reads the
48
- // previous array, the listener is never called, and the playback loop
49
- // stays parked forever (frame clock frozen while isPlaying() is true).
50
- const onBufferingCallbacks = (0, react_1.useRef)([]);
51
- const onResumeCallbacks = (0, react_1.useRef)([]);
43
+ const useBufferManager = (logLevel, mountTime, setBuffering, isBuffering) => {
44
+ const [blockCount, setBlockCount] = (0, react_1.useState)(0);
52
45
  const env = (0, use_remotion_environment_1.useRemotionEnvironment)();
53
46
  const rendering = env.isRendering;
54
- const buffering = (0, react_1.useRef)(false);
55
- const addBlock = (0, react_1.useCallback)((block) => {
47
+ const addBlock = (0, react_1.useCallback)(() => {
56
48
  if (rendering) {
57
49
  return {
58
50
  unblock: () => undefined,
59
51
  };
60
52
  }
61
53
  let unblocked = false;
62
- setBlocks((b) => [...b, block]);
54
+ setBlockCount((count) => count + 1);
63
55
  return {
64
56
  unblock: () => {
65
57
  if (unblocked) {
66
58
  return;
67
59
  }
68
60
  unblocked = true;
69
- setBlocks((b) => {
70
- const newArr = b.filter((bx) => bx !== block);
71
- if (newArr.length === b.length) {
72
- return b;
73
- }
74
- return newArr;
75
- });
61
+ setBlockCount((count) => count - 1);
76
62
  },
77
63
  };
78
64
  }, [rendering]);
79
- const listenForBuffering = (0, react_1.useCallback)((callback) => {
80
- onBufferingCallbacks.current = [
81
- ...onBufferingCallbacks.current,
82
- callback,
83
- ];
84
- return {
85
- remove: () => {
86
- onBufferingCallbacks.current = onBufferingCallbacks.current.filter((cb) => cb !== callback);
87
- },
88
- };
89
- }, []);
90
- const listenForResume = (0, react_1.useCallback)((callback) => {
91
- onResumeCallbacks.current = [...onResumeCallbacks.current, callback];
92
- return {
93
- remove: () => {
94
- onResumeCallbacks.current = onResumeCallbacks.current.filter((cb) => cb !== callback);
95
- },
96
- };
97
- }, []);
98
65
  (0, react_1.useEffect)(() => {
99
66
  if (rendering) {
100
67
  return;
@@ -102,9 +69,8 @@ const useBufferManager = (logLevel, mountTime) => {
102
69
  // Only fire on the `false -> true` transition: adding a block while
103
70
  // already buffering (e.g. a second media element starts loading) must
104
71
  // not re-dispatch `waiting` to listeners.
105
- if (blocks.length > 0 && !buffering.current) {
106
- buffering.current = true;
107
- [...onBufferingCallbacks.current].forEach((c) => c());
72
+ if (blockCount > 0 && !isBuffering()) {
73
+ setBuffering(true);
108
74
  (0, playback_logging_1.playbackLogging)({
109
75
  logLevel,
110
76
  message: 'Player is entering buffer state',
@@ -112,11 +78,8 @@ const useBufferManager = (logLevel, mountTime) => {
112
78
  tag: 'player',
113
79
  });
114
80
  }
115
- // Intentionally only firing when blocks change, not the callbacks
116
- // otherwise a buffering callback might remove itself after being called
117
- // and trigger again
118
81
  // eslint-disable-next-line react-hooks/exhaustive-deps
119
- }, [blocks]);
82
+ }, [blockCount]);
120
83
  if (typeof window !== 'undefined') {
121
84
  // eslint-disable-next-line react-hooks/rules-of-hooks
122
85
  (0, react_1.useLayoutEffect)(() => {
@@ -126,9 +89,8 @@ const useBufferManager = (logLevel, mountTime) => {
126
89
  // Only fire on the `true -> false` transition: the initial mount and
127
90
  // a block that was added and removed within the same commit must not
128
91
  // dispatch `resume` to listeners.
129
- if (blocks.length === 0 && buffering.current) {
130
- buffering.current = false;
131
- [...onResumeCallbacks.current].forEach((c) => c());
92
+ if (blockCount === 0 && isBuffering()) {
93
+ setBuffering(false);
132
94
  (0, playback_logging_1.playbackLogging)({
133
95
  logLevel,
134
96
  message: 'Player is exiting buffer state',
@@ -136,39 +98,16 @@ const useBufferManager = (logLevel, mountTime) => {
136
98
  tag: 'player',
137
99
  });
138
100
  }
139
- // Intentionally only firing when blocks change, not the callbacks
140
- // otherwise a resume callback might remove itself after being called
141
- // and trigger again
142
101
  // eslint-disable-next-line react-hooks/exhaustive-deps
143
- }, [blocks]);
102
+ }, [blockCount]);
144
103
  }
145
- return (0, react_1.useMemo)(() => {
146
- return { addBlock, listenForBuffering, listenForResume, buffering };
147
- }, [addBlock, buffering, listenForBuffering, listenForResume]);
104
+ return (0, react_1.useMemo)(() => ({ addBlock }), [addBlock]);
148
105
  };
149
106
  exports.BufferingContextReact = react_1.default.createContext(null);
150
107
  const BufferingProvider = ({ children }) => {
151
108
  const { logLevel, mountTime } = (0, react_1.useContext)(log_level_context_1.LogLevelContext);
152
- const bufferManager = useBufferManager(logLevel !== null && logLevel !== void 0 ? logLevel : 'info', mountTime);
109
+ const { isBuffering, setBuffering } = (0, react_1.useContext)(TimelineContext_js_1.SetTimelineContext);
110
+ const bufferManager = useBufferManager(logLevel !== null && logLevel !== void 0 ? logLevel : 'info', mountTime, setBuffering, isBuffering);
153
111
  return (jsx_runtime_1.jsx(exports.BufferingContextReact.Provider, { value: bufferManager, children: children }));
154
112
  };
155
113
  exports.BufferingProvider = BufferingProvider;
156
- const useIsPlayerBuffering = (bufferManager) => {
157
- const [isBuffering, setIsBuffering] = (0, react_1.useState)(bufferManager.buffering.current);
158
- (0, react_1.useEffect)(() => {
159
- const onBuffer = () => {
160
- setIsBuffering(true);
161
- };
162
- const onResume = () => {
163
- setIsBuffering(false);
164
- };
165
- const buffer = bufferManager.listenForBuffering(onBuffer);
166
- const resume = bufferManager.listenForResume(onResume);
167
- return () => {
168
- buffer.remove();
169
- resume.remove();
170
- };
171
- }, [bufferManager]);
172
- return isBuffering;
173
- };
174
- exports.useIsPlayerBuffering = useIsPlayerBuffering;
@@ -201,6 +201,7 @@ export declare const canvasImageSchema: {
201
201
  readonly showInTimeline: import("../interactivity-schema.js").HiddenFieldSchema;
202
202
  readonly src: {
203
203
  readonly type: "asset";
204
+ readonly assetType: "image";
204
205
  readonly default: undefined;
205
206
  readonly description: "Source";
206
207
  readonly keyframable: false;