remotion 4.0.390 → 4.0.391

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.
@@ -1,8 +1,9 @@
1
- import type { MutableRefObject } from 'react';
1
+ import type { MutableRefObject, RefObject } from 'react';
2
2
  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
+ frameRef: RefObject<number>;
6
7
  playing: boolean;
7
8
  rootId: string;
8
9
  playbackRate: number;
@@ -16,6 +16,7 @@ exports.SetTimelineContext = (0, react_1.createContext)({
16
16
  });
17
17
  exports.TimelineContext = (0, react_1.createContext)({
18
18
  frame: {},
19
+ frameRef: { current: 0 },
19
20
  playing: false,
20
21
  playbackRate: 1,
21
22
  rootId: '',
@@ -35,6 +36,7 @@ const TimelineContextProvider = ({ children, frameState }) => {
35
36
  const [remotionRootId] = (0, react_1.useState)(() => String((0, random_1.random)(null)));
36
37
  const [_frame, setFrame] = (0, react_1.useState)(() => (0, timeline_position_state_1.getInitialFrameState)());
37
38
  const frame = frameState !== null && frameState !== void 0 ? frameState : _frame;
39
+ const frameRef = (0, react_1.useRef)(0);
38
40
  const { delayRender, continueRender } = (0, use_delay_render_1.useDelayRender)();
39
41
  if (typeof window !== 'undefined') {
40
42
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -76,6 +78,7 @@ const TimelineContextProvider = ({ children, frameState }) => {
76
78
  playbackRate,
77
79
  setPlaybackRate,
78
80
  audioAndVideoTags,
81
+ frameRef,
79
82
  };
80
83
  }, [frame, playbackRate, playing, remotionRootId]);
81
84
  const setTimelineContextValue = (0, react_1.useMemo)(() => {
@@ -89,6 +89,7 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
89
89
  aud: propsToPass,
90
90
  audioId: id,
91
91
  premounting: Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting),
92
+ postmounting: Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting),
92
93
  });
93
94
  (0, use_media_in_timeline_js_1.useMediaInTimeline)({
94
95
  volume,
@@ -19,12 +19,15 @@ type AudioElem = {
19
19
  audioId: string;
20
20
  mediaElementSourceNode: SharedElementSourceNode | null;
21
21
  premounting: boolean;
22
+ postmounting: boolean;
23
+ audioMounted: boolean;
22
24
  };
23
25
  type SharedContext = {
24
26
  registerAudio: (options: {
25
27
  aud: AudioHTMLAttributes<HTMLAudioElement>;
26
28
  audioId: string;
27
29
  premounting: boolean;
30
+ postmounting: boolean;
28
31
  }) => AudioElem;
29
32
  unregisterAudio: (id: number) => void;
30
33
  updateAudio: (options: {
@@ -32,6 +35,7 @@ type SharedContext = {
32
35
  aud: AudioHTMLAttributes<HTMLAudioElement>;
33
36
  audioId: string;
34
37
  premounting: boolean;
38
+ postmounting: boolean;
35
39
  }) => void;
36
40
  playAllAudios: () => void;
37
41
  numberOfAudioTags: number;
@@ -43,9 +47,10 @@ export declare const SharedAudioContextProvider: React.FC<{
43
47
  readonly children: React.ReactNode;
44
48
  readonly audioLatencyHint: AudioContextLatencyCategory;
45
49
  }>;
46
- export declare const useSharedAudio: ({ aud, audioId, premounting, }: {
50
+ export declare const useSharedAudio: ({ aud, audioId, premounting, postmounting, }: {
47
51
  aud: AudioHTMLAttributes<HTMLAudioElement>;
48
52
  audioId: string;
49
53
  premounting: boolean;
54
+ postmounting: boolean;
50
55
  }) => AudioElem;
51
56
  export {};
@@ -126,7 +126,7 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
126
126
  }, [refs]);
127
127
  const registerAudio = (0, react_1.useCallback)((options) => {
128
128
  var _a, _b;
129
- const { aud, audioId, premounting } = options;
129
+ const { aud, audioId, premounting, postmounting } = options;
130
130
  const found = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.find((a) => a.audioId === audioId);
131
131
  if (found) {
132
132
  return found;
@@ -146,6 +146,8 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
146
146
  audioId,
147
147
  mediaElementSourceNode,
148
148
  premounting,
149
+ audioMounted: Boolean(ref.current),
150
+ postmounting,
149
151
  };
150
152
  (_b = audios.current) === null || _b === void 0 ? void 0 : _b.push(newElem);
151
153
  rerenderAudios();
@@ -163,12 +165,18 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
163
165
  audios.current = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.filter((a) => a.id !== id);
164
166
  rerenderAudios();
165
167
  }, [refs, rerenderAudios]);
166
- const updateAudio = (0, react_1.useCallback)(({ aud, audioId, id, premounting, }) => {
168
+ const updateAudio = (0, react_1.useCallback)(({ aud, audioId, id, premounting, postmounting, }) => {
167
169
  var _a;
168
170
  let changed = false;
169
171
  audios.current = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.map((prevA) => {
172
+ const audioMounted = Boolean(prevA.el.current);
173
+ if (prevA.audioMounted !== audioMounted) {
174
+ changed = true;
175
+ }
170
176
  if (prevA.id === id) {
171
- const isTheSame = compareProps(aud, prevA.props) && prevA.premounting === premounting;
177
+ const isTheSame = compareProps(aud, prevA.props) &&
178
+ prevA.premounting === premounting &&
179
+ prevA.postmounting === postmounting;
172
180
  if (isTheSame) {
173
181
  return prevA;
174
182
  }
@@ -177,7 +185,9 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
177
185
  ...prevA,
178
186
  props: aud,
179
187
  premounting,
188
+ postmounting,
180
189
  audioId,
190
+ audioMounted,
181
191
  };
182
192
  }
183
193
  return prevA;
@@ -232,7 +242,7 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
232
242
  }), children] }));
233
243
  };
234
244
  exports.SharedAudioContextProvider = SharedAudioContextProvider;
235
- const useSharedAudio = ({ aud, audioId, premounting, }) => {
245
+ const useSharedAudio = ({ aud, audioId, premounting, postmounting, }) => {
236
246
  var _a;
237
247
  const ctx = (0, react_1.useContext)(exports.SharedAudioContext);
238
248
  /**
@@ -240,7 +250,7 @@ const useSharedAudio = ({ aud, audioId, premounting, }) => {
240
250
  */
241
251
  const [elem] = (0, react_1.useState)(() => {
242
252
  if (ctx && ctx.numberOfAudioTags > 0) {
243
- return ctx.registerAudio({ aud, audioId, premounting });
253
+ return ctx.registerAudio({ aud, audioId, premounting, postmounting });
244
254
  }
245
255
  const el = react_1.default.createRef();
246
256
  const mediaElementSourceNode = (ctx === null || ctx === void 0 ? void 0 : ctx.audioContext)
@@ -256,6 +266,8 @@ const useSharedAudio = ({ aud, audioId, premounting, }) => {
256
266
  audioId,
257
267
  mediaElementSourceNode,
258
268
  premounting,
269
+ audioMounted: Boolean(el.current),
270
+ postmounting,
259
271
  };
260
272
  });
261
273
  /**
@@ -269,9 +281,9 @@ const useSharedAudio = ({ aud, audioId, premounting, }) => {
269
281
  if (typeof document !== 'undefined') {
270
282
  effectToUse(() => {
271
283
  if (ctx && ctx.numberOfAudioTags > 0) {
272
- ctx.updateAudio({ id: elem.id, aud, audioId, premounting });
284
+ ctx.updateAudio({ id: elem.id, aud, audioId, premounting, postmounting });
273
285
  }
274
- }, [aud, ctx, elem.id, audioId, premounting]);
286
+ }, [aud, ctx, elem.id, audioId, premounting, postmounting]);
275
287
  effectToUse(() => {
276
288
  return () => {
277
289
  if (ctx && ctx.numberOfAudioTags > 0) {
@@ -11,6 +11,7 @@ export type DelayRenderScope = {
11
11
  };
12
12
  remotion_puppeteerTimeout: number;
13
13
  remotion_attempt: number;
14
+ remotion_delayRenderHandles: number[];
14
15
  remotion_cancelledError?: string;
15
16
  };
16
17
  export declare const DELAY_RENDER_CALLSTACK_TOKEN = "The delayRender was called:";
@@ -27,7 +28,7 @@ export type DelayRenderOptions = {
27
28
  * @private
28
29
  */
29
30
  export declare const delayRenderInternal: ({ scope, environment, label, options, }: {
30
- scope: DelayRenderScope | undefined;
31
+ scope: DelayRenderScope;
31
32
  environment: RemotionEnvironment;
32
33
  label: string | null;
33
34
  options: DelayRenderOptions;
@@ -38,7 +39,7 @@ export declare const delayRender: (label?: string, options?: DelayRenderOptions)
38
39
  * @private
39
40
  */
40
41
  export declare const continueRenderInternal: ({ scope, handle, environment, logLevel, }: {
41
- scope: DelayRenderScope | undefined;
42
+ scope: DelayRenderScope;
42
43
  handle: number;
43
44
  environment: RemotionEnvironment;
44
45
  logLevel: LogLevel;
@@ -5,12 +5,12 @@ const cancel_render_js_1 = require("./cancel-render.js");
5
5
  const get_remotion_environment_js_1 = require("./get-remotion-environment.js");
6
6
  const log_js_1 = require("./log.js");
7
7
  const truthy_js_1 = require("./truthy.js");
8
- let handles = [];
9
8
  if (typeof window !== 'undefined') {
10
9
  window.remotion_renderReady = false;
11
10
  if (!window.remotion_delayRenderTimeouts) {
12
11
  window.remotion_delayRenderTimeouts = {};
13
12
  }
13
+ window.remotion_delayRenderHandles = [];
14
14
  }
15
15
  exports.DELAY_RENDER_CALLSTACK_TOKEN = 'The delayRender was called:';
16
16
  exports.DELAY_RENDER_RETRIES_LEFT = 'Retries left: ';
@@ -29,37 +29,31 @@ const delayRenderInternal = ({ scope, environment, label, options, }) => {
29
29
  JSON.stringify(label));
30
30
  }
31
31
  const handle = Math.random();
32
- handles.push(handle);
32
+ scope.remotion_delayRenderHandles.push(handle);
33
33
  const called = (_b = (_a = Error().stack) === null || _a === void 0 ? void 0 : _a.replace(/^Error/g, '')) !== null && _b !== void 0 ? _b : '';
34
34
  if (environment.isRendering) {
35
- const timeoutToUse = ((_c = options === null || options === void 0 ? void 0 : options.timeoutInMilliseconds) !== null && _c !== void 0 ? _c : (typeof scope === 'undefined'
36
- ? defaultTimeout
37
- : ((_d = scope.remotion_puppeteerTimeout) !== null && _d !== void 0 ? _d : defaultTimeout))) - 2000;
38
- if (typeof scope !== 'undefined') {
39
- const retriesLeft = ((_e = options === null || options === void 0 ? void 0 : options.retries) !== null && _e !== void 0 ? _e : 0) - (scope.remotion_attempt - 1);
40
- scope.remotion_delayRenderTimeouts[handle] = {
41
- label: label !== null && label !== void 0 ? label : null,
42
- startTime: Date.now(),
43
- timeout: setTimeout(() => {
44
- const message = [
45
- `A delayRender()`,
46
- label ? `"${label}"` : null,
47
- `was called but not cleared after ${timeoutToUse}ms. See https://remotion.dev/docs/timeout for help.`,
48
- retriesLeft > 0 ? exports.DELAY_RENDER_RETRIES_LEFT + retriesLeft : null,
49
- retriesLeft > 0 ? exports.DELAY_RENDER_RETRY_TOKEN : null,
50
- exports.DELAY_RENDER_CALLSTACK_TOKEN,
51
- called,
52
- ]
53
- .filter(truthy_js_1.truthy)
54
- .join(' ');
55
- (0, cancel_render_js_1.cancelRenderInternal)(scope, Error(message));
56
- }, timeoutToUse),
57
- };
58
- }
59
- }
60
- if (typeof scope !== 'undefined') {
61
- scope.remotion_renderReady = false;
35
+ const timeoutToUse = ((_d = (_c = options === null || options === void 0 ? void 0 : options.timeoutInMilliseconds) !== null && _c !== void 0 ? _c : scope.remotion_puppeteerTimeout) !== null && _d !== void 0 ? _d : defaultTimeout) - 2000;
36
+ const retriesLeft = ((_e = options === null || options === void 0 ? void 0 : options.retries) !== null && _e !== void 0 ? _e : 0) - (scope.remotion_attempt - 1);
37
+ scope.remotion_delayRenderTimeouts[handle] = {
38
+ label: label !== null && label !== void 0 ? label : null,
39
+ startTime: Date.now(),
40
+ timeout: setTimeout(() => {
41
+ const message = [
42
+ `A delayRender()`,
43
+ label ? `"${label}"` : null,
44
+ `was called but not cleared after ${timeoutToUse}ms. See https://remotion.dev/docs/timeout for help.`,
45
+ retriesLeft > 0 ? exports.DELAY_RENDER_RETRIES_LEFT + retriesLeft : null,
46
+ retriesLeft > 0 ? exports.DELAY_RENDER_RETRY_TOKEN : null,
47
+ exports.DELAY_RENDER_CALLSTACK_TOKEN,
48
+ called,
49
+ ]
50
+ .filter(truthy_js_1.truthy)
51
+ .join(' ');
52
+ (0, cancel_render_js_1.cancelRenderInternal)(scope, Error(message));
53
+ }, timeoutToUse),
54
+ };
62
55
  }
56
+ scope.remotion_renderReady = false;
63
57
  return handle;
64
58
  };
65
59
  exports.delayRenderInternal = delayRenderInternal;
@@ -68,8 +62,11 @@ exports.delayRenderInternal = delayRenderInternal;
68
62
  * @see [Documentation](https://remotion.dev/docs/delay-render)
69
63
  */
70
64
  const delayRender = (label, options) => {
65
+ if (typeof window === 'undefined') {
66
+ return Math.random();
67
+ }
71
68
  return (0, exports.delayRenderInternal)({
72
- scope: typeof window !== 'undefined' ? window : undefined,
69
+ scope: window,
73
70
  environment: (0, get_remotion_environment_js_1.getRemotionEnvironment)(),
74
71
  label: label !== null && label !== void 0 ? label : null,
75
72
  options: options !== null && options !== void 0 ? options : {},
@@ -88,7 +85,7 @@ const continueRenderInternal = ({ scope, handle, environment, logLevel, }) => {
88
85
  throw new TypeError('The parameter passed into continueRender() must be the return value of delayRender() which is a number. Got: ' +
89
86
  JSON.stringify(handle));
90
87
  }
91
- handles = handles.filter((h) => {
88
+ scope.remotion_delayRenderHandles = scope.remotion_delayRenderHandles.filter((h) => {
92
89
  if (h === handle) {
93
90
  if (environment.isRendering && scope !== undefined) {
94
91
  if (!scope.remotion_delayRenderTimeouts[handle]) {
@@ -110,7 +107,7 @@ const continueRenderInternal = ({ scope, handle, environment, logLevel, }) => {
110
107
  }
111
108
  return true;
112
109
  });
113
- if (handles.length === 0 && typeof scope !== 'undefined') {
110
+ if (scope.remotion_delayRenderHandles.length === 0) {
114
111
  scope.remotion_renderReady = true;
115
112
  }
116
113
  };
@@ -121,13 +118,14 @@ exports.continueRenderInternal = continueRenderInternal;
121
118
  */
122
119
  const continueRender = (handle) => {
123
120
  var _a;
121
+ if (typeof window === 'undefined') {
122
+ return;
123
+ }
124
124
  (0, exports.continueRenderInternal)({
125
- scope: typeof window !== 'undefined' ? window : undefined,
125
+ scope: window,
126
126
  handle,
127
127
  environment: (0, get_remotion_environment_js_1.getRemotionEnvironment)(),
128
- logLevel: typeof window !== 'undefined'
129
- ? ((_a = window.remotion_logLevel) !== null && _a !== void 0 ? _a : 'info')
130
- : 'info',
128
+ logLevel: (_a = window.remotion_logLevel) !== null && _a !== void 0 ? _a : 'info',
131
129
  });
132
130
  };
133
131
  exports.continueRender = continueRender;
@@ -22,6 +22,7 @@ declare global {
22
22
  startTime: number;
23
23
  };
24
24
  };
25
+ remotion_delayRenderHandles: number[];
25
26
  remotion_cancelledError: string | undefined;
26
27
  remotion_getCompositionNames: () => string[];
27
28
  remotion_seenCompositionIds: string[];
@@ -129,6 +129,7 @@ export declare const Internals: {
129
129
  aud: import("react").AudioHTMLAttributes<HTMLAudioElement>;
130
130
  audioId: string;
131
131
  premounting: boolean;
132
+ postmounting: boolean;
132
133
  }) => {
133
134
  id: number;
134
135
  props: import("react").AudioHTMLAttributes<HTMLAudioElement>;
@@ -136,6 +137,8 @@ export declare const Internals: {
136
137
  audioId: string;
137
138
  mediaElementSourceNode: import("./audio/shared-element-source-node.js").SharedElementSourceNode | null;
138
139
  premounting: boolean;
140
+ postmounting: boolean;
141
+ audioMounted: boolean;
139
142
  };
140
143
  unregisterAudio: (id: number) => void;
141
144
  updateAudio: (options: {
@@ -143,6 +146,7 @@ export declare const Internals: {
143
146
  aud: import("react").AudioHTMLAttributes<HTMLAudioElement>;
144
147
  audioId: string;
145
148
  premounting: boolean;
149
+ postmounting: boolean;
146
150
  }) => void;
147
151
  playAllAudios: () => void;
148
152
  numberOfAudioTags: number;
@@ -1,4 +1,4 @@
1
- import type { MutableRefObject } from 'react';
1
+ import type { MutableRefObject, RefObject } from 'react';
2
2
  export type PlayableMediaTag = {
3
3
  play: (reason: string) => void;
4
4
  id: string;
@@ -8,6 +8,7 @@ export declare const persistCurrentFrame: (time: CurrentTimePerComposition) => v
8
8
  export declare const getInitialFrameState: () => CurrentTimePerComposition;
9
9
  export declare const getFrameForComposition: (composition: string) => number;
10
10
  export declare const useTimelinePosition: () => number;
11
+ export declare const useTimelineFrameRef: () => RefObject<number>;
11
12
  export declare const useTimelineSetFrame: () => ((u: React.SetStateAction<Record<string, number>>) => void);
12
13
  type PlayingReturnType = readonly [
13
14
  boolean,
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.usePlayingState = exports.useTimelineSetFrame = exports.useTimelinePosition = exports.getFrameForComposition = exports.getInitialFrameState = exports.persistCurrentFrame = void 0;
3
+ exports.usePlayingState = exports.useTimelineSetFrame = exports.useTimelineFrameRef = exports.useTimelinePosition = exports.getFrameForComposition = exports.getInitialFrameState = exports.persistCurrentFrame = void 0;
4
4
  const react_1 = require("react");
5
5
  const TimelineContext_js_1 = require("./TimelineContext.js");
6
6
  const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
@@ -46,6 +46,11 @@ const useTimelinePosition = () => {
46
46
  return Math.min(videoConfig.durationInFrames - 1, unclamped);
47
47
  };
48
48
  exports.useTimelinePosition = useTimelinePosition;
49
+ const useTimelineFrameRef = () => {
50
+ const { frameRef } = (0, react_1.useContext)(TimelineContext_js_1.TimelineContext);
51
+ return frameRef;
52
+ };
53
+ exports.useTimelineFrameRef = useTimelineFrameRef;
49
54
  const useTimelineSetFrame = () => {
50
55
  const { setFrame } = (0, react_1.useContext)(TimelineContext_js_1.SetTimelineContext);
51
56
  return setFrame;
@@ -8,20 +8,27 @@ const log_level_context_js_1 = require("./log-level-context.js");
8
8
  const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
9
9
  exports.DelayRenderContextType = (0, react_1.createContext)(null);
10
10
  const useDelayRender = () => {
11
+ var _a;
11
12
  const environment = (0, use_remotion_environment_js_1.useRemotionEnvironment)();
12
- const scope = (0, react_1.useContext)(exports.DelayRenderContextType);
13
+ const scope = (_a = (0, react_1.useContext)(exports.DelayRenderContextType)) !== null && _a !== void 0 ? _a : (typeof window !== 'undefined' ? window : undefined);
13
14
  const logLevel = (0, log_level_context_js_1.useLogLevel)();
14
15
  const delayRender = (0, react_1.useCallback)((label, options) => {
16
+ if (!scope) {
17
+ return Math.random();
18
+ }
15
19
  return (0, delay_render_js_1.delayRenderInternal)({
16
- scope: scope !== null && scope !== void 0 ? scope : (typeof window !== 'undefined' ? window : undefined),
20
+ scope,
17
21
  environment,
18
22
  label: label !== null && label !== void 0 ? label : null,
19
23
  options: options !== null && options !== void 0 ? options : {},
20
24
  });
21
25
  }, [environment, scope]);
22
26
  const continueRender = (0, react_1.useCallback)((handle) => {
27
+ if (!scope) {
28
+ return;
29
+ }
23
30
  (0, delay_render_js_1.continueRenderInternal)({
24
- scope: scope !== null && scope !== void 0 ? scope : (typeof window !== 'undefined' ? window : undefined),
31
+ scope,
25
32
  handle,
26
33
  environment,
27
34
  logLevel,
@@ -3,4 +3,4 @@
3
3
  * @see [Documentation](https://remotion.dev/docs/version)
4
4
  * @returns {string} The current version of the remotion package
5
5
  */
6
- export declare const VERSION = "4.0.390";
6
+ export declare const VERSION = "4.0.391";
@@ -7,4 +7,4 @@ exports.VERSION = void 0;
7
7
  * @see [Documentation](https://remotion.dev/docs/version)
8
8
  * @returns {string} The current version of the remotion package
9
9
  */
10
- exports.VERSION = '4.0.390';
10
+ exports.VERSION = '4.0.391';
@@ -110,7 +110,7 @@ function truthy(value) {
110
110
  }
111
111
 
112
112
  // src/version.ts
113
- var VERSION = "4.0.390";
113
+ var VERSION = "4.0.391";
114
114
 
115
115
  // src/multiple-versions-warning.ts
116
116
  var checkMultipleRemotionVersions = () => {
@@ -354,6 +354,7 @@ var exports_timeline_position_state = {};
354
354
  __export(exports_timeline_position_state, {
355
355
  useTimelineSetFrame: () => useTimelineSetFrame,
356
356
  useTimelinePosition: () => useTimelinePosition,
357
+ useTimelineFrameRef: () => useTimelineFrameRef,
357
358
  usePlayingState: () => usePlayingState,
358
359
  persistCurrentFrame: () => persistCurrentFrame,
359
360
  getInitialFrameState: () => getInitialFrameState,
@@ -1243,6 +1244,10 @@ var useTimelinePosition = () => {
1243
1244
  const unclamped = state.frame[videoConfig.id] ?? (env.isPlayer ? 0 : getFrameForComposition(videoConfig.id));
1244
1245
  return Math.min(videoConfig.durationInFrames - 1, unclamped);
1245
1246
  };
1247
+ var useTimelineFrameRef = () => {
1248
+ const { frameRef } = useContext6(TimelineContext);
1249
+ return frameRef;
1250
+ };
1246
1251
  var useTimelineSetFrame = () => {
1247
1252
  const { setFrame } = useContext6(SetTimelineContext);
1248
1253
  return setFrame;
@@ -1356,12 +1361,12 @@ var Log = {
1356
1361
  };
1357
1362
 
1358
1363
  // src/delay-render.ts
1359
- var handles = [];
1360
1364
  if (typeof window !== "undefined") {
1361
1365
  window.remotion_renderReady = false;
1362
1366
  if (!window.remotion_delayRenderTimeouts) {
1363
1367
  window.remotion_delayRenderTimeouts = {};
1364
1368
  }
1369
+ window.remotion_delayRenderHandles = [];
1365
1370
  }
1366
1371
  var DELAY_RENDER_CALLSTACK_TOKEN = "The delayRender was called:";
1367
1372
  var DELAY_RENDER_RETRIES_LEFT = "Retries left: ";
@@ -1378,38 +1383,37 @@ var delayRenderInternal = ({
1378
1383
  throw new Error("The label parameter of delayRender() must be a string or undefined, got: " + JSON.stringify(label));
1379
1384
  }
1380
1385
  const handle = Math.random();
1381
- handles.push(handle);
1386
+ scope.remotion_delayRenderHandles.push(handle);
1382
1387
  const called = Error().stack?.replace(/^Error/g, "") ?? "";
1383
1388
  if (environment.isRendering) {
1384
- const timeoutToUse = (options?.timeoutInMilliseconds ?? (typeof scope === "undefined" ? defaultTimeout : scope.remotion_puppeteerTimeout ?? defaultTimeout)) - 2000;
1385
- if (typeof scope !== "undefined") {
1386
- const retriesLeft = (options?.retries ?? 0) - (scope.remotion_attempt - 1);
1387
- scope.remotion_delayRenderTimeouts[handle] = {
1388
- label: label ?? null,
1389
- startTime: Date.now(),
1390
- timeout: setTimeout(() => {
1391
- const message = [
1392
- `A delayRender()`,
1393
- label ? `"${label}"` : null,
1394
- `was called but not cleared after ${timeoutToUse}ms. See https://remotion.dev/docs/timeout for help.`,
1395
- retriesLeft > 0 ? DELAY_RENDER_RETRIES_LEFT + retriesLeft : null,
1396
- retriesLeft > 0 ? DELAY_RENDER_RETRY_TOKEN : null,
1397
- DELAY_RENDER_CALLSTACK_TOKEN,
1398
- called
1399
- ].filter(truthy).join(" ");
1400
- cancelRenderInternal(scope, Error(message));
1401
- }, timeoutToUse)
1402
- };
1403
- }
1404
- }
1405
- if (typeof scope !== "undefined") {
1406
- scope.remotion_renderReady = false;
1389
+ const timeoutToUse = (options?.timeoutInMilliseconds ?? scope.remotion_puppeteerTimeout ?? defaultTimeout) - 2000;
1390
+ const retriesLeft = (options?.retries ?? 0) - (scope.remotion_attempt - 1);
1391
+ scope.remotion_delayRenderTimeouts[handle] = {
1392
+ label: label ?? null,
1393
+ startTime: Date.now(),
1394
+ timeout: setTimeout(() => {
1395
+ const message = [
1396
+ `A delayRender()`,
1397
+ label ? `"${label}"` : null,
1398
+ `was called but not cleared after ${timeoutToUse}ms. See https://remotion.dev/docs/timeout for help.`,
1399
+ retriesLeft > 0 ? DELAY_RENDER_RETRIES_LEFT + retriesLeft : null,
1400
+ retriesLeft > 0 ? DELAY_RENDER_RETRY_TOKEN : null,
1401
+ DELAY_RENDER_CALLSTACK_TOKEN,
1402
+ called
1403
+ ].filter(truthy).join(" ");
1404
+ cancelRenderInternal(scope, Error(message));
1405
+ }, timeoutToUse)
1406
+ };
1407
1407
  }
1408
+ scope.remotion_renderReady = false;
1408
1409
  return handle;
1409
1410
  };
1410
1411
  var delayRender = (label, options) => {
1412
+ if (typeof window === "undefined") {
1413
+ return Math.random();
1414
+ }
1411
1415
  return delayRenderInternal({
1412
- scope: typeof window !== "undefined" ? window : undefined,
1416
+ scope: window,
1413
1417
  environment: getRemotionEnvironment(),
1414
1418
  label: label ?? null,
1415
1419
  options: options ?? {}
@@ -1427,7 +1431,7 @@ var continueRenderInternal = ({
1427
1431
  if (typeof handle !== "number") {
1428
1432
  throw new TypeError("The parameter passed into continueRender() must be the return value of delayRender() which is a number. Got: " + JSON.stringify(handle));
1429
1433
  }
1430
- handles = handles.filter((h) => {
1434
+ scope.remotion_delayRenderHandles = scope.remotion_delayRenderHandles.filter((h) => {
1431
1435
  if (h === handle) {
1432
1436
  if (environment.isRendering && scope !== undefined) {
1433
1437
  if (!scope.remotion_delayRenderTimeouts[handle]) {
@@ -1447,16 +1451,19 @@ var continueRenderInternal = ({
1447
1451
  }
1448
1452
  return true;
1449
1453
  });
1450
- if (handles.length === 0 && typeof scope !== "undefined") {
1454
+ if (scope.remotion_delayRenderHandles.length === 0) {
1451
1455
  scope.remotion_renderReady = true;
1452
1456
  }
1453
1457
  };
1454
1458
  var continueRender = (handle) => {
1459
+ if (typeof window === "undefined") {
1460
+ return;
1461
+ }
1455
1462
  continueRenderInternal({
1456
- scope: typeof window !== "undefined" ? window : undefined,
1463
+ scope: window,
1457
1464
  handle,
1458
1465
  environment: getRemotionEnvironment(),
1459
- logLevel: typeof window !== "undefined" ? window.remotion_logLevel ?? "info" : "info"
1466
+ logLevel: window.remotion_logLevel ?? "info"
1460
1467
  });
1461
1468
  };
1462
1469
 
@@ -1486,19 +1493,25 @@ var useMountTime = () => {
1486
1493
  var DelayRenderContextType = createContext9(null);
1487
1494
  var useDelayRender = () => {
1488
1495
  const environment = useRemotionEnvironment();
1489
- const scope = useContext8(DelayRenderContextType);
1496
+ const scope = useContext8(DelayRenderContextType) ?? (typeof window !== "undefined" ? window : undefined);
1490
1497
  const logLevel = useLogLevel();
1491
1498
  const delayRender2 = useCallback4((label, options) => {
1499
+ if (!scope) {
1500
+ return Math.random();
1501
+ }
1492
1502
  return delayRenderInternal({
1493
- scope: scope ?? (typeof window !== "undefined" ? window : undefined),
1503
+ scope,
1494
1504
  environment,
1495
1505
  label: label ?? null,
1496
1506
  options: options ?? {}
1497
1507
  });
1498
1508
  }, [environment, scope]);
1499
1509
  const continueRender2 = useCallback4((handle) => {
1510
+ if (!scope) {
1511
+ return;
1512
+ }
1500
1513
  continueRenderInternal({
1501
- scope: scope ?? (typeof window !== "undefined" ? window : undefined),
1514
+ scope,
1502
1515
  handle,
1503
1516
  environment,
1504
1517
  logLevel
@@ -1522,6 +1535,7 @@ var SetTimelineContext = createContext10({
1522
1535
  });
1523
1536
  var TimelineContext = createContext10({
1524
1537
  frame: {},
1538
+ frameRef: { current: 0 },
1525
1539
  playing: false,
1526
1540
  playbackRate: 1,
1527
1541
  rootId: "",
@@ -1541,6 +1555,7 @@ var TimelineContextProvider = ({ children, frameState }) => {
1541
1555
  const [remotionRootId] = useState5(() => String(random(null)));
1542
1556
  const [_frame, setFrame] = useState5(() => getInitialFrameState());
1543
1557
  const frame = frameState ?? _frame;
1558
+ const frameRef = useRef2(0);
1544
1559
  const { delayRender: delayRender2, continueRender: continueRender2 } = useDelayRender();
1545
1560
  if (typeof window !== "undefined") {
1546
1561
  useLayoutEffect(() => {
@@ -1576,7 +1591,8 @@ var TimelineContextProvider = ({ children, frameState }) => {
1576
1591
  rootId: remotionRootId,
1577
1592
  playbackRate,
1578
1593
  setPlaybackRate,
1579
- audioAndVideoTags
1594
+ audioAndVideoTags,
1595
+ frameRef
1580
1596
  };
1581
1597
  }, [frame, playbackRate, playing, remotionRootId]);
1582
1598
  const setTimelineContextValue = useMemo7(() => {
@@ -3196,7 +3212,7 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyHin
3196
3212
  });
3197
3213
  }, [refs]);
3198
3214
  const registerAudio = useCallback7((options) => {
3199
- const { aud, audioId, premounting } = options;
3215
+ const { aud, audioId, premounting, postmounting } = options;
3200
3216
  const found = audios.current?.find((a) => a.audioId === audioId);
3201
3217
  if (found) {
3202
3218
  return found;
@@ -3215,7 +3231,9 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyHin
3215
3231
  el: ref,
3216
3232
  audioId,
3217
3233
  mediaElementSourceNode,
3218
- premounting
3234
+ premounting,
3235
+ audioMounted: Boolean(ref.current),
3236
+ postmounting
3219
3237
  };
3220
3238
  audios.current?.push(newElem);
3221
3239
  rerenderAudios();
@@ -3236,12 +3254,17 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyHin
3236
3254
  aud,
3237
3255
  audioId,
3238
3256
  id,
3239
- premounting
3257
+ premounting,
3258
+ postmounting
3240
3259
  }) => {
3241
3260
  let changed = false;
3242
3261
  audios.current = audios.current?.map((prevA) => {
3262
+ const audioMounted = Boolean(prevA.el.current);
3263
+ if (prevA.audioMounted !== audioMounted) {
3264
+ changed = true;
3265
+ }
3243
3266
  if (prevA.id === id) {
3244
- const isTheSame = compareProps(aud, prevA.props) && prevA.premounting === premounting;
3267
+ const isTheSame = compareProps(aud, prevA.props) && prevA.premounting === premounting && prevA.postmounting === postmounting;
3245
3268
  if (isTheSame) {
3246
3269
  return prevA;
3247
3270
  }
@@ -3250,7 +3273,9 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyHin
3250
3273
  ...prevA,
3251
3274
  props: aud,
3252
3275
  premounting,
3253
- audioId
3276
+ postmounting,
3277
+ audioId,
3278
+ audioMounted
3254
3279
  };
3255
3280
  }
3256
3281
  return prevA;
@@ -3313,12 +3338,13 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyHin
3313
3338
  var useSharedAudio = ({
3314
3339
  aud,
3315
3340
  audioId,
3316
- premounting
3341
+ premounting,
3342
+ postmounting
3317
3343
  }) => {
3318
3344
  const ctx = useContext16(SharedAudioContext);
3319
3345
  const [elem] = useState11(() => {
3320
3346
  if (ctx && ctx.numberOfAudioTags > 0) {
3321
- return ctx.registerAudio({ aud, audioId, premounting });
3347
+ return ctx.registerAudio({ aud, audioId, premounting, postmounting });
3322
3348
  }
3323
3349
  const el = React15.createRef();
3324
3350
  const mediaElementSourceNode = ctx?.audioContext ? makeSharedElementSourceNode({
@@ -3331,16 +3357,18 @@ var useSharedAudio = ({
3331
3357
  props: aud,
3332
3358
  audioId,
3333
3359
  mediaElementSourceNode,
3334
- premounting
3360
+ premounting,
3361
+ audioMounted: Boolean(el.current),
3362
+ postmounting
3335
3363
  };
3336
3364
  });
3337
3365
  const effectToUse = React15.useInsertionEffect ?? React15.useLayoutEffect;
3338
3366
  if (typeof document !== "undefined") {
3339
3367
  effectToUse(() => {
3340
3368
  if (ctx && ctx.numberOfAudioTags > 0) {
3341
- ctx.updateAudio({ id: elem.id, aud, audioId, premounting });
3369
+ ctx.updateAudio({ id: elem.id, aud, audioId, premounting, postmounting });
3342
3370
  }
3343
- }, [aud, ctx, elem.id, audioId, premounting]);
3371
+ }, [aud, ctx, elem.id, audioId, premounting, postmounting]);
3344
3372
  effectToUse(() => {
3345
3373
  return () => {
3346
3374
  if (ctx && ctx.numberOfAudioTags > 0) {
@@ -4812,7 +4840,8 @@ var AudioForDevelopmentForwardRefFunction = (props, ref) => {
4812
4840
  const { el: audioRef, mediaElementSourceNode } = useSharedAudio({
4813
4841
  aud: propsToPass,
4814
4842
  audioId: id,
4815
- premounting: Boolean(sequenceContext?.premounting)
4843
+ premounting: Boolean(sequenceContext?.premounting),
4844
+ postmounting: Boolean(sequenceContext?.postmounting)
4816
4845
  });
4817
4846
  useMediaInTimeline({
4818
4847
  volume,
@@ -142,6 +142,7 @@ if (typeof window !== "undefined") {
142
142
  if (!window.remotion_delayRenderTimeouts) {
143
143
  window.remotion_delayRenderTimeouts = {};
144
144
  }
145
+ window.remotion_delayRenderHandles = [];
145
146
  }
146
147
  var DELAY_RENDER_CALLSTACK_TOKEN = "The delayRender was called:";
147
148
  var DELAY_RENDER_RETRIES_LEFT = "Retries left: ";
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.390";
2
+ var VERSION = "4.0.391";
3
3
  export {
4
4
  VERSION
5
5
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/core"
4
4
  },
5
5
  "name": "remotion",
6
- "version": "4.0.390",
6
+ "version": "4.0.391",
7
7
  "description": "Make videos programmatically",
8
8
  "main": "dist/cjs/index.js",
9
9
  "types": "dist/cjs/index.d.ts",
@@ -34,7 +34,7 @@
34
34
  "react-dom": "19.2.3",
35
35
  "webpack": "5.96.1",
36
36
  "zod": "3.22.3",
37
- "@remotion/eslint-config-internal": "4.0.390",
37
+ "@remotion/eslint-config-internal": "4.0.391",
38
38
  "eslint": "9.19.0"
39
39
  },
40
40
  "keywords": [