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.
- package/THIRD_PARTY_LICENSES.md +28 -0
- package/dist/cjs/AbsoluteFill.d.ts +3 -15
- package/dist/cjs/Composition.js +5 -5
- package/dist/cjs/CompositionManager.d.ts +2 -3
- package/dist/cjs/CompositionManagerContext.d.ts +1 -2
- package/dist/cjs/CompositionManagerProvider.js +119 -5
- package/dist/cjs/Folder.d.ts +1 -2
- package/dist/cjs/Folder.js +6 -5
- package/dist/cjs/Img.d.ts +1 -0
- package/dist/cjs/Img.js +1 -0
- package/dist/cjs/Interactive.d.ts +3 -15
- package/dist/cjs/RemotionRoot.js +1 -8
- package/dist/cjs/Sequence.js +47 -60
- package/dist/cjs/SequenceManager.d.ts +1 -0
- package/dist/cjs/SequenceManager.js +85 -3
- package/dist/cjs/TimelineContext.d.ts +14 -8
- package/dist/cjs/TimelineContext.js +40 -23
- package/dist/cjs/animated-image/AnimatedImage.d.ts +1 -0
- package/dist/cjs/animated-image/AnimatedImage.js +1 -0
- package/dist/cjs/audio/AudioForPreview.js +6 -2
- package/dist/cjs/audio/shared-audio-tags.d.ts +1 -0
- package/dist/cjs/audio/shared-audio-tags.js +10 -1
- package/dist/cjs/audio/wait-until-actually-resumed.d.ts +1 -1
- package/dist/cjs/audio/wait-until-actually-resumed.js +16 -14
- package/dist/cjs/buffering.d.ts +3 -19
- package/dist/cjs/buffering.js +16 -77
- package/dist/cjs/canvas-image/CanvasImage.d.ts +1 -0
- package/dist/cjs/canvas-image/CanvasImage.js +1 -0
- package/dist/cjs/freeze.js +1 -4
- package/dist/cjs/index.d.ts +0 -1
- package/dist/cjs/interactivity-schema.d.ts +11 -16
- package/dist/cjs/interactivity-schema.js +3 -15
- package/dist/cjs/internals.d.ts +18 -45
- package/dist/cjs/internals.js +12 -4
- package/dist/cjs/runtime-value-store.d.ts +7 -7
- package/dist/cjs/runtime-value-store.js +1 -1
- package/dist/cjs/sequence-order-marker.d.ts +57 -0
- package/dist/cjs/sequence-order-marker.js +44 -0
- package/dist/cjs/timeline-position-state.d.ts +2 -8
- package/dist/cjs/timeline-position-state.js +5 -7
- package/dist/cjs/use-buffer-state.js +1 -3
- package/dist/cjs/use-buffering.d.ts +1 -0
- package/dist/cjs/use-buffering.js +11 -0
- package/dist/cjs/use-media-in-timeline.d.ts +0 -1
- package/dist/cjs/use-media-in-timeline.js +15 -29
- package/dist/cjs/use-media-playback.js +48 -56
- package/dist/cjs/use-media-tag.js +25 -3
- package/dist/cjs/use-playing.d.ts +1 -0
- package/dist/cjs/use-playing.js +14 -0
- package/dist/cjs/use-sequence-registration.d.ts +5 -0
- package/dist/cjs/use-sequence-registration.js +37 -0
- package/dist/cjs/use-sync-external-store.d.ts +28 -0
- package/dist/cjs/use-sync-external-store.js +116 -0
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/video/VideoForPreview.js +5 -1
- package/dist/cjs/wrap-remotion-context.d.ts +1 -12
- package/dist/cjs/wrap-remotion-context.js +1 -8
- package/dist/esm/index.mjs +1145 -919
- package/dist/esm/version.mjs +1 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
22
|
-
const
|
|
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
|
-
|
|
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.
|
|
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;
|
|
@@ -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
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
};
|
package/dist/cjs/buffering.d.ts
CHANGED
|
@@ -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:
|
|
18
|
-
|
|
19
|
-
|
|
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 {};
|
package/dist/cjs/buffering.js
CHANGED
|
@@ -33,68 +33,35 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
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 [
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
106
|
-
|
|
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
|
-
}, [
|
|
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 (
|
|
130
|
-
|
|
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
|
-
}, [
|
|
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
|
|
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;
|