remotion 4.0.431 → 4.0.433

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +0 -1
  2. package/dist/cjs/Composition.js +1 -1
  3. package/dist/cjs/CompositionManager.d.ts +3 -2
  4. package/dist/cjs/CompositionManagerContext.d.ts +2 -1
  5. package/dist/cjs/CompositionManagerProvider.js +3 -5
  6. package/dist/cjs/Folder.d.ts +2 -0
  7. package/dist/cjs/Folder.js +11 -2
  8. package/dist/cjs/Img.js +14 -5
  9. package/dist/cjs/RemotionRoot.d.ts +1 -1
  10. package/dist/cjs/RemotionRoot.js +3 -4
  11. package/dist/cjs/Sequence.js +6 -8
  12. package/dist/cjs/SequenceManager.d.ts +10 -5
  13. package/dist/cjs/SequenceManager.js +50 -18
  14. package/dist/cjs/TimelineContext.d.ts +2 -1
  15. package/dist/cjs/TimelineContext.js +4 -15
  16. package/dist/cjs/audio/shared-audio-tags.d.ts +20 -1
  17. package/dist/cjs/audio/shared-audio-tags.js +73 -0
  18. package/dist/cjs/freeze.js +2 -1
  19. package/dist/cjs/get-effective-visual-mode-value.d.ts +8 -0
  20. package/dist/cjs/get-effective-visual-mode-value.js +20 -0
  21. package/dist/cjs/index.d.ts +1 -0
  22. package/dist/cjs/internals.d.ts +29 -6
  23. package/dist/cjs/internals.js +10 -1
  24. package/dist/cjs/nonce.d.ts +7 -1
  25. package/dist/cjs/nonce.js +30 -10
  26. package/dist/cjs/sequence-field-schema.d.ts +16 -3
  27. package/dist/cjs/sequence-stack-traces.d.ts +0 -4
  28. package/dist/cjs/sequence-stack-traces.js +1 -4
  29. package/dist/cjs/timeline-position-state.d.ts +3 -0
  30. package/dist/cjs/timeline-position-state.js +23 -4
  31. package/dist/cjs/use-media-in-timeline.d.ts +1 -1
  32. package/dist/cjs/use-media-in-timeline.js +3 -3
  33. package/dist/cjs/use-media-playback.js +1 -2
  34. package/dist/cjs/use-media-tag.js +2 -2
  35. package/dist/cjs/use-schema.d.ts +9 -2
  36. package/dist/cjs/use-schema.js +44 -14
  37. package/dist/cjs/use-sequence-control-override.js +1 -1
  38. package/dist/cjs/version.d.ts +1 -1
  39. package/dist/cjs/version.js +1 -1
  40. package/dist/cjs/wrap-in-schema.d.ts +6 -0
  41. package/dist/cjs/wrap-in-schema.js +114 -0
  42. package/dist/cjs/wrap-remotion-context.d.ts +1 -1
  43. package/dist/esm/index.mjs +1310 -1050
  44. package/dist/esm/version.mjs +1 -1
  45. package/package.json +2 -2
  46. package/dist/cjs/jsx-call-site-context.d.ts +0 -5
  47. package/dist/cjs/jsx-call-site-context.js +0 -5
package/README.md CHANGED
@@ -10,7 +10,6 @@
10
10
  [![Discord Shield](https://img.shields.io/discord/809501355504959528?color=000000&label=Discord&logo=fdgssdf)](https://remotion.dev/discord)
11
11
  [![NPM Version](https://img.shields.io/npm/v/remotion.svg?style=flat&color=black)](https://www.npmjs.org/package/remotion)
12
12
  [![NPM Downloads](https://img.shields.io/npm/dm/remotion.svg?style=flat&color=black&label=Downloads)](https://npmcharts.com/compare/remotion?minimal=true)
13
- [![Open Bounties](https://img.shields.io/endpoint?url=https%3A%2F%2Fconsole.algora.io%2Fapi%2Fshields%2Fremotion%2Fbounties%3Fstatus%3Dopen&style=flat&color=black&labelColor=grey&label=Open+Bounties)](https://github.com/remotion-dev/remotion/issues?q=is%3Aopen+label%3A%22%F0%9F%92%8E+Bounty%22+sort%3Aupdated-desc)
14
13
  <a href="https://twitter.com/remotion"><img src="https://img.shields.io/twitter/follow/remotion?label=Twitter&color=black" alt="Twitter"></a>
15
14
 
16
15
  Remotion is a framework for **creating videos programmatically using React.**
@@ -69,7 +69,7 @@ const InnerComposition = ({ width, height, fps, durationInFrames, id, defaultPro
69
69
  folderName,
70
70
  component: lazy,
71
71
  defaultProps: (0, input_props_serialization_js_1.serializeThenDeserializeInStudio)((defaultProps !== null && defaultProps !== void 0 ? defaultProps : {})),
72
- nonce,
72
+ nonce: nonce.get(),
73
73
  parentFolderName: parentName,
74
74
  schema: schema !== null && schema !== void 0 ? schema : null,
75
75
  calculateMetadata: (_a = compProps.calculateMetadata) !== null && _a !== void 0 ? _a : null,
@@ -3,6 +3,7 @@ import React from 'react';
3
3
  import type { AnyZodObject } from './any-zod-type.js';
4
4
  import type { CalculateMetadataFunction } from './Composition.js';
5
5
  import type { DownloadBehavior } from './download-behavior.js';
6
+ import type { NonceHistory } from './nonce.js';
6
7
  import type { InferProps, PropsIfHasProps } from './props-if-has-props.js';
7
8
  import type { SequenceSchema } from './sequence-field-schema.js';
8
9
  export type TComposition<Schema extends AnyZodObject, Props extends Record<string, unknown>> = {
@@ -14,7 +15,7 @@ export type TComposition<Schema extends AnyZodObject, Props extends Record<strin
14
15
  folderName: string | null;
15
16
  parentFolderName: string | null;
16
17
  component: LazyExoticComponent<ComponentType<Props>> | ComponentType<Props>;
17
- nonce: number;
18
+ nonce: NonceHistory;
18
19
  schema: Schema | null;
19
20
  calculateMetadata: CalculateMetadataFunction<InferProps<Schema, Props>> | null;
20
21
  } & PropsIfHasProps<Schema, Props>;
@@ -57,7 +58,7 @@ export type TSequence = {
57
58
  parent: string | null;
58
59
  rootId: string;
59
60
  showInTimeline: boolean;
60
- nonce: number;
61
+ nonce: NonceHistory;
61
62
  loopDisplay: LoopDisplay | undefined;
62
63
  stack: string | null;
63
64
  premountDisplay: number | null;
@@ -2,6 +2,7 @@ import type React from 'react';
2
2
  import type { AnyZodObject } from './any-zod-type.js';
3
3
  import type { AnyComposition, TComposition } from './CompositionManager.js';
4
4
  import type { TFolder } from './Folder.js';
5
+ import type { NonceHistory } from './nonce.js';
5
6
  import type { VideoConfig } from './video-config.js';
6
7
  export type BaseMetadata = Pick<VideoConfig, 'durationInFrames' | 'fps' | 'props' | 'height' | 'width' | 'defaultCodec' | 'defaultOutName' | 'defaultVideoImageFormat' | 'defaultPixelFormat' | 'defaultProResProfile'>;
7
8
  export type CanvasContent = {
@@ -24,7 +25,7 @@ export type CanvasContent = {
24
25
  export type CompositionManagerSetters = {
25
26
  registerComposition: <Schema extends AnyZodObject, Props extends Record<string, unknown>>(comp: TComposition<Schema, Props>) => void;
26
27
  unregisterComposition: (name: string) => void;
27
- registerFolder: (name: string, parent: string | null) => void;
28
+ registerFolder: (name: string, parent: string | null, nonce: NonceHistory) => void;
28
29
  unregisterFolder: (name: string, parent: string | null) => void;
29
30
  setCanvasContent: React.Dispatch<React.SetStateAction<CanvasContent | null>>;
30
31
  updateCompositionDefaultProps: (id: string, newDefaultProps: Record<string, unknown>) => void;
@@ -23,10 +23,7 @@ const CompositionManagerProvider = ({ children, onlyRenderComposition, currentCo
23
23
  if (comps.find((c) => c.id === comp.id)) {
24
24
  throw new Error(`Multiple composition with id ${comp.id} are registered.`);
25
25
  }
26
- const value = [...comps, comp]
27
- .slice()
28
- .sort((a, b) => a.nonce - b.nonce);
29
- return value;
26
+ return [...comps, comp];
30
27
  });
31
28
  }, [updateCompositions]);
32
29
  const unregisterComposition = (0, react_1.useCallback)((id) => {
@@ -34,13 +31,14 @@ const CompositionManagerProvider = ({ children, onlyRenderComposition, currentCo
34
31
  return comps.filter((c) => c.id !== id);
35
32
  });
36
33
  }, []);
37
- const registerFolder = (0, react_1.useCallback)((name, parent) => {
34
+ const registerFolder = (0, react_1.useCallback)((name, parent, nonce) => {
38
35
  setFolders((prevFolders) => {
39
36
  return [
40
37
  ...prevFolders,
41
38
  {
42
39
  name,
43
40
  parent,
41
+ nonce,
44
42
  },
45
43
  ];
46
44
  });
@@ -1,7 +1,9 @@
1
1
  import type { FC } from 'react';
2
+ import type { NonceHistory } from './nonce.js';
2
3
  export type TFolder = {
3
4
  name: string;
4
5
  parent: string | null;
6
+ nonce: NonceHistory;
5
7
  };
6
8
  type FolderContextType = {
7
9
  folderName: string | null;
@@ -4,6 +4,7 @@ exports.Folder = exports.FolderContext = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const CompositionManagerContext_js_1 = require("./CompositionManagerContext.js");
7
+ const nonce_js_1 = require("./nonce.js");
7
8
  const truthy_js_1 = require("./truthy.js");
8
9
  const validate_folder_name_js_1 = require("./validation/validate-folder-name.js");
9
10
  exports.FolderContext = (0, react_1.createContext)({
@@ -17,6 +18,7 @@ exports.FolderContext = (0, react_1.createContext)({
17
18
  const Folder = ({ name, children }) => {
18
19
  const parent = (0, react_1.useContext)(exports.FolderContext);
19
20
  const { registerFolder, unregisterFolder } = (0, react_1.useContext)(CompositionManagerContext_js_1.CompositionSetters);
21
+ const nonce = (0, nonce_js_1.useNonce)();
20
22
  (0, validate_folder_name_js_1.validateFolderName)(name);
21
23
  const parentNameArr = [parent.parentName, parent.folderName].filter(truthy_js_1.truthy);
22
24
  const parentName = parentNameArr.length === 0 ? null : parentNameArr.join('/');
@@ -27,11 +29,18 @@ const Folder = ({ name, children }) => {
27
29
  };
28
30
  }, [name, parentName]);
29
31
  (0, react_1.useEffect)(() => {
30
- registerFolder(name, parentName);
32
+ registerFolder(name, parentName, nonce.get());
31
33
  return () => {
32
34
  unregisterFolder(name, parentName);
33
35
  };
34
- }, [name, parent.folderName, parentName, registerFolder, unregisterFolder]);
36
+ }, [
37
+ name,
38
+ parent.folderName,
39
+ parentName,
40
+ registerFolder,
41
+ unregisterFolder,
42
+ nonce,
43
+ ]);
35
44
  return ((0, jsx_runtime_1.jsx)(exports.FolderContext.Provider, { value: value, children: children }));
36
45
  };
37
46
  exports.Folder = Folder;
package/dist/cjs/Img.js CHANGED
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Img = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const cancel_render_js_1 = require("./cancel-render.js");
7
6
  const get_cross_origin_value_js_1 = require("./get-cross-origin-value.js");
8
7
  const prefetch_js_1 = require("./prefetch.js");
9
8
  const SequenceContext_js_1 = require("./SequenceContext.js");
@@ -49,6 +48,7 @@ const ImgRefForwarding = ({ onError, maxRetries = 2, src, pauseWhenLoading, dela
49
48
  imageRef.current.setAttribute('src', newSrc);
50
49
  }, timeout);
51
50
  }, []);
51
+ const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
52
52
  const didGetError = (0, react_1.useCallback)((e) => {
53
53
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
54
54
  if (!errors.current) {
@@ -68,9 +68,14 @@ const ImgRefForwarding = ({ onError, maxRetries = 2, src, pauseWhenLoading, dela
68
68
  retryIn(backoff);
69
69
  return;
70
70
  }
71
- (0, cancel_render_js_1.cancelRender)('Error loading image with src: ' + ((_l = imageRef.current) === null || _l === void 0 ? void 0 : _l.src));
72
- }, [maxRetries, onError, retryIn]);
73
- const { delayRender, continueRender } = (0, use_delay_render_js_1.useDelayRender)();
71
+ try {
72
+ cancelRender('Error loading image with src: ' + ((_l = imageRef.current) === null || _l === void 0 ? void 0 : _l.src));
73
+ }
74
+ catch (_m) {
75
+ // cancelRender() intentionally throws after storing the error in scope.
76
+ // In async image callbacks, we rely on the stored error for renderer propagation.
77
+ }
78
+ }, [cancelRender, maxRetries, onError, retryIn]);
74
79
  if (typeof window !== 'undefined') {
75
80
  const isPremounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting);
76
81
  const isPostmounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting);
@@ -125,7 +130,11 @@ const ImgRefForwarding = ({ onError, maxRetries = 2, src, pauseWhenLoading, dela
125
130
  // fall back to onload event if decode() fails
126
131
  // eslint-disable-next-line no-console
127
132
  console.warn(err);
128
- if (current.complete) {
133
+ // HTMLImageElement.complete is also true for broken images (e.g. 404),
134
+ // so only treat it as loaded if intrinsic dimensions are available.
135
+ if (current.complete &&
136
+ current.naturalWidth > 0 &&
137
+ current.naturalHeight > 0) {
129
138
  onComplete();
130
139
  }
131
140
  else {
@@ -8,5 +8,5 @@ export declare const RemotionRootContexts: React.FC<{
8
8
  readonly videoEnabled: boolean;
9
9
  readonly audioEnabled: boolean;
10
10
  readonly frameState: Record<string, number> | null;
11
- readonly nonceContextSeed: number;
11
+ readonly visualModeEnabled: boolean;
12
12
  }>;
@@ -13,17 +13,16 @@ const SequenceManager_js_1 = require("./SequenceManager.js");
13
13
  const TimelineContext_js_1 = require("./TimelineContext.js");
14
14
  const use_media_enabled_js_1 = require("./use-media-enabled.js");
15
15
  const duration_state_js_1 = require("./video/duration-state.js");
16
- const RemotionRootContexts = ({ children, numberOfAudioTags, logLevel, audioLatencyHint, videoEnabled, audioEnabled, frameState, nonceContextSeed, }) => {
16
+ const RemotionRootContexts = ({ children, numberOfAudioTags, logLevel, audioLatencyHint, videoEnabled, audioEnabled, frameState, visualModeEnabled, }) => {
17
17
  const nonceContext = (0, react_1.useMemo)(() => {
18
18
  let counter = 0;
19
19
  return {
20
20
  getNonce: () => counter++,
21
21
  };
22
- // eslint-disable-next-line react-hooks/exhaustive-deps
23
- }, [nonceContextSeed]);
22
+ }, []);
24
23
  const logging = (0, react_1.useMemo)(() => {
25
24
  return { logLevel, mountTime: Date.now() };
26
25
  }, [logLevel]);
27
- return ((0, jsx_runtime_1.jsx)(log_level_context_js_1.LogLevelContext.Provider, { value: logging, children: (0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(TimelineContext_js_1.TimelineContextProvider, { frameState: frameState, children: (0, jsx_runtime_1.jsx)(use_media_enabled_js_1.MediaEnabledProvider, { videoEnabled: videoEnabled, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(EditorProps_js_1.EditorPropsProvider, { children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(SequenceManager_js_1.SequenceManagerProvider, { children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioContextProvider, { numberOfAudioTags: numberOfAudioTags, audioLatencyHint: audioLatencyHint, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: (0, jsx_runtime_1.jsx)(buffering_js_1.BufferingProvider, { children: children }) }) }) }) }) }) }) }) }) }));
26
+ return ((0, jsx_runtime_1.jsx)(log_level_context_js_1.LogLevelContext.Provider, { value: logging, children: (0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(TimelineContext_js_1.TimelineContextProvider, { frameState: frameState, children: (0, jsx_runtime_1.jsx)(use_media_enabled_js_1.MediaEnabledProvider, { videoEnabled: videoEnabled, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(EditorProps_js_1.EditorPropsProvider, { children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(SequenceManager_js_1.SequenceManagerProvider, { visualModeEnabled: visualModeEnabled, children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioContextProvider, { numberOfAudioTags: numberOfAudioTags, audioLatencyHint: audioLatencyHint, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: (0, jsx_runtime_1.jsx)(buffering_js_1.BufferingProvider, { children: children }) }) }) }) }) }) }) }) }) }));
28
27
  };
29
28
  exports.RemotionRootContexts = RemotionRootContexts;
@@ -11,7 +11,6 @@ const PremountContext_js_1 = require("./PremountContext.js");
11
11
  const SequenceContext_js_1 = require("./SequenceContext.js");
12
12
  const SequenceManager_js_1 = require("./SequenceManager.js");
13
13
  const timeline_position_state_js_1 = require("./timeline-position-state.js");
14
- const TimelineContext_js_1 = require("./TimelineContext.js");
15
14
  const use_current_frame_1 = require("./use-current-frame");
16
15
  const use_remotion_environment_js_1 = require("./use-remotion-environment.js");
17
16
  const use_video_config_js_1 = require("./use-video-config.js");
@@ -21,7 +20,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
21
20
  const { layout = 'absolute-fill' } = other;
22
21
  const [id] = (0, react_1.useState)(() => String(Math.random()));
23
22
  const parentSequence = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
24
- const { rootId } = (0, react_1.useContext)(TimelineContext_js_1.TimelineContext);
23
+ const { rootId } = (0, timeline_position_state_js_1.useTimelineContext)();
25
24
  const cumulatedFrom = parentSequence
26
25
  ? parentSequence.cumulatedFrom + parentSequence.relativeFrom
27
26
  : 0;
@@ -110,7 +109,7 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
110
109
  type: 'sequence',
111
110
  rootId,
112
111
  showInTimeline,
113
- nonce,
112
+ nonce: nonce.get(),
114
113
  loopDisplay,
115
114
  stack: stack !== null && stack !== void 0 ? stack : inheritedStack,
116
115
  premountDisplay: premountDisplay !== null && premountDisplay !== void 0 ? premountDisplay : null,
@@ -169,7 +168,8 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
169
168
  };
170
169
  const RegularSequence = (0, react_1.forwardRef)(RegularSequenceRefForwardingFunction);
171
170
  const PremountedPostmountedSequenceRefForwardingFunction = (props, ref) => {
172
- const frame = (0, use_current_frame_1.useCurrentFrame)();
171
+ const parentPremountContext = (0, react_1.useContext)(PremountContext_js_1.PremountContext);
172
+ const frame = (0, use_current_frame_1.useCurrentFrame)() - parentPremountContext.premountFramesRemaining;
173
173
  if (props.layout === 'none') {
174
174
  throw new Error('`<Sequence>` with `premountFor` and `postmountFor` props does not support layout="none"');
175
175
  }
@@ -202,10 +202,8 @@ const PremountedPostmountedSequenceRefForwardingFunction = (props, ref) => {
202
202
  styleWhilePremounted,
203
203
  styleWhilePostmounted,
204
204
  ]);
205
- const parentPremountContext = (0, react_1.useContext)(PremountContext_js_1.PremountContext);
206
- const { playing } = (0, react_1.useContext)(TimelineContext_js_1.TimelineContext);
207
- const premountFramesRemaining = parentPremountContext.premountFramesRemaining +
208
- (premountingActive ? from - frame : 0);
205
+ const { playing } = (0, timeline_position_state_js_1.useTimelineContext)();
206
+ const premountFramesRemaining = premountingActive ? from - frame : 0;
209
207
  const premountContextValue = (0, react_1.useMemo)(() => {
210
208
  return {
211
209
  premountFramesRemaining,
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { TSequence } from './CompositionManager.js';
3
+ import type { CanUpdateSequencePropStatus } from './use-schema.js';
3
4
  export type SequenceManagerContext = {
4
5
  registerSequence: (seq: TSequence) => void;
5
6
  unregisterSequence: (id: string) => void;
@@ -11,12 +12,16 @@ export type SequenceVisibilityToggleState = {
11
12
  setHidden: React.Dispatch<React.SetStateAction<Record<string, boolean>>>;
12
13
  };
13
14
  export declare const SequenceVisibilityToggleContext: React.Context<SequenceVisibilityToggleState>;
14
- export type SequenceControlOverrideState = {
15
- overrides: Record<string, Record<string, unknown>>;
16
- setOverride: (sequenceId: string, key: string, value: unknown) => void;
17
- clearOverrides: (sequenceId: string) => void;
15
+ export type VisualModeOverrides = {
16
+ visualModeEnabled: boolean;
17
+ dragOverrides: Record<string, Record<string, unknown>>;
18
+ setDragOverrides: (sequenceId: string, key: string, value: unknown) => void;
19
+ clearDragOverrides: (sequenceId: string) => void;
20
+ codeValues: Record<string, Record<string, CanUpdateSequencePropStatus>>;
21
+ setCodeValues: (sequenceId: string, values: Record<string, CanUpdateSequencePropStatus> | null) => void;
18
22
  };
19
- export declare const SequenceControlOverrideContext: React.Context<SequenceControlOverrideState>;
23
+ export declare const VisualModeOverridesContext: React.Context<VisualModeOverrides>;
20
24
  export declare const SequenceManagerProvider: React.FC<{
21
25
  readonly children: React.ReactNode;
26
+ readonly visualModeEnabled: boolean;
22
27
  }>;
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SequenceManagerProvider = exports.SequenceControlOverrideContext = exports.SequenceVisibilityToggleContext = exports.SequenceManager = void 0;
36
+ exports.SequenceManagerProvider = exports.VisualModeOverridesContext = exports.SequenceVisibilityToggleContext = exports.SequenceManager = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  exports.SequenceManager = react_1.default.createContext({
@@ -51,22 +51,28 @@ exports.SequenceVisibilityToggleContext = react_1.default.createContext({
51
51
  throw new Error('SequenceVisibilityToggle not initialized');
52
52
  },
53
53
  });
54
- exports.SequenceControlOverrideContext = react_1.default.createContext({
55
- overrides: {},
56
- setOverride: () => {
57
- throw new Error('SequenceControlOverrideContext not initialized');
54
+ exports.VisualModeOverridesContext = react_1.default.createContext({
55
+ dragOverrides: {},
56
+ setDragOverrides: () => {
57
+ throw new Error('VisualModeOverridesContext not initialized');
58
58
  },
59
- clearOverrides: () => {
60
- throw new Error('SequenceControlOverrideContext not initialized');
59
+ clearDragOverrides: () => {
60
+ throw new Error('VisualModeOverridesContext not initialized');
61
61
  },
62
+ codeValues: {},
63
+ setCodeValues: () => {
64
+ throw new Error('VisualModeOverridesContext not initialized');
65
+ },
66
+ visualModeEnabled: false,
62
67
  });
63
- const SequenceManagerProvider = ({ children }) => {
68
+ const SequenceManagerProvider = ({ children, visualModeEnabled }) => {
64
69
  const [sequences, setSequences] = (0, react_1.useState)([]);
65
70
  const [hidden, setHidden] = (0, react_1.useState)({});
66
- const [controlOverrides, setControlOverrides] = (0, react_1.useState)({});
67
- const controlOverridesRef = (0, react_1.useRef)(controlOverrides);
68
- controlOverridesRef.current = controlOverrides;
69
- const setOverride = (0, react_1.useCallback)((sequenceId, key, value) => {
71
+ const [dragOverrides, setControlOverrides] = (0, react_1.useState)({});
72
+ const controlOverridesRef = (0, react_1.useRef)(dragOverrides);
73
+ controlOverridesRef.current = dragOverrides;
74
+ const [codeValues, setCodeValuesMapState] = (0, react_1.useState)({});
75
+ const setDragOverrides = (0, react_1.useCallback)((sequenceId, key, value) => {
70
76
  setControlOverrides((prev) => ({
71
77
  ...prev,
72
78
  [sequenceId]: {
@@ -75,7 +81,7 @@ const SequenceManagerProvider = ({ children }) => {
75
81
  },
76
82
  }));
77
83
  }, []);
78
- const clearOverrides = (0, react_1.useCallback)((sequenceId) => {
84
+ const clearDragOverrides = (0, react_1.useCallback)((sequenceId) => {
79
85
  setControlOverrides((prev) => {
80
86
  if (!prev[sequenceId]) {
81
87
  return prev;
@@ -85,6 +91,22 @@ const SequenceManagerProvider = ({ children }) => {
85
91
  return next;
86
92
  });
87
93
  }, []);
94
+ const setCodeValues = (0, react_1.useCallback)((sequenceId, values) => {
95
+ setCodeValuesMapState((prev) => {
96
+ if (prev[sequenceId] === values) {
97
+ return prev;
98
+ }
99
+ if (values === null) {
100
+ if (!(sequenceId in prev)) {
101
+ return prev;
102
+ }
103
+ const next = { ...prev };
104
+ delete next[sequenceId];
105
+ return next;
106
+ }
107
+ return { ...prev, [sequenceId]: values };
108
+ });
109
+ }, []);
88
110
  const registerSequence = (0, react_1.useCallback)((seq) => {
89
111
  setSequences((seqs) => {
90
112
  return [...seqs, seq];
@@ -108,11 +130,21 @@ const SequenceManagerProvider = ({ children }) => {
108
130
  }, [hidden]);
109
131
  const overrideContext = (0, react_1.useMemo)(() => {
110
132
  return {
111
- overrides: controlOverrides,
112
- setOverride,
113
- clearOverrides,
133
+ visualModeEnabled,
134
+ dragOverrides,
135
+ setDragOverrides,
136
+ clearDragOverrides,
137
+ codeValues,
138
+ setCodeValues,
114
139
  };
115
- }, [controlOverrides, setOverride, clearOverrides]);
116
- return ((0, jsx_runtime_1.jsx)(exports.SequenceManager.Provider, { value: sequenceContext, children: (0, jsx_runtime_1.jsx)(exports.SequenceVisibilityToggleContext.Provider, { value: hiddenContext, children: (0, jsx_runtime_1.jsx)(exports.SequenceControlOverrideContext.Provider, { value: overrideContext, children: children }) }) }));
140
+ }, [
141
+ visualModeEnabled,
142
+ dragOverrides,
143
+ setDragOverrides,
144
+ clearDragOverrides,
145
+ codeValues,
146
+ setCodeValues,
147
+ ]);
148
+ return ((0, jsx_runtime_1.jsx)(exports.SequenceManager.Provider, { value: sequenceContext, children: (0, jsx_runtime_1.jsx)(exports.SequenceVisibilityToggleContext.Provider, { value: hiddenContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeOverridesContext.Provider, { value: overrideContext, children: children }) }) }));
117
149
  };
118
150
  exports.SequenceManagerProvider = SequenceManagerProvider;
@@ -15,7 +15,8 @@ export type SetTimelineContextValue = {
15
15
  setPlaying: (u: React.SetStateAction<boolean>) => void;
16
16
  };
17
17
  export declare const SetTimelineContext: React.Context<SetTimelineContextValue>;
18
- export declare const TimelineContext: React.Context<TimelineContextValue>;
18
+ export declare const TimelineContext: React.Context<TimelineContextValue | null>;
19
+ export declare const AbsoluteTimeContext: React.Context<TimelineContextValue | null>;
19
20
  export declare const TimelineContextProvider: React.FC<{
20
21
  readonly children: React.ReactNode;
21
22
  readonly frameState: Record<string, number> | null;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineContextProvider = exports.TimelineContext = exports.SetTimelineContext = void 0;
3
+ exports.TimelineContextProvider = exports.AbsoluteTimeContext = exports.TimelineContext = exports.SetTimelineContext = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const random_1 = require("./random");
@@ -14,19 +14,8 @@ exports.SetTimelineContext = (0, react_1.createContext)({
14
14
  throw new Error('default');
15
15
  },
16
16
  });
17
- exports.TimelineContext = (0, react_1.createContext)({
18
- frame: {},
19
- playing: false,
20
- playbackRate: 1,
21
- rootId: '',
22
- imperativePlaying: {
23
- current: false,
24
- },
25
- setPlaybackRate: () => {
26
- throw new Error('default');
27
- },
28
- audioAndVideoTags: { current: [] },
29
- });
17
+ exports.TimelineContext = (0, react_1.createContext)(null);
18
+ exports.AbsoluteTimeContext = (0, react_1.createContext)(null);
30
19
  const TimelineContextProvider = ({ children, frameState }) => {
31
20
  const [playing, setPlaying] = (0, react_1.useState)(false);
32
21
  const imperativePlaying = (0, react_1.useRef)(false);
@@ -84,6 +73,6 @@ const TimelineContextProvider = ({ children, frameState }) => {
84
73
  setPlaying,
85
74
  };
86
75
  }, []);
87
- return ((0, jsx_runtime_1.jsx)(exports.TimelineContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(exports.SetTimelineContext.Provider, { value: setTimelineContextValue, children: children }) }));
76
+ return ((0, jsx_runtime_1.jsx)(exports.AbsoluteTimeContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(exports.TimelineContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(exports.SetTimelineContext.Provider, { value: setTimelineContextValue, children: children }) }) }));
88
77
  };
89
78
  exports.TimelineContextProvider = TimelineContextProvider;
@@ -1,4 +1,4 @@
1
- import type { AudioHTMLAttributes } from 'react';
1
+ import { type AudioHTMLAttributes } from 'react';
2
2
  import React from 'react';
3
3
  import type { SharedElementSourceNode } from './shared-element-source-node.js';
4
4
  /**
@@ -23,6 +23,21 @@ type AudioElem = {
23
23
  audioMounted: boolean;
24
24
  cleanupOnMediaTagUnmount: () => void;
25
25
  };
26
+ export type ScheduleAudioNodeResult = {
27
+ type: 'started';
28
+ scheduledTime: number;
29
+ } | {
30
+ type: 'not-started';
31
+ };
32
+ export type ScheduleAudioNodeOptions = {
33
+ readonly node: AudioBufferSourceNode;
34
+ readonly targetTime: number;
35
+ readonly mediaTimestamp: number;
36
+ readonly currentTime: number;
37
+ readonly sequenceEndTime: number;
38
+ readonly sequenceStartTime: number;
39
+ readonly debugAudioScheduling: boolean;
40
+ };
26
41
  type SharedContext = {
27
42
  registerAudio: (options: {
28
43
  aud: AudioHTMLAttributes<HTMLAudioElement>;
@@ -41,6 +56,10 @@ type SharedContext = {
41
56
  playAllAudios: () => void;
42
57
  numberOfAudioTags: number;
43
58
  audioContext: AudioContext | null;
59
+ audioSyncAnchor: {
60
+ value: number;
61
+ };
62
+ scheduleAudioNode: (options: ScheduleAudioNodeOptions) => ScheduleAudioNodeResult;
44
63
  };
45
64
  export declare const SharedAudioContext: React.Context<SharedContext | null>;
46
65
  export declare const SharedAudioContextProvider: React.FC<{
@@ -37,6 +37,7 @@ exports.useSharedAudio = exports.SharedAudioContextProvider = exports.SharedAudi
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const log_level_context_js_1 = require("../log-level-context.js");
40
+ const log_js_1 = require("../log.js");
40
41
  const play_and_handle_not_allowed_error_js_1 = require("../play-and-handle-not-allowed-error.js");
41
42
  const use_remotion_environment_js_1 = require("../use-remotion-environment.js");
42
43
  const shared_element_source_node_js_1 = require("./shared-element-source-node.js");
@@ -87,6 +88,74 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
87
88
  latencyHint: audioLatencyHint,
88
89
  audioEnabled,
89
90
  });
91
+ const audioSyncAnchor = (0, react_1.useMemo)(() => ({ value: 0 }), []);
92
+ const prevEndTimes = (0, react_1.useRef)({ scheduledEndTime: null, mediaEndTime: null });
93
+ const scheduleAudioNode = (0, react_1.useMemo)(() => {
94
+ return ({ node, mediaTimestamp, targetTime, currentTime, sequenceEndTime, sequenceStartTime, debugAudioScheduling, }) => {
95
+ var _a, _b;
96
+ if (!audioContext) {
97
+ throw new Error('Audio context not found');
98
+ }
99
+ const bufferDuration = (_b = (_a = node.buffer) === null || _a === void 0 ? void 0 : _a.duration) !== null && _b !== void 0 ? _b : 0;
100
+ const unclampedMediaEndTime = mediaTimestamp + bufferDuration;
101
+ const needsTrimEnd = unclampedMediaEndTime > sequenceEndTime;
102
+ const needsTrimStart = mediaTimestamp < sequenceStartTime;
103
+ const offsetBecauseOfTrim = needsTrimStart
104
+ ? sequenceStartTime - mediaTimestamp
105
+ : 0;
106
+ const offsetBecauseOfTooLate = targetTime < 0 ? -targetTime : 0;
107
+ const offset = offsetBecauseOfTrim + offsetBecauseOfTooLate;
108
+ const duration = needsTrimEnd
109
+ ? bufferDuration -
110
+ Math.max(0, unclampedMediaEndTime - sequenceEndTime) -
111
+ offset
112
+ : bufferDuration - offset;
113
+ const scheduledTime = targetTime + currentTime + offset;
114
+ if (offset < 0) {
115
+ throw new Error('offset < 0: ' +
116
+ JSON.stringify({
117
+ offset,
118
+ targetTime,
119
+ currentTime,
120
+ offsetBecauseOfTrim,
121
+ offsetBecauseOfTooLate,
122
+ }));
123
+ }
124
+ if (duration > 0) {
125
+ node.start(scheduledTime, offset, duration);
126
+ }
127
+ const scheduledEndTime = scheduledTime + duration / node.playbackRate.value;
128
+ const mediaTime = mediaTimestamp + offset;
129
+ const mediaEndTime = mediaTime + duration;
130
+ const latency = audioContext.baseLatency + audioContext.outputLatency;
131
+ const timeDiff = scheduledTime - currentTime - latency;
132
+ const prev = prevEndTimes.current;
133
+ const scheduledMismatch = prev.scheduledEndTime !== null &&
134
+ Math.abs(scheduledTime - prev.scheduledEndTime) > 0.001;
135
+ const mediaMismatch = prev.mediaEndTime !== null &&
136
+ Math.abs(mediaTime - prev.mediaEndTime) > 0.001;
137
+ if (debugAudioScheduling) {
138
+ log_js_1.Log.info({ logLevel, tag: 'audio-scheduling' }, 'scheduled %c%s%c %s %c%s%c %s %c%s%c %s %s %s', scheduledMismatch ? 'color: red; font-weight: bold' : '', scheduledTime.toFixed(4), '', scheduledEndTime.toFixed(4), mediaMismatch ? 'color: red; font-weight: bold' : '', mediaTime.toFixed(4), '', mediaEndTime.toFixed(4), duration < 0
139
+ ? 'color: red; font-weight: bold'
140
+ : timeDiff < 0
141
+ ? 'color: red; font-weight: bold'
142
+ : 'color: blue; font-weight: bold', duration < 0
143
+ ? 'missed ' + Math.abs(offset).toFixed(2) + 's'
144
+ : Math.abs(timeDiff).toFixed(2) +
145
+ (timeDiff < 0 ? ' delay' : ' ahead'), '', 'current=' + currentTime.toFixed(4), 'offset=' + offset.toFixed(4), 'latency=' + latency.toFixed(4), 'state=' + audioContext.state);
146
+ }
147
+ prev.scheduledEndTime = scheduledEndTime;
148
+ prev.mediaEndTime = mediaEndTime;
149
+ return duration > 0
150
+ ? {
151
+ type: 'started',
152
+ scheduledTime,
153
+ }
154
+ : {
155
+ type: 'not-started',
156
+ };
157
+ };
158
+ }, [audioContext, logLevel]);
90
159
  const refs = (0, react_1.useMemo)(() => {
91
160
  return new Array(numberOfAudioTags).fill(true).map(() => {
92
161
  const ref = (0, react_1.createRef)();
@@ -253,6 +322,8 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
253
322
  playAllAudios,
254
323
  numberOfAudioTags,
255
324
  audioContext,
325
+ audioSyncAnchor,
326
+ scheduleAudioNode,
256
327
  };
257
328
  }, [
258
329
  numberOfAudioTags,
@@ -261,6 +332,8 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
261
332
  unregisterAudio,
262
333
  updateAudio,
263
334
  audioContext,
335
+ audioSyncAnchor,
336
+ scheduleAudioNode,
264
337
  ]);
265
338
  return ((0, jsx_runtime_1.jsxs)(exports.SharedAudioContext.Provider, { value: value, children: [refs.map(({ id, ref }) => {
266
339
  return (
@@ -4,6 +4,7 @@ exports.Freeze = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const SequenceContext_js_1 = require("./SequenceContext.js");
7
+ const timeline_position_state_js_1 = require("./timeline-position-state.js");
7
8
  const TimelineContext_js_1 = require("./TimelineContext.js");
8
9
  const use_current_frame_js_1 = require("./use-current-frame.js");
9
10
  const use_video_config_js_1 = require("./use-video-config.js");
@@ -35,7 +36,7 @@ const Freeze = ({ frame: frameToFreeze, children, active = true, }) => {
35
36
  return active(frame);
36
37
  }
37
38
  }, [active, frame]);
38
- const timelineContext = (0, react_1.useContext)(TimelineContext_js_1.TimelineContext);
39
+ const timelineContext = (0, timeline_position_state_js_1.useTimelineContext)();
39
40
  const sequenceContext = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
40
41
  const relativeFrom = (_a = sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom) !== null && _a !== void 0 ? _a : 0;
41
42
  const timelineValue = (0, react_1.useMemo)(() => {
@@ -0,0 +1,8 @@
1
+ import type { CanUpdateSequencePropStatus } from './use-schema';
2
+ export declare const getEffectiveVisualModeValue: ({ codeValue, runtimeValue, dragOverrideValue, defaultValue, shouldResortToDefaultValueIfUndefined, }: {
3
+ codeValue: CanUpdateSequencePropStatus | null;
4
+ runtimeValue: unknown;
5
+ dragOverrideValue: unknown;
6
+ defaultValue: unknown;
7
+ shouldResortToDefaultValueIfUndefined: boolean;
8
+ }) => unknown;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getEffectiveVisualModeValue = void 0;
4
+ const getEffectiveVisualModeValue = ({ codeValue, runtimeValue, dragOverrideValue, defaultValue, shouldResortToDefaultValueIfUndefined = false, }) => {
5
+ if (dragOverrideValue !== undefined) {
6
+ return dragOverrideValue;
7
+ }
8
+ if (!codeValue) {
9
+ return runtimeValue;
10
+ }
11
+ if (!codeValue.canUpdate) {
12
+ return runtimeValue;
13
+ }
14
+ if (codeValue.codeValue === undefined &&
15
+ shouldResortToDefaultValueIfUndefined) {
16
+ return defaultValue;
17
+ }
18
+ return codeValue.codeValue;
19
+ };
20
+ exports.getEffectiveVisualModeValue = getEffectiveVisualModeValue;