remotion 3.3.83 → 3.3.84

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.
@@ -78,5 +78,6 @@ export declare const compositionsRef: React.RefObject<{
78
78
  }>;
79
79
  export declare const CompositionManagerProvider: React.FC<{
80
80
  children: React.ReactNode;
81
+ numberOfAudioTags: number;
81
82
  }>;
82
83
  export {};
@@ -26,6 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.CompositionManagerProvider = exports.compositionsRef = exports.CompositionManager = void 0;
27
27
  const jsx_runtime_1 = require("react/jsx-runtime");
28
28
  const react_1 = __importStar(require("react"));
29
+ const shared_audio_tags_js_1 = require("./audio/shared-audio-tags.js");
29
30
  exports.CompositionManager = (0, react_1.createContext)({
30
31
  compositions: [],
31
32
  registerComposition: () => undefined,
@@ -45,7 +46,8 @@ exports.CompositionManager = (0, react_1.createContext)({
45
46
  currentCompositionMetadata: null,
46
47
  });
47
48
  exports.compositionsRef = react_1.default.createRef();
48
- const CompositionManagerProvider = ({ children }) => {
49
+ const CompositionManagerProvider = ({ children, numberOfAudioTags }) => {
50
+ var _a;
49
51
  // Wontfix, expected to have
50
52
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
53
  const [compositions, setCompositions] = (0, react_1.useState)([]);
@@ -159,6 +161,7 @@ const CompositionManagerProvider = ({ children }) => {
159
161
  unregisterFolder,
160
162
  currentCompositionMetadata,
161
163
  ]);
162
- return ((0, jsx_runtime_1.jsx)(exports.CompositionManager.Provider, { value: contextValue, children: children }));
164
+ const composition = (_a = compositions.find((c) => c.id === currentComposition)) === null || _a === void 0 ? void 0 : _a.component;
165
+ return ((0, jsx_runtime_1.jsx)(exports.CompositionManager.Provider, { value: contextValue, children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioContextProvider, { numberOfAudioTags: numberOfAudioTags, component: composition !== null && composition !== void 0 ? composition : null, children: children }) }));
163
166
  };
164
167
  exports.CompositionManagerProvider = CompositionManagerProvider;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RemotionRoot = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const shared_audio_tags_js_1 = require("./audio/shared-audio-tags.js");
7
6
  const CompositionManager_js_1 = require("./CompositionManager.js");
8
7
  const delay_render_js_1 = require("./delay-render.js");
9
8
  const NativeLayers_js_1 = require("./NativeLayers.js");
@@ -67,10 +66,6 @@ const RemotionRoot = ({ children, numberOfAudioTags }) => {
67
66
  }
68
67
  }
69
68
  }, []);
70
- return ((0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(timeline_position_state_js_1.TimelineContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(timeline_position_state_js_1.SetTimelineContext.Provider, { value: setTimelineContextValue, children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(NativeLayers_js_1.NativeLayersProvider, { children: (0, jsx_runtime_1.jsx)(CompositionManager_js_1.CompositionManagerProvider, { children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioContextProvider
71
- // In the preview, which is mostly played on Desktop, we opt out of the autoplay policy fix as described in https://github.com/remotion-dev/remotion/pull/554, as it mostly applies to mobile.
72
- , {
73
- // In the preview, which is mostly played on Desktop, we opt out of the autoplay policy fix as described in https://github.com/remotion-dev/remotion/pull/554, as it mostly applies to mobile.
74
- numberOfAudioTags: numberOfAudioTags, children: children }) }) }) }) }) }) }) }));
69
+ return ((0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(timeline_position_state_js_1.TimelineContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(timeline_position_state_js_1.SetTimelineContext.Provider, { value: setTimelineContextValue, children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(NativeLayers_js_1.NativeLayersProvider, { children: (0, jsx_runtime_1.jsx)(CompositionManager_js_1.CompositionManagerProvider, { numberOfAudioTags: numberOfAudioTags, children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: children }) }) }) }) }) }) }));
75
70
  };
76
71
  exports.RemotionRoot = RemotionRoot;
@@ -9,4 +9,4 @@ export declare const Audio: React.ForwardRefExoticComponent<Pick<Omit<React.Deta
9
9
  playbackRate?: number | undefined;
10
10
  acceptableTimeShiftInSeconds?: number | undefined;
11
11
  allowAmplificationDuringRender?: boolean | undefined;
12
- } & RemotionMainAudioProps, "id" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "lang" | "placeholder" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "src" | "volume" | "playbackRate" | "allowAmplificationDuringRender" | "controlsList" | "crossOrigin" | "loop" | "mediaGroup" | "muted" | "playsInline" | "preload" | "acceptableTimeShiftInSeconds" | keyof RemotionMainAudioProps> & React.RefAttributes<HTMLAudioElement>>;
12
+ } & RemotionMainAudioProps, "id" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "lang" | "placeholder" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "volume" | "allowAmplificationDuringRender" | "controlsList" | "crossOrigin" | "loop" | "mediaGroup" | "muted" | "playsInline" | "preload" | "src" | "playbackRate" | "acceptableTimeShiftInSeconds" | keyof RemotionMainAudioProps> & React.RefAttributes<HTMLAudioElement>>;
@@ -1,3 +1,4 @@
1
+ import type { ComponentType, LazyExoticComponent } from 'react';
1
2
  import React from 'react';
2
3
  import type { RemotionAudioProps } from './props.js';
3
4
  /**
@@ -32,6 +33,7 @@ export declare const SharedAudioContext: React.Context<SharedContext | null>;
32
33
  export declare const SharedAudioContextProvider: React.FC<{
33
34
  numberOfAudioTags: number;
34
35
  children: React.ReactNode;
36
+ component: LazyExoticComponent<ComponentType<unknown>> | null;
35
37
  }>;
36
38
  export declare const useSharedAudio: (aud: RemotionAudioProps, audioId: string) => AudioElem;
37
39
  export {};
@@ -59,7 +59,7 @@ const didPropChange = (key, newProp, prevProp) => {
59
59
  return true;
60
60
  };
61
61
  exports.SharedAudioContext = (0, react_1.createContext)(null);
62
- const SharedAudioContextProvider = ({ children, numberOfAudioTags }) => {
62
+ const SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) => {
63
63
  const audios = (0, react_1.useRef)([]);
64
64
  const [initialNumberOfAudioTags] = (0, react_1.useState)(numberOfAudioTags);
65
65
  if (numberOfAudioTags !== initialNumberOfAudioTags) {
@@ -176,6 +176,22 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags }) => {
176
176
  unregisterAudio,
177
177
  updateAudio,
178
178
  ]);
179
+ // Fixing a bug: In React, if a component is unmounted using useInsertionEffect, then
180
+ // the cleanup function does sometimes not work properly. That is why when we
181
+ // are changing the composition, we reset the audio state.
182
+ // TODO: Possibly this does not save the problem completely, since the
183
+ // if an audio tag that is inside a sequence will also not be removed
184
+ // from the shared audios.
185
+ const resetAudio = (0, react_1.useCallback)(() => {
186
+ takenAudios.current = new Array(numberOfAudioTags).fill(false);
187
+ audios.current = [];
188
+ rerenderAudios();
189
+ }, [numberOfAudioTags, rerenderAudios]);
190
+ (0, react_1.useEffect)(() => {
191
+ return () => {
192
+ resetAudio();
193
+ };
194
+ }, [component, resetAudio]);
179
195
  return ((0, jsx_runtime_1.jsxs)(exports.SharedAudioContext.Provider, { value: value, children: [refs.map(({ id, ref }) => {
180
196
  return (0, jsx_runtime_1.jsx)("audio", { ref: ref, src: EMPTY_AUDIO }, id);
181
197
  }), children] }));
@@ -71,6 +71,7 @@ export declare const Internals: {
71
71
  SharedAudioContextProvider: import("react").FC<{
72
72
  numberOfAudioTags: number;
73
73
  children: import("react").ReactNode;
74
+ component: import("react").LazyExoticComponent<import("react").ComponentType<unknown>> | null;
74
75
  }>;
75
76
  invalidCompositionErrorMessage: string;
76
77
  isCompositionIdValid: (id: string) => RegExpMatchArray | null;
@@ -1 +1 @@
1
- export declare const VERSION = "3.3.83";
1
+ export declare const VERSION = "3.3.84";
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // Automatically generated on publish
5
- exports.VERSION = '3.3.83';
5
+ exports.VERSION = '3.3.84';
@@ -1,5 +1,5 @@
1
- import React, { createContext, useState, useMemo, useLayoutEffect, useContext, useEffect, forwardRef, useRef, useCallback, useImperativeHandle, Children, isValidElement, useReducer, createRef, Suspense } from 'react';
2
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
1
+ import React, { createContext, useState, useMemo, useLayoutEffect, useContext, useEffect, forwardRef, useRef, createRef, useCallback, useImperativeHandle, Children, isValidElement, useReducer, Suspense } from 'react';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import { createPortal } from 'react-dom';
4
4
 
5
5
  const NativeLayersContext = createContext({
@@ -58,7 +58,7 @@ function truthy(value) {
58
58
  }
59
59
 
60
60
  // Automatically generated on publish
61
- const VERSION = '3.3.83';
61
+ const VERSION = '3.3.84';
62
62
 
63
63
  const checkMultipleRemotionVersions = () => {
64
64
  if (typeof globalThis === 'undefined') {
@@ -160,6 +160,218 @@ const useRemotionEnvironment = () => {
160
160
  return getRemotionEnvironment();
161
161
  };
162
162
 
163
+ const EMPTY_AUDIO = 'data:audio/mp3;base64,/+MYxAAJcAV8AAgAABn//////+/gQ5BAMA+D4Pg+BAQBAEAwD4Pg+D4EBAEAQDAPg++hYBH///hUFQVBUFREDQNHmf///////+MYxBUGkAGIMAAAAP/29Xt6lUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxDUAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV';
164
+ const compareProps = (obj1, obj2) => {
165
+ const keysA = Object.keys(obj1).sort();
166
+ const keysB = Object.keys(obj2).sort();
167
+ if (keysA.length !== keysB.length) {
168
+ return false;
169
+ }
170
+ for (let i = 0; i < keysA.length; i++) {
171
+ // Not the same keys
172
+ if (keysA[i] !== keysB[i]) {
173
+ return false;
174
+ }
175
+ // Not the same values
176
+ if (obj1[keysA[i]] !== obj2[keysB[i]]) {
177
+ return false;
178
+ }
179
+ }
180
+ return true;
181
+ };
182
+ const didPropChange = (key, newProp, prevProp) => {
183
+ // /music.mp3 and http://localhost:3000/music.mp3 are the same
184
+ if (key === 'src' &&
185
+ !prevProp.startsWith('data:') &&
186
+ !newProp.startsWith('data:')) {
187
+ return (new URL(prevProp, window.location.origin).toString() !==
188
+ new URL(newProp, window.location.origin).toString());
189
+ }
190
+ if (prevProp === newProp) {
191
+ return false;
192
+ }
193
+ return true;
194
+ };
195
+ const SharedAudioContext = createContext(null);
196
+ const SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) => {
197
+ const audios = useRef([]);
198
+ const [initialNumberOfAudioTags] = useState(numberOfAudioTags);
199
+ if (numberOfAudioTags !== initialNumberOfAudioTags) {
200
+ throw new Error('The number of shared audio tags has changed dynamically. Once you have set this property, you cannot change it afterwards.');
201
+ }
202
+ const refs = useMemo(() => {
203
+ return new Array(numberOfAudioTags).fill(true).map(() => {
204
+ return { id: Math.random(), ref: createRef() };
205
+ });
206
+ }, [numberOfAudioTags]);
207
+ const takenAudios = useRef(new Array(numberOfAudioTags).fill(false));
208
+ const rerenderAudios = useCallback(() => {
209
+ refs.forEach(({ ref, id }) => {
210
+ var _a;
211
+ const data = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.find((a) => a.id === id);
212
+ const { current } = ref;
213
+ if (!current) {
214
+ // Whole player has been unmounted, the refs don't exist anymore.
215
+ // It is not an error anymore though
216
+ return;
217
+ }
218
+ if (data === undefined) {
219
+ current.src = EMPTY_AUDIO;
220
+ return;
221
+ }
222
+ if (!data) {
223
+ throw new TypeError('Expected audio data to be there');
224
+ }
225
+ Object.keys(data.props).forEach((key) => {
226
+ // @ts-expect-error
227
+ if (didPropChange(key, data.props[key], current[key])) {
228
+ // @ts-expect-error
229
+ current[key] = data.props[key];
230
+ }
231
+ });
232
+ });
233
+ }, [refs]);
234
+ const registerAudio = useCallback((aud, audioId) => {
235
+ var _a, _b;
236
+ const found = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.find((a) => a.audioId === audioId);
237
+ if (found) {
238
+ return found;
239
+ }
240
+ const firstFreeAudio = takenAudios.current.findIndex((a) => a === false);
241
+ if (firstFreeAudio === -1) {
242
+ throw new Error(`Tried to simultaneously mount ${numberOfAudioTags + 1} <Audio /> tags at the same time. With the current settings, the maximum amount of <Audio /> tags is limited to ${numberOfAudioTags} at the same time. Remotion pre-mounts silent audio tags to help avoid browser autoplay restrictions. See https://remotion.dev/docs/player/autoplay#use-the-numberofsharedaudiotags-property for more information on how to increase this limit.`);
243
+ }
244
+ const { id, ref } = refs[firstFreeAudio];
245
+ const cloned = [...takenAudios.current];
246
+ cloned[firstFreeAudio] = id;
247
+ takenAudios.current = cloned;
248
+ const newElem = {
249
+ props: aud,
250
+ id,
251
+ el: ref,
252
+ audioId,
253
+ };
254
+ (_b = audios.current) === null || _b === void 0 ? void 0 : _b.push(newElem);
255
+ rerenderAudios();
256
+ return newElem;
257
+ }, [numberOfAudioTags, refs, rerenderAudios]);
258
+ const unregisterAudio = useCallback((id) => {
259
+ var _a;
260
+ const cloned = [...takenAudios.current];
261
+ const index = refs.findIndex((r) => r.id === id);
262
+ if (index === -1) {
263
+ throw new TypeError('Error occured in ');
264
+ }
265
+ cloned[index] = false;
266
+ takenAudios.current = cloned;
267
+ audios.current = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.filter((a) => a.id !== id);
268
+ rerenderAudios();
269
+ }, [refs, rerenderAudios]);
270
+ const updateAudio = useCallback(({ aud, audioId, id, }) => {
271
+ var _a;
272
+ let changed = false;
273
+ audios.current = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.map((prevA) => {
274
+ if (prevA.id === id) {
275
+ const isTheSame = compareProps(aud, prevA.props);
276
+ if (isTheSame) {
277
+ return prevA;
278
+ }
279
+ changed = true;
280
+ return {
281
+ ...prevA,
282
+ props: aud,
283
+ audioId,
284
+ };
285
+ }
286
+ return prevA;
287
+ });
288
+ if (changed) {
289
+ rerenderAudios();
290
+ }
291
+ }, [rerenderAudios]);
292
+ const playAllAudios = useCallback(() => {
293
+ refs.forEach((ref) => {
294
+ var _a;
295
+ (_a = ref.ref.current) === null || _a === void 0 ? void 0 : _a.play();
296
+ });
297
+ }, [refs]);
298
+ const value = useMemo(() => {
299
+ return {
300
+ registerAudio,
301
+ unregisterAudio,
302
+ updateAudio,
303
+ playAllAudios,
304
+ numberOfAudioTags,
305
+ };
306
+ }, [
307
+ numberOfAudioTags,
308
+ playAllAudios,
309
+ registerAudio,
310
+ unregisterAudio,
311
+ updateAudio,
312
+ ]);
313
+ // Fixing a bug: In React, if a component is unmounted using useInsertionEffect, then
314
+ // the cleanup function does sometimes not work properly. That is why when we
315
+ // are changing the composition, we reset the audio state.
316
+ // TODO: Possibly this does not save the problem completely, since the
317
+ // if an audio tag that is inside a sequence will also not be removed
318
+ // from the shared audios.
319
+ const resetAudio = useCallback(() => {
320
+ takenAudios.current = new Array(numberOfAudioTags).fill(false);
321
+ audios.current = [];
322
+ rerenderAudios();
323
+ }, [numberOfAudioTags, rerenderAudios]);
324
+ useEffect(() => {
325
+ return () => {
326
+ resetAudio();
327
+ };
328
+ }, [component, resetAudio]);
329
+ return (jsxs(SharedAudioContext.Provider, { value: value, children: [refs.map(({ id, ref }) => {
330
+ return jsx("audio", { ref: ref, src: EMPTY_AUDIO }, id);
331
+ }), children] }));
332
+ };
333
+ const useSharedAudio = (aud, audioId) => {
334
+ var _a;
335
+ const ctx = useContext(SharedAudioContext);
336
+ /**
337
+ * We work around this in React 18 so an audio tag will only register itself once
338
+ */
339
+ const [elem] = useState(() => {
340
+ if (ctx && ctx.numberOfAudioTags > 0) {
341
+ return ctx.registerAudio(aud, audioId);
342
+ }
343
+ return {
344
+ el: React.createRef(),
345
+ id: Math.random(),
346
+ props: aud,
347
+ audioId,
348
+ };
349
+ });
350
+ /**
351
+ * Effects in React 18 fire twice, and we are looking for a way to only fire it once.
352
+ * - useInsertionEffect only fires once. If it's available we are in React 18.
353
+ * - useLayoutEffect only fires once in React 17.
354
+ *
355
+ * Need to import it from React to fix React 17 ESM support.
356
+ */
357
+ const effectToUse = (_a = React.useInsertionEffect) !== null && _a !== void 0 ? _a : React.useLayoutEffect;
358
+ if (typeof document !== 'undefined') {
359
+ effectToUse(() => {
360
+ if (ctx && ctx.numberOfAudioTags > 0) {
361
+ ctx.updateAudio({ id: elem.id, aud, audioId });
362
+ }
363
+ }, [aud, ctx, elem.id, audioId]);
364
+ effectToUse(() => {
365
+ return () => {
366
+ if (ctx && ctx.numberOfAudioTags > 0) {
367
+ ctx.unregisterAudio(elem.id);
368
+ }
369
+ };
370
+ }, [ctx, elem.id]);
371
+ }
372
+ return elem;
373
+ };
374
+
163
375
  const CompositionManager = createContext({
164
376
  compositions: [],
165
377
  registerComposition: () => undefined,
@@ -179,7 +391,8 @@ const CompositionManager = createContext({
179
391
  currentCompositionMetadata: null,
180
392
  });
181
393
  const compositionsRef = React.createRef();
182
- const CompositionManagerProvider = ({ children }) => {
394
+ const CompositionManagerProvider = ({ children, numberOfAudioTags }) => {
395
+ var _a;
183
396
  // Wontfix, expected to have
184
397
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
185
398
  const [compositions, setCompositions] = useState([]);
@@ -293,7 +506,8 @@ const CompositionManagerProvider = ({ children }) => {
293
506
  unregisterFolder,
294
507
  currentCompositionMetadata,
295
508
  ]);
296
- return (jsx(CompositionManager.Provider, { value: contextValue, children: children }));
509
+ const composition = (_a = compositions.find((c) => c.id === currentComposition)) === null || _a === void 0 ? void 0 : _a.component;
510
+ return (jsx(CompositionManager.Provider, { value: contextValue, children: jsx(SharedAudioContextProvider, { numberOfAudioTags: numberOfAudioTags, component: composition !== null && composition !== void 0 ? composition : null, children: children }) }));
297
511
  };
298
512
 
299
513
  const HIDDEN_NAMES = ['__WEBPACK_DEFAULT_EXPORT__'];
@@ -1385,202 +1599,6 @@ const useMediaMutedState = () => {
1385
1599
  }, [mediaMuted, setMediaMuted]);
1386
1600
  };
1387
1601
 
1388
- const EMPTY_AUDIO = 'data:audio/mp3;base64,/+MYxAAJcAV8AAgAABn//////+/gQ5BAMA+D4Pg+BAQBAEAwD4Pg+D4EBAEAQDAPg++hYBH///hUFQVBUFREDQNHmf///////+MYxBUGkAGIMAAAAP/29Xt6lUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxDUAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV';
1389
- const compareProps = (obj1, obj2) => {
1390
- const keysA = Object.keys(obj1).sort();
1391
- const keysB = Object.keys(obj2).sort();
1392
- if (keysA.length !== keysB.length) {
1393
- return false;
1394
- }
1395
- for (let i = 0; i < keysA.length; i++) {
1396
- // Not the same keys
1397
- if (keysA[i] !== keysB[i]) {
1398
- return false;
1399
- }
1400
- // Not the same values
1401
- if (obj1[keysA[i]] !== obj2[keysB[i]]) {
1402
- return false;
1403
- }
1404
- }
1405
- return true;
1406
- };
1407
- const didPropChange = (key, newProp, prevProp) => {
1408
- // /music.mp3 and http://localhost:3000/music.mp3 are the same
1409
- if (key === 'src' &&
1410
- !prevProp.startsWith('data:') &&
1411
- !newProp.startsWith('data:')) {
1412
- return (new URL(prevProp, window.location.origin).toString() !==
1413
- new URL(newProp, window.location.origin).toString());
1414
- }
1415
- if (prevProp === newProp) {
1416
- return false;
1417
- }
1418
- return true;
1419
- };
1420
- const SharedAudioContext = createContext(null);
1421
- const SharedAudioContextProvider = ({ children, numberOfAudioTags }) => {
1422
- const audios = useRef([]);
1423
- const [initialNumberOfAudioTags] = useState(numberOfAudioTags);
1424
- if (numberOfAudioTags !== initialNumberOfAudioTags) {
1425
- throw new Error('The number of shared audio tags has changed dynamically. Once you have set this property, you cannot change it afterwards.');
1426
- }
1427
- const refs = useMemo(() => {
1428
- return new Array(numberOfAudioTags).fill(true).map(() => {
1429
- return { id: Math.random(), ref: createRef() };
1430
- });
1431
- }, [numberOfAudioTags]);
1432
- const takenAudios = useRef(new Array(numberOfAudioTags).fill(false));
1433
- const rerenderAudios = useCallback(() => {
1434
- refs.forEach(({ ref, id }) => {
1435
- var _a;
1436
- const data = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.find((a) => a.id === id);
1437
- const { current } = ref;
1438
- if (!current) {
1439
- // Whole player has been unmounted, the refs don't exist anymore.
1440
- // It is not an error anymore though
1441
- return;
1442
- }
1443
- if (data === undefined) {
1444
- current.src = EMPTY_AUDIO;
1445
- return;
1446
- }
1447
- if (!data) {
1448
- throw new TypeError('Expected audio data to be there');
1449
- }
1450
- Object.keys(data.props).forEach((key) => {
1451
- // @ts-expect-error
1452
- if (didPropChange(key, data.props[key], current[key])) {
1453
- // @ts-expect-error
1454
- current[key] = data.props[key];
1455
- }
1456
- });
1457
- });
1458
- }, [refs]);
1459
- const registerAudio = useCallback((aud, audioId) => {
1460
- var _a, _b;
1461
- const found = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.find((a) => a.audioId === audioId);
1462
- if (found) {
1463
- return found;
1464
- }
1465
- const firstFreeAudio = takenAudios.current.findIndex((a) => a === false);
1466
- if (firstFreeAudio === -1) {
1467
- throw new Error(`Tried to simultaneously mount ${numberOfAudioTags + 1} <Audio /> tags at the same time. With the current settings, the maximum amount of <Audio /> tags is limited to ${numberOfAudioTags} at the same time. Remotion pre-mounts silent audio tags to help avoid browser autoplay restrictions. See https://remotion.dev/docs/player/autoplay#use-the-numberofsharedaudiotags-property for more information on how to increase this limit.`);
1468
- }
1469
- const { id, ref } = refs[firstFreeAudio];
1470
- const cloned = [...takenAudios.current];
1471
- cloned[firstFreeAudio] = id;
1472
- takenAudios.current = cloned;
1473
- const newElem = {
1474
- props: aud,
1475
- id,
1476
- el: ref,
1477
- audioId,
1478
- };
1479
- (_b = audios.current) === null || _b === void 0 ? void 0 : _b.push(newElem);
1480
- rerenderAudios();
1481
- return newElem;
1482
- }, [numberOfAudioTags, refs, rerenderAudios]);
1483
- const unregisterAudio = useCallback((id) => {
1484
- var _a;
1485
- const cloned = [...takenAudios.current];
1486
- const index = refs.findIndex((r) => r.id === id);
1487
- if (index === -1) {
1488
- throw new TypeError('Error occured in ');
1489
- }
1490
- cloned[index] = false;
1491
- takenAudios.current = cloned;
1492
- audios.current = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.filter((a) => a.id !== id);
1493
- rerenderAudios();
1494
- }, [refs, rerenderAudios]);
1495
- const updateAudio = useCallback(({ aud, audioId, id, }) => {
1496
- var _a;
1497
- let changed = false;
1498
- audios.current = (_a = audios.current) === null || _a === void 0 ? void 0 : _a.map((prevA) => {
1499
- if (prevA.id === id) {
1500
- const isTheSame = compareProps(aud, prevA.props);
1501
- if (isTheSame) {
1502
- return prevA;
1503
- }
1504
- changed = true;
1505
- return {
1506
- ...prevA,
1507
- props: aud,
1508
- audioId,
1509
- };
1510
- }
1511
- return prevA;
1512
- });
1513
- if (changed) {
1514
- rerenderAudios();
1515
- }
1516
- }, [rerenderAudios]);
1517
- const playAllAudios = useCallback(() => {
1518
- refs.forEach((ref) => {
1519
- var _a;
1520
- (_a = ref.ref.current) === null || _a === void 0 ? void 0 : _a.play();
1521
- });
1522
- }, [refs]);
1523
- const value = useMemo(() => {
1524
- return {
1525
- registerAudio,
1526
- unregisterAudio,
1527
- updateAudio,
1528
- playAllAudios,
1529
- numberOfAudioTags,
1530
- };
1531
- }, [
1532
- numberOfAudioTags,
1533
- playAllAudios,
1534
- registerAudio,
1535
- unregisterAudio,
1536
- updateAudio,
1537
- ]);
1538
- return (jsxs(SharedAudioContext.Provider, { value: value, children: [refs.map(({ id, ref }) => {
1539
- return jsx("audio", { ref: ref, src: EMPTY_AUDIO }, id);
1540
- }), children] }));
1541
- };
1542
- const useSharedAudio = (aud, audioId) => {
1543
- var _a;
1544
- const ctx = useContext(SharedAudioContext);
1545
- /**
1546
- * We work around this in React 18 so an audio tag will only register itself once
1547
- */
1548
- const [elem] = useState(() => {
1549
- if (ctx && ctx.numberOfAudioTags > 0) {
1550
- return ctx.registerAudio(aud, audioId);
1551
- }
1552
- return {
1553
- el: React.createRef(),
1554
- id: Math.random(),
1555
- props: aud,
1556
- audioId,
1557
- };
1558
- });
1559
- /**
1560
- * Effects in React 18 fire twice, and we are looking for a way to only fire it once.
1561
- * - useInsertionEffect only fires once. If it's available we are in React 18.
1562
- * - useLayoutEffect only fires once in React 17.
1563
- *
1564
- * Need to import it from React to fix React 17 ESM support.
1565
- */
1566
- const effectToUse = (_a = React.useInsertionEffect) !== null && _a !== void 0 ? _a : React.useLayoutEffect;
1567
- if (typeof document !== 'undefined') {
1568
- effectToUse(() => {
1569
- if (ctx && ctx.numberOfAudioTags > 0) {
1570
- ctx.updateAudio({ id: elem.id, aud, audioId });
1571
- }
1572
- }, [aud, ctx, elem.id, audioId]);
1573
- effectToUse(() => {
1574
- return () => {
1575
- if (ctx && ctx.numberOfAudioTags > 0) {
1576
- ctx.unregisterAudio(elem.id);
1577
- }
1578
- };
1579
- }, [ctx, elem.id]);
1580
- }
1581
- return elem;
1582
- };
1583
-
1584
1602
  const AudioForDevelopmentForwardRefFunction = (props, ref) => {
1585
1603
  const [initialShouldPreMountAudioElements] = useState(props.shouldPreMountAudioTags);
1586
1604
  if (props.shouldPreMountAudioTags !== initialShouldPreMountAudioElements) {
@@ -2170,11 +2188,7 @@ const RemotionRoot = ({ children, numberOfAudioTags }) => {
2170
2188
  }
2171
2189
  }
2172
2190
  }, []);
2173
- return (jsx(NonceContext.Provider, { value: nonceContext, children: jsx(TimelineContext.Provider, { value: timelineContextValue, children: jsx(SetTimelineContext.Provider, { value: setTimelineContextValue, children: jsx(PrefetchProvider, { children: jsx(NativeLayersProvider, { children: jsx(CompositionManagerProvider, { children: jsx(DurationsContextProvider, { children: jsx(SharedAudioContextProvider
2174
- // In the preview, which is mostly played on Desktop, we opt out of the autoplay policy fix as described in https://github.com/remotion-dev/remotion/pull/554, as it mostly applies to mobile.
2175
- , {
2176
- // In the preview, which is mostly played on Desktop, we opt out of the autoplay policy fix as described in https://github.com/remotion-dev/remotion/pull/554, as it mostly applies to mobile.
2177
- numberOfAudioTags: numberOfAudioTags, children: children }) }) }) }) }) }) }) }));
2191
+ return (jsx(NonceContext.Provider, { value: nonceContext, children: jsx(TimelineContext.Provider, { value: timelineContextValue, children: jsx(SetTimelineContext.Provider, { value: setTimelineContextValue, children: jsx(PrefetchProvider, { children: jsx(NativeLayersProvider, { children: jsx(CompositionManagerProvider, { numberOfAudioTags: numberOfAudioTags, children: jsx(DurationsContextProvider, { children: children }) }) }) }) }) }) }));
2178
2192
  };
2179
2193
 
2180
2194
  const ENV_VARIABLES_ENV_NAME = 'ENV_VARIABLES';
@@ -1,4 +1,4 @@
1
1
  // Automatically generated on publish
2
- const VERSION = '3.3.83';
2
+ const VERSION = '3.3.84';
3
3
 
4
4
  export { VERSION };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remotion",
3
- "version": "3.3.83",
3
+ "version": "3.3.84",
4
4
  "description": "Render videos in React",
5
5
  "main": "dist/cjs/index.js",
6
6
  "types": "dist/cjs/index.d.ts",