remotion 4.1.0-alpha5 → 4.1.0-alpha7

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.
@@ -22,17 +22,32 @@ export type CalculateMetadataFunction<T extends Record<string, unknown>> = (opti
22
22
  props: T;
23
23
  abortSignal: AbortSignal;
24
24
  }) => Promise<CalcMetadataReturnType<T>> | CalcMetadataReturnType<T>;
25
- export type StillProps<Schema extends AnyZodObject, Props extends Record<string, unknown>> = {
25
+ type OptionalDimensions<Schema extends AnyZodObject, Props extends Record<string, unknown>> = {
26
+ width?: number;
27
+ height?: number;
28
+ calculateMetadata: CalculateMetadataFunction<InferProps<Schema, Props>>;
29
+ };
30
+ type MandatoryDimensions<Schema extends AnyZodObject, Props extends Record<string, unknown>> = {
26
31
  width: number;
27
32
  height: number;
28
- id: string;
29
33
  calculateMetadata?: CalculateMetadataFunction<InferProps<Schema, Props>>;
30
- schema?: Schema;
31
- } & CompProps<Props> & PropsIfHasProps<Schema, Props>;
32
- export type CompositionProps<Schema extends AnyZodObject, Props extends Record<string, unknown>> = StillProps<Schema, Props> & {
34
+ };
35
+ type StillCalculateMetadataOrExplicit<Schema extends AnyZodObject, Props extends Record<string, unknown>> = OptionalDimensions<Schema, Props> | MandatoryDimensions<Schema, Props>;
36
+ type CompositionCalculateMetadataOrExplicit<Schema extends AnyZodObject, Props extends Record<string, unknown>> = (OptionalDimensions<Schema, Props> & {
37
+ fps?: number;
38
+ durationInFrames?: number;
39
+ }) | (MandatoryDimensions<Schema, Props> & {
33
40
  fps: number;
34
41
  durationInFrames: number;
35
- };
42
+ });
43
+ export type StillProps<Schema extends AnyZodObject, Props extends Record<string, unknown>> = {
44
+ id: string;
45
+ schema?: Schema;
46
+ } & StillCalculateMetadataOrExplicit<Schema, Props> & CompProps<Props> & PropsIfHasProps<Schema, Props>;
47
+ export type CompositionProps<Schema extends AnyZodObject, Props extends Record<string, unknown>> = {
48
+ id: string;
49
+ schema?: Schema;
50
+ } & CompositionCalculateMetadataOrExplicit<Schema, Props> & CompProps<Props> & PropsIfHasProps<Schema, Props>;
36
51
  /**
37
52
  * @description This component is used to register a video to make it renderable and make it show in the sidebar, in dev mode.
38
53
  * @see [Documentation](https://www.remotion.dev/docs/composition)
@@ -19,9 +19,6 @@ const use_lazy_component_js_1 = require("./use-lazy-component.js");
19
19
  const use_video_js_1 = require("./use-video.js");
20
20
  const validate_composition_id_js_1 = require("./validation/validate-composition-id.js");
21
21
  const validate_default_props_js_1 = require("./validation/validate-default-props.js");
22
- const validate_dimensions_js_1 = require("./validation/validate-dimensions.js");
23
- const validate_duration_in_frames_js_1 = require("./validation/validate-duration-in-frames.js");
24
- const validate_fps_js_1 = require("./validation/validate-fps.js");
25
22
  const Fallback = () => {
26
23
  (0, react_1.useEffect)(() => {
27
24
  const fallback = (0, delay_render_js_1.delayRender)('Waiting for Root component to unsuspend');
@@ -56,20 +53,12 @@ const Composition = ({ width, height, fps, durationInFrames, id, defaultProps, s
56
53
  throw new Error('No id for composition passed.');
57
54
  }
58
55
  (0, validate_composition_id_js_1.validateCompositionId)(id);
59
- (0, validate_dimensions_js_1.validateDimension)(width, 'width', 'of the <Composition/> component');
60
- (0, validate_dimensions_js_1.validateDimension)(height, 'height', 'of the <Composition/> component');
61
- (0, validate_duration_in_frames_js_1.validateDurationInFrames)({
62
- durationInFrames,
63
- component: 'of the <Composition/> component',
64
- allowFloats: false,
65
- });
66
- (0, validate_fps_js_1.validateFps)(fps, 'as a prop of the <Composition/> component', false);
67
56
  (0, validate_default_props_js_1.validateDefaultAndInputProps)(defaultProps, 'defaultProps', id);
68
57
  registerComposition({
69
- durationInFrames,
70
- fps,
71
- height,
72
- width,
58
+ durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : undefined,
59
+ fps: fps !== null && fps !== void 0 ? fps : undefined,
60
+ height: height !== null && height !== void 0 ? height : undefined,
61
+ width: width !== null && width !== void 0 ? width : undefined,
73
62
  id,
74
63
  folderName,
75
64
  component: lazy,
@@ -4,10 +4,10 @@ import type { AnyZodObject } from 'zod';
4
4
  import type { CalculateMetadataFunction } from './Composition.js';
5
5
  import type { InferProps, PropsIfHasProps } from './props-if-has-props.js';
6
6
  export type TComposition<Schema extends AnyZodObject, Props extends Record<string, unknown>> = {
7
- width: number;
8
- height: number;
9
- fps: number;
10
- durationInFrames: number;
7
+ width: number | undefined;
8
+ height: number | undefined;
9
+ fps: number | undefined;
10
+ durationInFrames: number | undefined;
11
11
  id: string;
12
12
  folderName: string | null;
13
13
  parentFolderName: string | null;
@@ -13,9 +13,8 @@ const random_js_1 = require("./random.js");
13
13
  const timeline_position_state_js_1 = require("./timeline-position-state.js");
14
14
  const duration_state_js_1 = require("./video/duration-state.js");
15
15
  const RemotionRoot = ({ children, numberOfAudioTags }) => {
16
- var _a;
17
16
  const [remotionRootId] = (0, react_1.useState)(() => String((0, random_js_1.random)(null)));
18
- const [frame, setFrame] = (0, react_1.useState)((_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0);
17
+ const [frame, setFrame] = (0, react_1.useState)({});
19
18
  const [playing, setPlaying] = (0, react_1.useState)(false);
20
19
  const imperativePlaying = (0, react_1.useRef)(false);
21
20
  const [fastRefreshes, setFastRefreshes] = (0, react_1.useState)(0);
@@ -24,9 +23,12 @@ const RemotionRoot = ({ children, numberOfAudioTags }) => {
24
23
  if (typeof window !== 'undefined') {
25
24
  // eslint-disable-next-line react-hooks/rules-of-hooks
26
25
  (0, react_1.useLayoutEffect)(() => {
27
- window.remotion_setFrame = (f) => {
26
+ window.remotion_setFrame = (f, composition) => {
28
27
  const id = (0, delay_render_js_1.delayRender)(`Setting the current frame to ${f}`);
29
- setFrame(f);
28
+ setFrame((s) => ({
29
+ ...s,
30
+ [composition]: f,
31
+ }));
30
32
  requestAnimationFrame(() => (0, delay_render_js_1.continueRender)(id));
31
33
  };
32
34
  window.remotion_isPlayer = false;
@@ -30,12 +30,23 @@ const ResolveCompositionConfig = ({ children }) => {
30
30
  : {};
31
31
  }, [allEditorProps, renderModalComposition]);
32
32
  const doResolution = (0, react_1.useCallback)((composition, editorProps) => {
33
+ var _a;
33
34
  const controller = new AbortController();
34
35
  if (currentCompositionMetadata) {
35
36
  return controller;
36
37
  }
38
+ const inputProps = typeof window === 'undefined' ||
39
+ (0, get_environment_js_1.getRemotionEnvironment)() === 'player-development' ||
40
+ (0, get_environment_js_1.getRemotionEnvironment)() === 'player-production'
41
+ ? {}
42
+ : (_a = (0, input_props_js_1.getInputProps)()) !== null && _a !== void 0 ? _a : {};
37
43
  const { signal } = controller;
38
- const promOrNot = (0, resolve_video_config_js_1.resolveVideoConfig)({ composition, editorProps, signal });
44
+ const promOrNot = (0, resolve_video_config_js_1.resolveVideoConfig)({
45
+ composition,
46
+ editorProps,
47
+ inputProps,
48
+ signal,
49
+ });
39
50
  if (typeof promOrNot === 'object' && 'then' in promOrNot) {
40
51
  setResolvedConfigs((r) => ({
41
52
  ...r,
@@ -171,7 +182,11 @@ const useResolvedVideoConfig = (preferredCompositionId) => {
171
182
  return {
172
183
  type: 'success',
173
184
  result: {
174
- ...composition,
185
+ width: composition.width,
186
+ height: composition.height,
187
+ fps: composition.fps,
188
+ id: composition.id,
189
+ durationInFrames: composition.durationInFrames,
175
190
  defaultProps: (_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {},
176
191
  props: {
177
192
  ...((_c = composition.defaultProps) !== null && _c !== void 0 ? _c : {}),
@@ -5,11 +5,13 @@ 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
7
  const timeline_position_state_js_1 = require("./timeline-position-state.js");
8
+ const use_video_config_js_1 = require("./use-video-config.js");
8
9
  /**
9
10
  * @description This method freezes all of its children to the frame that you specify as a prop
10
11
  * @see [Documentation](https://www.remotion.dev/docs/freeze)
11
12
  */
12
13
  const Freeze = ({ frame, children }) => {
14
+ const videoConfig = (0, use_video_config_js_1.useVideoConfig)();
13
15
  if (typeof frame === 'undefined') {
14
16
  throw new Error(`The <Freeze /> component requires a 'frame' prop, but none was passed.`);
15
17
  }
@@ -30,9 +32,11 @@ const Freeze = ({ frame, children }) => {
30
32
  imperativePlaying: {
31
33
  current: false,
32
34
  },
33
- frame,
35
+ frame: {
36
+ [videoConfig.id]: frame,
37
+ },
34
38
  };
35
- }, [context, frame]);
39
+ }, [context, frame, videoConfig.id]);
36
40
  return ((0, jsx_runtime_1.jsx)(timeline_position_state_js_1.TimelineContext.Provider, { value: value, children: (0, jsx_runtime_1.jsx)(SequenceContext_js_1.SequenceContext.Provider, { value: null, children: children }) }));
37
41
  };
38
42
  exports.Freeze = Freeze;
@@ -18,7 +18,7 @@ declare global {
18
18
  remotion_projectName: string;
19
19
  remotion_cwd: string;
20
20
  remotion_studioServerCommand: string;
21
- remotion_setFrame: (frame: number) => void;
21
+ remotion_setFrame: (frame: number, composition: string) => void;
22
22
  remotion_initialFrame: number;
23
23
  remotion_proxyPort: number;
24
24
  remotion_audioEnabled: boolean;
@@ -31,7 +31,7 @@ declare global {
31
31
  remotion_isPlayer: boolean;
32
32
  remotion_isBuilding: undefined | (() => void);
33
33
  remotion_finishedBuilding: undefined | (() => void);
34
- siteVersion: '6';
34
+ siteVersion: '7';
35
35
  remotion_version: string;
36
36
  remotion_imported: string | boolean;
37
37
  }
package/dist/cjs/index.js CHANGED
@@ -98,7 +98,7 @@ exports.Config = new Proxy(proxyObj, {
98
98
  console.warn('+ Replace:');
99
99
  console.warn('import {Config} from "@remotion/cli/config";');
100
100
  console.warn();
101
- console.warn('For more information, see https://v4.remotion.dev/docs/4-0-migration.');
101
+ console.warn('For more information, see https://www.remotion.dev/docs/4-0-migration.');
102
102
  process.exit(1);
103
103
  };
104
104
  },
@@ -8,45 +8,44 @@ import { processColor } from './interpolate-colors.js';
8
8
  import type { SetTimelineContextValue, TimelineContextValue } from './timeline-position-state.js';
9
9
  import * as TimelinePosition from './timeline-position-state.js';
10
10
  import { truthy } from './truthy.js';
11
+ import { validateDimension } from './validation/validate-dimensions.js';
12
+ import { validateDurationInFrames } from './validation/validate-duration-in-frames.js';
13
+ import { validateFps } from './validation/validate-fps.js';
11
14
  import type { MediaVolumeContextValue, SetMediaVolumeContextValue } from './volume-position-state.js';
12
15
  import { useRemotionContexts } from './wrap-remotion-context.js';
13
16
  declare const Timeline: typeof TimelinePosition;
14
17
  export declare const Internals: {
15
- useUnsafeVideoConfig: () => import("./video-config.js").VideoConfig | null;
16
- Timeline: typeof TimelinePosition;
17
- CompositionManager: import("react").Context<CompositionManagerContext>;
18
- SequenceManager: import("react").Context<import("./SequenceManager.js").SequenceManagerContext>;
19
- RemotionRoot: import("react").FC<{
18
+ readonly useUnsafeVideoConfig: () => import("./video-config.js").VideoConfig | null;
19
+ readonly Timeline: typeof TimelinePosition;
20
+ readonly CompositionManager: import("react").Context<CompositionManagerContext>;
21
+ readonly SequenceManager: import("react").Context<import("./SequenceManager.js").SequenceManagerContext>;
22
+ readonly RemotionRoot: import("react").FC<{
20
23
  children: import("react").ReactNode;
21
24
  numberOfAudioTags: number;
22
25
  }>;
23
- useVideo: () => (import("./video-config.js").VideoConfig & {
26
+ readonly useVideo: () => (import("./video-config.js").VideoConfig & {
24
27
  component: import("react").LazyExoticComponent<import("react").ComponentType<Record<string, unknown>>>;
25
28
  }) | null;
26
- getRoot: () => import("react").FC<{}> | null;
27
- useMediaVolumeState: () => readonly [number, (u: number) => void];
28
- useMediaMutedState: () => readonly [boolean, (u: import("react").SetStateAction<boolean>) => void];
29
- useLazyComponent: <Props>(compProps: CompProps<Props>) => import("react").ExoticComponent<(import("react").PropsWithoutRef<Props> & import("react").RefAttributes<import("react").Component<Props, any, any>>) | import("react").PropsWithRef<Props>> & {
29
+ readonly getRoot: () => import("react").FC<{}> | null;
30
+ readonly useMediaVolumeState: () => readonly [number, (u: number) => void];
31
+ readonly useMediaMutedState: () => readonly [boolean, (u: import("react").SetStateAction<boolean>) => void];
32
+ readonly useLazyComponent: <Props>(compProps: CompProps<Props>) => import("react").ExoticComponent<(import("react").PropsWithoutRef<Props> & import("react").RefAttributes<import("react").Component<Props, any, any>>) | import("react").PropsWithRef<Props>> & {
30
33
  readonly _result: import("react").ComponentType<Props>;
31
34
  };
32
- truthy: typeof truthy;
33
- SequenceContext: import("react").Context<import("./SequenceContext.js").SequenceContextType | null>;
34
- useRemotionContexts: typeof useRemotionContexts;
35
- RemotionContextProvider: (props: import("./wrap-remotion-context.js").RemotionContextProviderProps) => JSX.Element;
36
- CSSUtils: typeof CSSUtils;
37
- setupEnvVariables: () => void;
38
- MediaVolumeContext: import("react").Context<MediaVolumeContextValue>;
39
- SetMediaVolumeContext: import("react").Context<SetMediaVolumeContextValue>;
40
- validateDurationInFrames: ({ allowFloats, component, durationInFrames, }: {
41
- durationInFrames: number;
42
- component: string;
43
- allowFloats: boolean;
44
- }) => void;
45
- validateFps: (fps: number, location: string, isGif: boolean) => void;
46
- validateDefaultAndInputProps: (defaultProps: unknown, name: "defaultProps" | "inputProps", compositionId: string | null) => void;
47
- validateDimension: (amount: number, nameOfProp: string, location: string) => void;
48
- getRemotionEnvironment: () => RemotionEnvironment;
49
- SharedAudioContext: import("react").Context<{
35
+ readonly truthy: typeof truthy;
36
+ readonly SequenceContext: import("react").Context<import("./SequenceContext.js").SequenceContextType | null>;
37
+ readonly useRemotionContexts: typeof useRemotionContexts;
38
+ readonly RemotionContextProvider: (props: import("./wrap-remotion-context.js").RemotionContextProviderProps) => JSX.Element;
39
+ readonly CSSUtils: typeof CSSUtils;
40
+ readonly setupEnvVariables: () => void;
41
+ readonly MediaVolumeContext: import("react").Context<MediaVolumeContextValue>;
42
+ readonly SetMediaVolumeContext: import("react").Context<SetMediaVolumeContextValue>;
43
+ readonly validateDurationInFrames: typeof validateDurationInFrames;
44
+ readonly validateFps: typeof validateFps;
45
+ readonly validateDefaultAndInputProps: (defaultProps: unknown, name: "defaultProps" | "inputProps", compositionId: string | null) => void;
46
+ readonly validateDimension: typeof validateDimension;
47
+ readonly getRemotionEnvironment: () => RemotionEnvironment;
48
+ readonly SharedAudioContext: import("react").Context<{
50
49
  registerAudio: (aud: import("./index.js").RemotionAudioProps, audioId: string) => {
51
50
  id: number;
52
51
  props: import("./index.js").RemotionAudioProps;
@@ -62,53 +61,54 @@ export declare const Internals: {
62
61
  playAllAudios: () => void;
63
62
  numberOfAudioTags: number;
64
63
  } | null>;
65
- SharedAudioContextProvider: import("react").FC<{
64
+ readonly SharedAudioContextProvider: import("react").FC<{
66
65
  numberOfAudioTags: number;
67
66
  children: import("react").ReactNode;
68
67
  component: import("react").LazyExoticComponent<import("react").ComponentType<Record<string, unknown>>> | null;
69
68
  }>;
70
- invalidCompositionErrorMessage: string;
71
- isCompositionIdValid: (id: string) => RegExpMatchArray | null;
72
- getPreviewDomElement: () => HTMLElement | null;
73
- compositionsRef: import("react").RefObject<{
69
+ readonly invalidCompositionErrorMessage: string;
70
+ readonly isCompositionIdValid: (id: string) => RegExpMatchArray | null;
71
+ readonly getPreviewDomElement: () => HTMLElement | null;
72
+ readonly compositionsRef: import("react").RefObject<{
74
73
  getCompositions: () => import("./CompositionManager.js").TCompMetadataWithCalcFunction<import("zod").AnyZodObject, Record<string, unknown>>[];
75
74
  }>;
76
- DELAY_RENDER_CALLSTACK_TOKEN: string;
77
- portalNode: () => HTMLElement;
78
- waitForRoot: (fn: (comp: import("react").FC<{}>) => void) => () => void;
79
- CanUseRemotionHooksProvider: import("react").FC<{
75
+ readonly DELAY_RENDER_CALLSTACK_TOKEN: "The delayRender was called:";
76
+ readonly portalNode: () => HTMLElement;
77
+ readonly waitForRoot: (fn: (comp: import("react").FC<{}>) => void) => () => void;
78
+ readonly CanUseRemotionHooksProvider: import("react").FC<{
80
79
  children: import("react").ReactNode;
81
80
  }>;
82
- CanUseRemotionHooks: import("react").Context<boolean>;
83
- PrefetchProvider: import("react").FC<{
81
+ readonly CanUseRemotionHooks: import("react").Context<boolean>;
82
+ readonly PrefetchProvider: import("react").FC<{
84
83
  children: import("react").ReactNode;
85
84
  }>;
86
- DurationsContextProvider: import("react").FC<{
85
+ readonly DurationsContextProvider: import("react").FC<{
87
86
  children: import("react").ReactNode;
88
87
  }>;
89
- IsPlayerContextProvider: import("react").FC<{
88
+ readonly IsPlayerContextProvider: import("react").FC<{
90
89
  children?: import("react").ReactNode;
91
90
  }>;
92
- useIsPlayer: () => boolean;
93
- useRemotionEnvironment: () => RemotionEnvironment;
94
- validateFrame: ({ allowFloats, durationInFrames, frame, }: {
91
+ readonly useIsPlayer: () => boolean;
92
+ readonly useRemotionEnvironment: () => RemotionEnvironment;
93
+ readonly validateFrame: ({ allowFloats, durationInFrames, frame, }: {
95
94
  frame: number;
96
95
  durationInFrames: number;
97
96
  allowFloats: boolean;
98
97
  }) => void;
99
- EditorPropsProvider: import("react").FC<{
98
+ readonly EditorPropsProvider: import("react").FC<{
100
99
  children: import("react").ReactNode;
101
100
  }>;
102
- EditorPropsContext: import("react").Context<import("./EditorProps.js").EditorPropsContextType>;
103
- usePreload: (src: string) => string;
104
- processColor: typeof processColor;
105
- NonceContext: import("react").Context<import("./nonce.js").TNonceContext>;
106
- resolveVideoConfig: ({ composition, editorProps: editorPropsOrUndefined, signal, }: {
101
+ readonly EditorPropsContext: import("react").Context<import("./EditorProps.js").EditorPropsContextType>;
102
+ readonly usePreload: (src: string) => string;
103
+ readonly processColor: typeof processColor;
104
+ readonly NonceContext: import("react").Context<import("./nonce.js").TNonceContext>;
105
+ readonly resolveVideoConfig: ({ composition, editorProps: editorPropsOrUndefined, signal, inputProps, }: {
107
106
  composition: import("./CompositionManager.js").TCompMetadataWithCalcFunction<import("zod").AnyZodObject, Record<string, unknown>>;
108
107
  editorProps: object;
109
108
  signal: AbortSignal;
109
+ inputProps: Record<string, unknown>;
110
110
  }) => import("./video-config.js").VideoConfig | Promise<import("./video-config.js").VideoConfig>;
111
- useResolvedVideoConfig: (preferredCompositionId: string | null) => ({
111
+ readonly useResolvedVideoConfig: (preferredCompositionId: string | null) => ({
112
112
  type: "loading";
113
113
  } | {
114
114
  type: "success";
@@ -117,15 +117,17 @@ export declare const Internals: {
117
117
  type: "error";
118
118
  error: Error;
119
119
  }) | null;
120
- resolveCompositionsRef: import("react").RefObject<{
120
+ readonly resolveCompositionsRef: import("react").RefObject<{
121
121
  setCurrentRenderModalComposition: (compositionId: string | null) => void;
122
122
  reloadCurrentlySelectedComposition: () => void;
123
123
  }>;
124
- ResolveCompositionConfig: import("react").FC<import("react").PropsWithChildren<{
124
+ readonly ResolveCompositionConfig: import("react").FC<import("react").PropsWithChildren<{
125
125
  children: import("react").ReactNode;
126
126
  }>>;
127
- REMOTION_STUDIO_CONTAINER_ELEMENT: string;
128
- AssetManager: import("react").Context<import("./AssetManager.js").AssetManagerContext>;
129
- bundleName: string;
127
+ readonly REMOTION_STUDIO_CONTAINER_ELEMENT: "__remotion-studio-container";
128
+ readonly AssetManager: import("react").Context<import("./AssetManager.js").AssetManagerContext>;
129
+ readonly bundleName: "bundle.js";
130
+ readonly persistCurrentFrame: (frame: number, composition: string) => void;
131
+ readonly useTimelineSetFrame: () => (u: import("react").SetStateAction<Record<string, number>>) => void;
130
132
  };
131
133
  export type { TComposition, Timeline, TCompMetadata, TSequence, TAsset, TimelineContextValue, SetTimelineContextValue, CompProps, CompositionManagerContext, MediaVolumeContextValue, SetMediaVolumeContextValue, RemotionEnvironment, };
@@ -47,6 +47,7 @@ const ResolveCompositionConfig_js_1 = require("./ResolveCompositionConfig.js");
47
47
  const SequenceContext_js_1 = require("./SequenceContext.js");
48
48
  const SequenceManager_js_1 = require("./SequenceManager.js");
49
49
  const setup_env_variables_js_1 = require("./setup-env-variables.js");
50
+ const timeline_position_state_js_1 = require("./timeline-position-state.js");
50
51
  const TimelinePosition = __importStar(require("./timeline-position-state.js"));
51
52
  const truthy_js_1 = require("./truthy.js");
52
53
  const use_lazy_component_js_1 = require("./use-lazy-component.js");
@@ -117,4 +118,6 @@ exports.Internals = {
117
118
  REMOTION_STUDIO_CONTAINER_ELEMENT: get_preview_dom_element_js_1.REMOTION_STUDIO_CONTAINER_ELEMENT,
118
119
  AssetManager: AssetManager_js_1.AssetManager,
119
120
  bundleName: 'bundle.js',
121
+ persistCurrentFrame: timeline_position_state_js_1.persistCurrentFrame,
122
+ useTimelineSetFrame: timeline_position_state_js_1.useTimelineSetFrame,
120
123
  };
@@ -14,8 +14,7 @@ const validate_duration_in_frames_js_1 = require("../validation/validate-duratio
14
14
  const Loop = ({ durationInFrames, times = Infinity, children, name, ...props }) => {
15
15
  const currentFrame = (0, use_current_frame_js_1.useCurrentFrame)();
16
16
  const { durationInFrames: compDuration } = (0, use_video_config_js_1.useVideoConfig)();
17
- (0, validate_duration_in_frames_js_1.validateDurationInFrames)({
18
- durationInFrames,
17
+ (0, validate_duration_in_frames_js_1.validateDurationInFrames)(durationInFrames, {
19
18
  component: 'of the <Loop /> component',
20
19
  allowFloats: true,
21
20
  });
@@ -1,8 +1,9 @@
1
1
  import type { AnyZodObject } from 'zod';
2
2
  import type { TCompMetadataWithCalcFunction } from './CompositionManager.js';
3
3
  import type { VideoConfig } from './video-config.js';
4
- export declare const resolveVideoConfig: ({ composition, editorProps: editorPropsOrUndefined, signal, }: {
4
+ export declare const resolveVideoConfig: ({ composition, editorProps: editorPropsOrUndefined, signal, inputProps, }: {
5
5
  composition: TCompMetadataWithCalcFunction<AnyZodObject, Record<string, unknown>>;
6
6
  editorProps: object;
7
7
  signal: AbortSignal;
8
+ inputProps: Record<string, unknown>;
8
9
  }) => VideoConfig | Promise<VideoConfig>;
@@ -1,23 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveVideoConfig = void 0;
4
- const input_props_js_1 = require("./config/input-props.js");
5
- const get_environment_js_1 = require("./get-environment.js");
6
4
  const validate_dimensions_js_1 = require("./validation/validate-dimensions.js");
7
5
  const validate_duration_in_frames_js_1 = require("./validation/validate-duration-in-frames.js");
8
- const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined, signal, }) => {
9
- var _a, _b, _c, _d, _e, _f, _g, _h;
6
+ const validate_fps_js_1 = require("./validation/validate-fps.js");
7
+ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined, signal, inputProps, }) => {
8
+ var _a, _b, _c, _d, _e, _f, _g;
10
9
  const calculatedProm = composition.calculateMetadata
11
10
  ? composition.calculateMetadata({
12
11
  defaultProps: (_a = composition.defaultProps) !== null && _a !== void 0 ? _a : {},
13
12
  props: {
14
13
  ...((_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {}),
15
14
  ...(editorPropsOrUndefined !== null && editorPropsOrUndefined !== void 0 ? editorPropsOrUndefined : {}),
16
- ...(typeof window === 'undefined' ||
17
- (0, get_environment_js_1.getRemotionEnvironment)() === 'player-development' ||
18
- (0, get_environment_js_1.getRemotionEnvironment)() === 'player-production'
19
- ? {}
20
- : (_c = (0, input_props_js_1.getInputProps)()) !== null && _c !== void 0 ? _c : {}),
15
+ ...inputProps,
21
16
  },
22
17
  abortSignal: signal,
23
18
  })
@@ -50,43 +45,35 @@ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined,
50
45
  return {
51
46
  ...data,
52
47
  id: composition.id,
53
- defaultProps: (_d = composition.defaultProps) !== null && _d !== void 0 ? _d : {},
54
- props: (_e = composition.defaultProps) !== null && _e !== void 0 ? _e : {},
48
+ defaultProps: (_c = composition.defaultProps) !== null && _c !== void 0 ? _c : {},
49
+ props: {
50
+ ...((_d = composition.defaultProps) !== null && _d !== void 0 ? _d : {}),
51
+ ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}),
52
+ },
55
53
  };
56
54
  }
57
55
  return {
58
56
  ...data,
59
57
  id: composition.id,
60
- defaultProps: (_f = composition.defaultProps) !== null && _f !== void 0 ? _f : {},
61
- props: (_h = (_g = calculatedProm.props) !== null && _g !== void 0 ? _g : composition.defaultProps) !== null && _h !== void 0 ? _h : {},
58
+ defaultProps: (_e = composition.defaultProps) !== null && _e !== void 0 ? _e : {},
59
+ props: (_g = (_f = calculatedProm.props) !== null && _f !== void 0 ? _f : composition.defaultProps) !== null && _g !== void 0 ? _g : {},
62
60
  };
63
61
  };
64
62
  exports.resolveVideoConfig = resolveVideoConfig;
65
63
  const validateCalculated = ({ composition, calculated, }) => {
66
64
  var _a, _b, _c, _d, _e, _f, _g, _h;
67
- const potentialErrorLocation = `calculated by calculateMetadata() for the composition "${composition.id}"`;
68
- const width = (_b = (_a = calculated === null || calculated === void 0 ? void 0 : calculated.width) !== null && _a !== void 0 ? _a : composition.width) !== null && _b !== void 0 ? _b : null;
69
- if (!width) {
70
- throw new TypeError('Composition width was neither specified via the `width` prop nor the `calculateMetadata()` function.');
71
- }
72
- (0, validate_dimensions_js_1.validateDimension)(width, 'width', potentialErrorLocation);
73
- const height = (_d = (_c = calculated === null || calculated === void 0 ? void 0 : calculated.height) !== null && _c !== void 0 ? _c : composition.height) !== null && _d !== void 0 ? _d : null;
74
- if (!height) {
75
- throw new TypeError('Composition height was neither specified via the `height` prop nor the `calculateMetadata()` function.');
76
- }
77
- (0, validate_dimensions_js_1.validateDimension)(width, 'height', potentialErrorLocation);
65
+ const calculateMetadataErrorLocation = `calculated by calculateMetadata() for the composition "${composition.id}"`;
66
+ const defaultErrorLocation = `of the "<Composition />" component with the id "${composition.id}"`;
67
+ const width = (_b = (_a = calculated === null || calculated === void 0 ? void 0 : calculated.width) !== null && _a !== void 0 ? _a : composition.width) !== null && _b !== void 0 ? _b : undefined;
68
+ (0, validate_dimensions_js_1.validateDimension)(width, 'width', (calculated === null || calculated === void 0 ? void 0 : calculated.width) ? calculateMetadataErrorLocation : defaultErrorLocation);
69
+ const height = (_d = (_c = calculated === null || calculated === void 0 ? void 0 : calculated.height) !== null && _c !== void 0 ? _c : composition.height) !== null && _d !== void 0 ? _d : undefined;
70
+ (0, validate_dimensions_js_1.validateDimension)(height, 'height', (calculated === null || calculated === void 0 ? void 0 : calculated.height) ? calculateMetadataErrorLocation : defaultErrorLocation);
78
71
  const fps = (_f = (_e = calculated === null || calculated === void 0 ? void 0 : calculated.fps) !== null && _e !== void 0 ? _e : composition.fps) !== null && _f !== void 0 ? _f : null;
79
- if (!fps) {
80
- throw new TypeError('Composition fps was neither specified via the `fps` prop nor the `calculateMetadata()` function.');
81
- }
72
+ (0, validate_fps_js_1.validateFps)(fps, (calculated === null || calculated === void 0 ? void 0 : calculated.fps) ? calculateMetadataErrorLocation : defaultErrorLocation, false);
82
73
  const durationInFrames = (_h = (_g = calculated === null || calculated === void 0 ? void 0 : calculated.durationInFrames) !== null && _g !== void 0 ? _g : composition.durationInFrames) !== null && _h !== void 0 ? _h : null;
83
- if (!durationInFrames) {
84
- throw new TypeError('Composition durationInFrames was neither specified via the `durationInFrames` prop nor the `calculateMetadata()` function.');
85
- }
86
- (0, validate_duration_in_frames_js_1.validateDurationInFrames)({
87
- durationInFrames,
88
- component: potentialErrorLocation,
74
+ (0, validate_duration_in_frames_js_1.validateDurationInFrames)(durationInFrames, {
89
75
  allowFloats: false,
76
+ component: `of the "<Composition />" component with the id "${composition.id}"`,
90
77
  });
91
78
  return { width, height, fps, durationInFrames };
92
79
  };
@@ -41,8 +41,7 @@ const Series = ({ children }) => {
41
41
  const { durationInFrames, children: _children, from, ...passedProps } = castedChild.props; // `from` is not accepted and must be filtered out if used in JS
42
42
  if (i !== flattenedChildren.length - 1 ||
43
43
  durationInFramesProp !== Infinity) {
44
- (0, validate_duration_in_frames_js_1.validateDurationInFrames)({
45
- durationInFrames: durationInFramesProp,
44
+ (0, validate_duration_in_frames_js_1.validateDurationInFrames)(durationInFramesProp, {
46
45
  component: `of a <Series.Sequence /> component`,
47
46
  allowFloats: true,
48
47
  });
@@ -52,7 +52,7 @@ function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durati
52
52
  };
53
53
  const frame = (reverse
54
54
  ? (passedDurationInFrames !== null && passedDurationInFrames !== void 0 ? passedDurationInFrames : naturalDurationGetter.get()) - passedFrame
55
- : passedFrame) - delay;
55
+ : passedFrame) - (reverse ? -delay : delay);
56
56
  const spr = (0, spring_utils_js_1.springCalculation)({
57
57
  fps,
58
58
  frame: passedDurationInFrames === undefined
@@ -49,6 +49,14 @@ const inner = (path) => {
49
49
  }
50
50
  return `/${trimLeadingSlash(path)}`;
51
51
  };
52
+ const encodeBySplitting = (path) => {
53
+ const splitBySlash = path.split('/');
54
+ const encodedArray = splitBySlash.map((element) => {
55
+ return encodeURIComponent(element);
56
+ });
57
+ const merged = encodedArray.join('/');
58
+ return merged;
59
+ };
52
60
  /**
53
61
  * @description Reference a file from the public/ folder. If the file does not appear in the autocomplete, type the path manually.
54
62
  * @see [Documentation](https://www.remotion.dev/docs/staticfile)
@@ -76,9 +84,10 @@ const staticFile = (path) => {
76
84
  }
77
85
  const includesHex = (0, exports.includesHexOfUnsafeChar)(path);
78
86
  if (includesHex.containsHex) {
79
- warnOnce(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). The encoding gets automatically handled by staticFile() `);
87
+ warnOnce(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). Since Remotion 4.0, the encoding is done by staticFile() itself. You may want to remove a encodeURIComponent() wrapping.`);
80
88
  }
81
- const preparsed = inner(encodeURIComponent(path));
89
+ const preprocessed = encodeBySplitting(path);
90
+ const preparsed = inner(preprocessed);
82
91
  if (!preparsed.startsWith('/')) {
83
92
  return `/${preparsed}`;
84
93
  }
@@ -4,7 +4,7 @@ export type PlayableMediaTag = {
4
4
  id: string;
5
5
  };
6
6
  export type TimelineContextValue = {
7
- frame: number;
7
+ frame: Record<string, number>;
8
8
  playing: boolean;
9
9
  rootId: string;
10
10
  playbackRate: number;
@@ -13,13 +13,15 @@ export type TimelineContextValue = {
13
13
  audioAndVideoTags: MutableRefObject<PlayableMediaTag[]>;
14
14
  };
15
15
  export type SetTimelineContextValue = {
16
- setFrame: (u: React.SetStateAction<number>) => void;
16
+ setFrame: (u: React.SetStateAction<Record<string, number>>) => void;
17
17
  setPlaying: (u: React.SetStateAction<boolean>) => void;
18
18
  };
19
19
  export declare const TimelineContext: import("react").Context<TimelineContextValue>;
20
20
  export declare const SetTimelineContext: import("react").Context<SetTimelineContextValue>;
21
+ export declare const persistCurrentFrame: (frame: number, composition: string) => void;
22
+ export declare const getFrameForComposition: (composition: string) => number;
21
23
  export declare const useTimelinePosition: () => number;
22
- export declare const useTimelineSetFrame: () => (u: React.SetStateAction<number>) => void;
24
+ export declare const useTimelineSetFrame: () => (u: React.SetStateAction<Record<string, number>>) => void;
23
25
  type PlayingReturnType = readonly [
24
26
  boolean,
25
27
  (u: React.SetStateAction<boolean>) => void,
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.usePlayingState = exports.useTimelineSetFrame = exports.useTimelinePosition = exports.SetTimelineContext = exports.TimelineContext = void 0;
3
+ exports.usePlayingState = exports.useTimelineSetFrame = exports.useTimelinePosition = exports.getFrameForComposition = exports.persistCurrentFrame = exports.SetTimelineContext = exports.TimelineContext = void 0;
4
4
  const react_1 = require("react");
5
5
  const use_video_js_1 = require("./use-video.js");
6
6
  exports.TimelineContext = (0, react_1.createContext)({
7
- frame: 0,
7
+ frame: {},
8
8
  playing: false,
9
9
  playbackRate: 1,
10
10
  rootId: '',
@@ -24,16 +24,34 @@ exports.SetTimelineContext = (0, react_1.createContext)({
24
24
  throw new Error('default');
25
25
  },
26
26
  });
27
+ const makeKey = (composition) => {
28
+ return `remotion.time.${composition}`;
29
+ };
30
+ const persistCurrentFrame = (frame, composition) => {
31
+ localStorage.setItem(makeKey(composition), String(frame));
32
+ };
33
+ exports.persistCurrentFrame = persistCurrentFrame;
34
+ const getFrameForComposition = (composition) => {
35
+ var _a, _b;
36
+ const frame = localStorage.getItem(makeKey(composition));
37
+ return frame
38
+ ? Number(frame)
39
+ : (_b = (typeof window === 'undefined' ? 0 : (_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0)) !== null && _b !== void 0 ? _b : 0;
40
+ };
41
+ exports.getFrameForComposition = getFrameForComposition;
27
42
  const useTimelinePosition = () => {
43
+ var _a, _b;
28
44
  const videoConfig = (0, use_video_js_1.useVideo)();
29
45
  const state = (0, react_1.useContext)(exports.TimelineContext);
30
- // A dynamically calculated duration using calculateMetadata()
31
- // may lead to the frame being bigger than the duration.
32
- // If we have the config, we clamp the frame to the duration.
33
46
  if (!videoConfig) {
34
- return state.frame;
47
+ return typeof window === 'undefined'
48
+ ? 0
49
+ : (_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0;
35
50
  }
36
- return Math.min(videoConfig.durationInFrames - 1, state.frame);
51
+ const unclamped = (_b = state.frame[videoConfig.id]) !== null && _b !== void 0 ? _b : (typeof window !== 'undefined' && window.remotion_isPlayer
52
+ ? 0
53
+ : (0, exports.getFrameForComposition)(videoConfig.id));
54
+ return Math.min(videoConfig.durationInFrames - 1, unclamped);
37
55
  };
38
56
  exports.useTimelinePosition = useTimelinePosition;
39
57
  const useTimelineSetFrame = () => {
@@ -1 +1 @@
1
- export declare const validateDimension: (amount: number, nameOfProp: string, location: string) => void;
1
+ export declare function validateDimension(amount: unknown, nameOfProp: string, location: string): asserts amount is number;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateDimension = void 0;
4
- const validateDimension = (amount, nameOfProp, location) => {
4
+ function validateDimension(amount, nameOfProp, location) {
5
5
  if (typeof amount !== 'number') {
6
6
  throw new Error(`The "${nameOfProp}" prop ${location} must be a number, but you passed a value of type ${typeof amount}`);
7
7
  }
@@ -17,5 +17,5 @@ const validateDimension = (amount, nameOfProp, location) => {
17
17
  if (amount <= 0) {
18
18
  throw new TypeError(`The "${nameOfProp}" prop ${location} must be positive, but got ${amount}.`);
19
19
  }
20
- };
20
+ }
21
21
  exports.validateDimension = validateDimension;
@@ -1,5 +1,4 @@
1
- export declare const validateDurationInFrames: ({ allowFloats, component, durationInFrames, }: {
2
- durationInFrames: number;
1
+ export declare function validateDurationInFrames(durationInFrames: unknown, options: {
3
2
  component: string;
4
3
  allowFloats: boolean;
5
- }) => void;
4
+ }): asserts durationInFrames is number;
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateDurationInFrames = void 0;
4
- const validateDurationInFrames = ({ allowFloats, component, durationInFrames, }) => {
4
+ function validateDurationInFrames(durationInFrames, options) {
5
+ const { allowFloats, component } = options;
6
+ if (typeof durationInFrames === 'undefined') {
7
+ throw new Error(`The "durationInFrames" prop ${component} is missing.`);
8
+ }
5
9
  if (typeof durationInFrames !== 'number') {
6
10
  throw new Error(`The "durationInFrames" prop ${component} must be a number, but you passed a value of type ${typeof durationInFrames}`);
7
11
  }
@@ -14,5 +18,5 @@ const validateDurationInFrames = ({ allowFloats, component, durationInFrames, })
14
18
  if (!Number.isFinite(durationInFrames)) {
15
19
  throw new TypeError(`The "durationInFrames" prop ${component} must be finite, but got ${durationInFrames}.`);
16
20
  }
17
- };
21
+ }
18
22
  exports.validateDurationInFrames = validateDurationInFrames;
@@ -1 +1 @@
1
- export declare const validateFps: (fps: number, location: string, isGif: boolean) => void;
1
+ export declare function validateFps(fps: unknown, location: string, isGif: boolean): asserts fps is number;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateFps = void 0;
4
- const validateFps = (fps, location, isGif) => {
4
+ function validateFps(fps, location, isGif) {
5
5
  if (typeof fps !== 'number') {
6
6
  throw new Error(`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`);
7
7
  }
@@ -17,5 +17,5 @@ const validateFps = (fps, location, isGif) => {
17
17
  if (isGif && fps > 50) {
18
18
  throw new TypeError(`The FPS for a GIF cannot be higher than 50. Use the --every-nth-frame option to lower the FPS: https://remotion.dev/docs/render-as-gif`);
19
19
  }
20
- };
20
+ }
21
21
  exports.validateFps = validateFps;
@@ -1 +1 @@
1
- export declare const VERSION = "4.1.0-alpha5";
1
+ export declare const VERSION = "4.1.0-alpha7";
@@ -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 = '4.1.0-alpha5';
5
+ exports.VERSION = '4.1.0-alpha7';
@@ -58,7 +58,7 @@ function truthy(value) {
58
58
  }
59
59
 
60
60
  // Automatically generated on publish
61
- const VERSION = '4.1.0-alpha5';
61
+ const VERSION = '4.1.0-alpha7';
62
62
 
63
63
  const checkMultipleRemotionVersions = () => {
64
64
  if (typeof globalThis === 'undefined') {
@@ -344,7 +344,7 @@ const EditorPropsProvider = ({ children }) => {
344
344
  return (jsx(EditorPropsContext.Provider, { value: ctx, children: children }));
345
345
  };
346
346
 
347
- const validateDimension = (amount, nameOfProp, location) => {
347
+ function validateDimension(amount, nameOfProp, location) {
348
348
  if (typeof amount !== 'number') {
349
349
  throw new Error(`The "${nameOfProp}" prop ${location} must be a number, but you passed a value of type ${typeof amount}`);
350
350
  }
@@ -360,9 +360,13 @@ const validateDimension = (amount, nameOfProp, location) => {
360
360
  if (amount <= 0) {
361
361
  throw new TypeError(`The "${nameOfProp}" prop ${location} must be positive, but got ${amount}.`);
362
362
  }
363
- };
363
+ }
364
364
 
365
- const validateDurationInFrames = ({ allowFloats, component, durationInFrames, }) => {
365
+ function validateDurationInFrames(durationInFrames, options) {
366
+ const { allowFloats, component } = options;
367
+ if (typeof durationInFrames === 'undefined') {
368
+ throw new Error(`The "durationInFrames" prop ${component} is missing.`);
369
+ }
366
370
  if (typeof durationInFrames !== 'number') {
367
371
  throw new Error(`The "durationInFrames" prop ${component} must be a number, but you passed a value of type ${typeof durationInFrames}`);
368
372
  }
@@ -375,21 +379,35 @@ const validateDurationInFrames = ({ allowFloats, component, durationInFrames, })
375
379
  if (!Number.isFinite(durationInFrames)) {
376
380
  throw new TypeError(`The "durationInFrames" prop ${component} must be finite, but got ${durationInFrames}.`);
377
381
  }
378
- };
382
+ }
379
383
 
380
- const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined, signal, }) => {
381
- var _a, _b, _c, _d, _e, _f, _g, _h;
384
+ function validateFps(fps, location, isGif) {
385
+ if (typeof fps !== 'number') {
386
+ throw new Error(`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`);
387
+ }
388
+ if (!Number.isFinite(fps)) {
389
+ throw new Error(`"fps" must be a finite, but you passed ${fps} ${location}`);
390
+ }
391
+ if (isNaN(fps)) {
392
+ throw new Error(`"fps" must not be NaN, but got ${fps} ${location}`);
393
+ }
394
+ if (fps <= 0) {
395
+ throw new TypeError(`"fps" must be positive, but got ${fps} ${location}`);
396
+ }
397
+ if (isGif && fps > 50) {
398
+ throw new TypeError(`The FPS for a GIF cannot be higher than 50. Use the --every-nth-frame option to lower the FPS: https://remotion.dev/docs/render-as-gif`);
399
+ }
400
+ }
401
+
402
+ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined, signal, inputProps, }) => {
403
+ var _a, _b, _c, _d, _e, _f, _g;
382
404
  const calculatedProm = composition.calculateMetadata
383
405
  ? composition.calculateMetadata({
384
406
  defaultProps: (_a = composition.defaultProps) !== null && _a !== void 0 ? _a : {},
385
407
  props: {
386
408
  ...((_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {}),
387
409
  ...(editorPropsOrUndefined !== null && editorPropsOrUndefined !== void 0 ? editorPropsOrUndefined : {}),
388
- ...(typeof window === 'undefined' ||
389
- getRemotionEnvironment() === 'player-development' ||
390
- getRemotionEnvironment() === 'player-production'
391
- ? {}
392
- : (_c = getInputProps()) !== null && _c !== void 0 ? _c : {}),
410
+ ...inputProps,
393
411
  },
394
412
  abortSignal: signal,
395
413
  })
@@ -422,42 +440,34 @@ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined,
422
440
  return {
423
441
  ...data,
424
442
  id: composition.id,
425
- defaultProps: (_d = composition.defaultProps) !== null && _d !== void 0 ? _d : {},
426
- props: (_e = composition.defaultProps) !== null && _e !== void 0 ? _e : {},
443
+ defaultProps: (_c = composition.defaultProps) !== null && _c !== void 0 ? _c : {},
444
+ props: {
445
+ ...((_d = composition.defaultProps) !== null && _d !== void 0 ? _d : {}),
446
+ ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}),
447
+ },
427
448
  };
428
449
  }
429
450
  return {
430
451
  ...data,
431
452
  id: composition.id,
432
- defaultProps: (_f = composition.defaultProps) !== null && _f !== void 0 ? _f : {},
433
- props: (_h = (_g = calculatedProm.props) !== null && _g !== void 0 ? _g : composition.defaultProps) !== null && _h !== void 0 ? _h : {},
453
+ defaultProps: (_e = composition.defaultProps) !== null && _e !== void 0 ? _e : {},
454
+ props: (_g = (_f = calculatedProm.props) !== null && _f !== void 0 ? _f : composition.defaultProps) !== null && _g !== void 0 ? _g : {},
434
455
  };
435
456
  };
436
457
  const validateCalculated = ({ composition, calculated, }) => {
437
458
  var _a, _b, _c, _d, _e, _f, _g, _h;
438
- const potentialErrorLocation = `calculated by calculateMetadata() for the composition "${composition.id}"`;
439
- const width = (_b = (_a = calculated === null || calculated === void 0 ? void 0 : calculated.width) !== null && _a !== void 0 ? _a : composition.width) !== null && _b !== void 0 ? _b : null;
440
- if (!width) {
441
- throw new TypeError('Composition width was neither specified via the `width` prop nor the `calculateMetadata()` function.');
442
- }
443
- validateDimension(width, 'width', potentialErrorLocation);
444
- const height = (_d = (_c = calculated === null || calculated === void 0 ? void 0 : calculated.height) !== null && _c !== void 0 ? _c : composition.height) !== null && _d !== void 0 ? _d : null;
445
- if (!height) {
446
- throw new TypeError('Composition height was neither specified via the `height` prop nor the `calculateMetadata()` function.');
447
- }
448
- validateDimension(width, 'height', potentialErrorLocation);
459
+ const calculateMetadataErrorLocation = `calculated by calculateMetadata() for the composition "${composition.id}"`;
460
+ const defaultErrorLocation = `of the "<Composition />" component with the id "${composition.id}"`;
461
+ const width = (_b = (_a = calculated === null || calculated === void 0 ? void 0 : calculated.width) !== null && _a !== void 0 ? _a : composition.width) !== null && _b !== void 0 ? _b : undefined;
462
+ validateDimension(width, 'width', (calculated === null || calculated === void 0 ? void 0 : calculated.width) ? calculateMetadataErrorLocation : defaultErrorLocation);
463
+ const height = (_d = (_c = calculated === null || calculated === void 0 ? void 0 : calculated.height) !== null && _c !== void 0 ? _c : composition.height) !== null && _d !== void 0 ? _d : undefined;
464
+ validateDimension(height, 'height', (calculated === null || calculated === void 0 ? void 0 : calculated.height) ? calculateMetadataErrorLocation : defaultErrorLocation);
449
465
  const fps = (_f = (_e = calculated === null || calculated === void 0 ? void 0 : calculated.fps) !== null && _e !== void 0 ? _e : composition.fps) !== null && _f !== void 0 ? _f : null;
450
- if (!fps) {
451
- throw new TypeError('Composition fps was neither specified via the `fps` prop nor the `calculateMetadata()` function.');
452
- }
466
+ validateFps(fps, (calculated === null || calculated === void 0 ? void 0 : calculated.fps) ? calculateMetadataErrorLocation : defaultErrorLocation, false);
453
467
  const durationInFrames = (_h = (_g = calculated === null || calculated === void 0 ? void 0 : calculated.durationInFrames) !== null && _g !== void 0 ? _g : composition.durationInFrames) !== null && _h !== void 0 ? _h : null;
454
- if (!durationInFrames) {
455
- throw new TypeError('Composition durationInFrames was neither specified via the `durationInFrames` prop nor the `calculateMetadata()` function.');
456
- }
457
- validateDurationInFrames({
458
- durationInFrames,
459
- component: potentialErrorLocation,
468
+ validateDurationInFrames(durationInFrames, {
460
469
  allowFloats: false,
470
+ component: `of the "<Composition />" component with the id "${composition.id}"`,
461
471
  });
462
472
  return { width, height, fps, durationInFrames };
463
473
  };
@@ -484,12 +494,23 @@ const ResolveCompositionConfig = ({ children }) => {
484
494
  : {};
485
495
  }, [allEditorProps, renderModalComposition]);
486
496
  const doResolution = useCallback((composition, editorProps) => {
497
+ var _a;
487
498
  const controller = new AbortController();
488
499
  if (currentCompositionMetadata) {
489
500
  return controller;
490
501
  }
502
+ const inputProps = typeof window === 'undefined' ||
503
+ getRemotionEnvironment() === 'player-development' ||
504
+ getRemotionEnvironment() === 'player-production'
505
+ ? {}
506
+ : (_a = getInputProps()) !== null && _a !== void 0 ? _a : {};
491
507
  const { signal } = controller;
492
- const promOrNot = resolveVideoConfig({ composition, editorProps, signal });
508
+ const promOrNot = resolveVideoConfig({
509
+ composition,
510
+ editorProps,
511
+ inputProps,
512
+ signal,
513
+ });
493
514
  if (typeof promOrNot === 'object' && 'then' in promOrNot) {
494
515
  setResolvedConfigs((r) => ({
495
516
  ...r,
@@ -623,7 +644,11 @@ const useResolvedVideoConfig = (preferredCompositionId) => {
623
644
  return {
624
645
  type: 'success',
625
646
  result: {
626
- ...composition,
647
+ width: composition.width,
648
+ height: composition.height,
649
+ fps: composition.fps,
650
+ id: composition.id,
651
+ durationInFrames: composition.durationInFrames,
627
652
  defaultProps: (_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {},
628
653
  props: {
629
654
  ...((_c = composition.defaultProps) !== null && _c !== void 0 ? _c : {}),
@@ -677,7 +702,7 @@ const useVideo = () => {
677
702
  };
678
703
 
679
704
  const TimelineContext = createContext({
680
- frame: 0,
705
+ frame: {},
681
706
  playing: false,
682
707
  playbackRate: 1,
683
708
  rootId: '',
@@ -697,16 +722,32 @@ const SetTimelineContext = createContext({
697
722
  throw new Error('default');
698
723
  },
699
724
  });
725
+ const makeKey = (composition) => {
726
+ return `remotion.time.${composition}`;
727
+ };
728
+ const persistCurrentFrame = (frame, composition) => {
729
+ localStorage.setItem(makeKey(composition), String(frame));
730
+ };
731
+ const getFrameForComposition = (composition) => {
732
+ var _a, _b;
733
+ const frame = localStorage.getItem(makeKey(composition));
734
+ return frame
735
+ ? Number(frame)
736
+ : (_b = (typeof window === 'undefined' ? 0 : (_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0)) !== null && _b !== void 0 ? _b : 0;
737
+ };
700
738
  const useTimelinePosition = () => {
739
+ var _a, _b;
701
740
  const videoConfig = useVideo();
702
741
  const state = useContext(TimelineContext);
703
- // A dynamically calculated duration using calculateMetadata()
704
- // may lead to the frame being bigger than the duration.
705
- // If we have the config, we clamp the frame to the duration.
706
742
  if (!videoConfig) {
707
- return state.frame;
743
+ return typeof window === 'undefined'
744
+ ? 0
745
+ : (_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0;
708
746
  }
709
- return Math.min(videoConfig.durationInFrames - 1, state.frame);
747
+ const unclamped = (_b = state.frame[videoConfig.id]) !== null && _b !== void 0 ? _b : (typeof window !== 'undefined' && window.remotion_isPlayer
748
+ ? 0
749
+ : getFrameForComposition(videoConfig.id));
750
+ return Math.min(videoConfig.durationInFrames - 1, unclamped);
710
751
  };
711
752
  const useTimelineSetFrame = () => {
712
753
  const { setFrame } = useContext(SetTimelineContext);
@@ -722,6 +763,8 @@ var TimelinePosition = /*#__PURE__*/Object.freeze({
722
763
  __proto__: null,
723
764
  TimelineContext: TimelineContext,
724
765
  SetTimelineContext: SetTimelineContext,
766
+ persistCurrentFrame: persistCurrentFrame,
767
+ getFrameForComposition: getFrameForComposition,
725
768
  useTimelinePosition: useTimelinePosition,
726
769
  useTimelineSetFrame: useTimelineSetFrame,
727
770
  usePlayingState: usePlayingState
@@ -923,8 +966,7 @@ const useCurrentFrame = () => {
923
966
  const Loop = ({ durationInFrames, times = Infinity, children, name, ...props }) => {
924
967
  const currentFrame = useCurrentFrame();
925
968
  const { durationInFrames: compDuration } = useVideoConfig();
926
- validateDurationInFrames({
927
- durationInFrames,
969
+ validateDurationInFrames(durationInFrames, {
928
970
  component: 'of the <Loop /> component',
929
971
  allowFloats: true,
930
972
  });
@@ -2399,24 +2441,6 @@ const validateDefaultAndInputProps = (defaultProps, name, compositionId) => {
2399
2441
  }
2400
2442
  };
2401
2443
 
2402
- const validateFps = (fps, location, isGif) => {
2403
- if (typeof fps !== 'number') {
2404
- throw new Error(`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`);
2405
- }
2406
- if (!Number.isFinite(fps)) {
2407
- throw new Error(`"fps" must be a finite, but you passed ${fps} ${location}`);
2408
- }
2409
- if (isNaN(fps)) {
2410
- throw new Error(`"fps" must not be NaN, but got ${fps} ${location}`);
2411
- }
2412
- if (fps <= 0) {
2413
- throw new TypeError(`"fps" must be positive, but got ${fps} ${location}`);
2414
- }
2415
- if (isGif && fps > 50) {
2416
- throw new TypeError(`The FPS for a GIF cannot be higher than 50. Use the --every-nth-frame option to lower the FPS: https://remotion.dev/docs/render-as-gif`);
2417
- }
2418
- };
2419
-
2420
2444
  const Fallback = () => {
2421
2445
  useEffect(() => {
2422
2446
  const fallback = delayRender('Waiting for Root component to unsuspend');
@@ -2451,20 +2475,12 @@ const Composition = ({ width, height, fps, durationInFrames, id, defaultProps, s
2451
2475
  throw new Error('No id for composition passed.');
2452
2476
  }
2453
2477
  validateCompositionId(id);
2454
- validateDimension(width, 'width', 'of the <Composition/> component');
2455
- validateDimension(height, 'height', 'of the <Composition/> component');
2456
- validateDurationInFrames({
2457
- durationInFrames,
2458
- component: 'of the <Composition/> component',
2459
- allowFloats: false,
2460
- });
2461
- validateFps(fps, 'as a prop of the <Composition/> component', false);
2462
2478
  validateDefaultAndInputProps(defaultProps, 'defaultProps', id);
2463
2479
  registerComposition({
2464
- durationInFrames,
2465
- fps,
2466
- height,
2467
- width,
2480
+ durationInFrames: durationInFrames !== null && durationInFrames !== void 0 ? durationInFrames : undefined,
2481
+ fps: fps !== null && fps !== void 0 ? fps : undefined,
2482
+ height: height !== null && height !== void 0 ? height : undefined,
2483
+ width: width !== null && width !== void 0 ? width : undefined,
2468
2484
  id,
2469
2485
  folderName,
2470
2486
  component: lazy,
@@ -2718,6 +2734,7 @@ class Easing {
2718
2734
  * @see [Documentation](https://www.remotion.dev/docs/freeze)
2719
2735
  */
2720
2736
  const Freeze = ({ frame, children }) => {
2737
+ const videoConfig = useVideoConfig();
2721
2738
  if (typeof frame === 'undefined') {
2722
2739
  throw new Error(`The <Freeze /> component requires a 'frame' prop, but none was passed.`);
2723
2740
  }
@@ -2738,9 +2755,11 @@ const Freeze = ({ frame, children }) => {
2738
2755
  imperativePlaying: {
2739
2756
  current: false,
2740
2757
  },
2741
- frame,
2758
+ frame: {
2759
+ [videoConfig.id]: frame,
2760
+ },
2742
2761
  };
2743
- }, [context, frame]);
2762
+ }, [context, frame, videoConfig.id]);
2744
2763
  return (jsx(TimelineContext.Provider, { value: value, children: jsx(SequenceContext.Provider, { value: null, children: children }) }));
2745
2764
  };
2746
2765
 
@@ -3461,9 +3480,8 @@ const waitForRoot = (fn) => {
3461
3480
  };
3462
3481
 
3463
3482
  const RemotionRoot = ({ children, numberOfAudioTags }) => {
3464
- var _a;
3465
3483
  const [remotionRootId] = useState(() => String(random(null)));
3466
- const [frame, setFrame] = useState((_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0);
3484
+ const [frame, setFrame] = useState({});
3467
3485
  const [playing, setPlaying] = useState(false);
3468
3486
  const imperativePlaying = useRef(false);
3469
3487
  const [fastRefreshes, setFastRefreshes] = useState(0);
@@ -3472,9 +3490,12 @@ const RemotionRoot = ({ children, numberOfAudioTags }) => {
3472
3490
  if (typeof window !== 'undefined') {
3473
3491
  // eslint-disable-next-line react-hooks/rules-of-hooks
3474
3492
  useLayoutEffect(() => {
3475
- window.remotion_setFrame = (f) => {
3493
+ window.remotion_setFrame = (f, composition) => {
3476
3494
  const id = delayRender(`Setting the current frame to ${f}`);
3477
- setFrame(f);
3495
+ setFrame((s) => ({
3496
+ ...s,
3497
+ [composition]: f,
3498
+ }));
3478
3499
  requestAnimationFrame(() => continueRender(id));
3479
3500
  };
3480
3501
  window.remotion_isPlayer = false;
@@ -3668,6 +3689,8 @@ const Internals = {
3668
3689
  REMOTION_STUDIO_CONTAINER_ELEMENT,
3669
3690
  AssetManager,
3670
3691
  bundleName: 'bundle.js',
3692
+ persistCurrentFrame,
3693
+ useTimelineSetFrame,
3671
3694
  };
3672
3695
 
3673
3696
  const flattenChildren = (children) => {
@@ -3717,8 +3740,7 @@ const Series = ({ children }) => {
3717
3740
  const { durationInFrames, children: _children, from, ...passedProps } = castedChild.props; // `from` is not accepted and must be filtered out if used in JS
3718
3741
  if (i !== flattenedChildren.length - 1 ||
3719
3742
  durationInFramesProp !== Infinity) {
3720
- validateDurationInFrames({
3721
- durationInFrames: durationInFramesProp,
3743
+ validateDurationInFrames(durationInFramesProp, {
3722
3744
  component: `of a <Series.Sequence /> component`,
3723
3745
  allowFloats: true,
3724
3746
  });
@@ -3970,7 +3992,7 @@ function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durati
3970
3992
  };
3971
3993
  const frame = (reverse
3972
3994
  ? (passedDurationInFrames !== null && passedDurationInFrames !== void 0 ? passedDurationInFrames : naturalDurationGetter.get()) - passedFrame
3973
- : passedFrame) - delay;
3995
+ : passedFrame) - (reverse ? -delay : delay);
3974
3996
  const spr = springCalculation({
3975
3997
  fps,
3976
3998
  frame: passedDurationInFrames === undefined
@@ -4036,6 +4058,14 @@ const inner = (path) => {
4036
4058
  }
4037
4059
  return `/${trimLeadingSlash(path)}`;
4038
4060
  };
4061
+ const encodeBySplitting = (path) => {
4062
+ const splitBySlash = path.split('/');
4063
+ const encodedArray = splitBySlash.map((element) => {
4064
+ return encodeURIComponent(element);
4065
+ });
4066
+ const merged = encodedArray.join('/');
4067
+ return merged;
4068
+ };
4039
4069
  /**
4040
4070
  * @description Reference a file from the public/ folder. If the file does not appear in the autocomplete, type the path manually.
4041
4071
  * @see [Documentation](https://www.remotion.dev/docs/staticfile)
@@ -4063,9 +4093,10 @@ const staticFile = (path) => {
4063
4093
  }
4064
4094
  const includesHex = includesHexOfUnsafeChar(path);
4065
4095
  if (includesHex.containsHex) {
4066
- warnOnce(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). The encoding gets automatically handled by staticFile() `);
4096
+ warnOnce(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). Since Remotion 4.0, the encoding is done by staticFile() itself. You may want to remove a encodeURIComponent() wrapping.`);
4067
4097
  }
4068
- const preparsed = inner(encodeURIComponent(path));
4098
+ const preprocessed = encodeBySplitting(path);
4099
+ const preparsed = inner(preprocessed);
4069
4100
  if (!preparsed.startsWith('/')) {
4070
4101
  return `/${preparsed}`;
4071
4102
  }
@@ -4622,7 +4653,7 @@ const Config = new Proxy(proxyObj, {
4622
4653
  console.warn('+ Replace:');
4623
4654
  console.warn('import {Config} from "@remotion/cli/config";');
4624
4655
  console.warn();
4625
- console.warn('For more information, see https://v4.remotion.dev/docs/4-0-migration.');
4656
+ console.warn('For more information, see https://www.remotion.dev/docs/4-0-migration.');
4626
4657
  process.exit(1);
4627
4658
  };
4628
4659
  },
@@ -1,4 +1,4 @@
1
1
  // Automatically generated on publish
2
- const VERSION = '4.1.0-alpha5';
2
+ const VERSION = '4.1.0-alpha7';
3
3
 
4
4
  export { VERSION };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remotion",
3
- "version": "4.1.0-alpha5",
3
+ "version": "4.1.0-alpha7",
4
4
  "description": "Render videos in React",
5
5
  "main": "dist/cjs/index.js",
6
6
  "types": "dist/cjs/index.d.ts",