remotion 4.1.0-alpha4 → 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.
Files changed (40) hide show
  1. package/dist/cjs/Composition.d.ts +24 -9
  2. package/dist/cjs/Composition.js +6 -17
  3. package/dist/cjs/CompositionManager.d.ts +11 -12
  4. package/dist/cjs/CompositionManagerContext.d.ts +4 -3
  5. package/dist/cjs/Img.d.ts +1 -1
  6. package/dist/cjs/RemotionRoot.js +6 -4
  7. package/dist/cjs/ResolveCompositionConfig.js +24 -7
  8. package/dist/cjs/Still.d.ts +1 -1
  9. package/dist/cjs/audio/Audio.d.ts +1 -1
  10. package/dist/cjs/audio/shared-audio-tags.d.ts +1 -1
  11. package/dist/cjs/freeze.js +6 -2
  12. package/dist/cjs/index.d.ts +6 -6
  13. package/dist/cjs/index.js +1 -1
  14. package/dist/cjs/internals.d.ts +62 -60
  15. package/dist/cjs/internals.js +3 -0
  16. package/dist/cjs/loop/index.js +1 -2
  17. package/dist/cjs/props-if-has-props.d.ts +2 -2
  18. package/dist/cjs/resolve-video-config.d.ts +3 -2
  19. package/dist/cjs/resolve-video-config.js +23 -33
  20. package/dist/cjs/series/index.js +2 -3
  21. package/dist/cjs/spring/index.js +1 -1
  22. package/dist/cjs/static-file.js +11 -2
  23. package/dist/cjs/timeline-position-state.d.ts +5 -3
  24. package/dist/cjs/timeline-position-state.js +25 -7
  25. package/dist/cjs/use-unsafe-video-config.js +2 -1
  26. package/dist/cjs/use-video.d.ts +1 -1
  27. package/dist/cjs/use-video.js +3 -3
  28. package/dist/cjs/validation/validate-dimensions.d.ts +1 -1
  29. package/dist/cjs/validation/validate-dimensions.js +2 -2
  30. package/dist/cjs/validation/validate-duration-in-frames.d.ts +2 -3
  31. package/dist/cjs/validation/validate-duration-in-frames.js +6 -2
  32. package/dist/cjs/validation/validate-fps.d.ts +1 -1
  33. package/dist/cjs/validation/validate-fps.js +2 -2
  34. package/dist/cjs/version.d.ts +1 -1
  35. package/dist/cjs/version.js +1 -1
  36. package/dist/cjs/video/OffthreadVideo.js +4 -2
  37. package/dist/cjs/video-config.d.ts +2 -1
  38. package/dist/esm/index.mjs +136 -99
  39. package/dist/esm/version.mjs +1 -1
  40. package/package.json +1 -1
@@ -14,7 +14,9 @@ const VideoForDevelopment_js_1 = require("./VideoForDevelopment.js");
14
14
  * @see [Documentation](https://www.remotion.dev/docs/offthreadvideo)
15
15
  */
16
16
  const OffthreadVideo = (props) => {
17
- const { startFrom, endAt, imageFormat, ...otherProps } = props;
17
+ // Should only destruct `startFrom` and `endAt` from props,
18
+ // rest gets drilled down
19
+ const { startFrom, endAt, ...otherProps } = props;
18
20
  const environment = (0, get_environment_js_1.useRemotionEnvironment)();
19
21
  const onDuration = (0, react_1.useCallback)(() => undefined, []);
20
22
  if (typeof props.src !== 'string') {
@@ -31,7 +33,7 @@ const OffthreadVideo = (props) => {
31
33
  }
32
34
  (0, validate_media_props_js_1.validateMediaProps)(props, 'Video');
33
35
  if (environment === 'rendering') {
34
- return ((0, jsx_runtime_1.jsx)(OffthreadVideoForRendering_js_1.OffthreadVideoForRendering, { imageFormat: imageFormat, ...otherProps }));
36
+ return (0, jsx_runtime_1.jsx)(OffthreadVideoForRendering_js_1.OffthreadVideoForRendering, { ...otherProps });
35
37
  }
36
38
  return ((0, jsx_runtime_1.jsx)(VideoForDevelopment_js_1.VideoForDevelopment, { onDuration: onDuration, onlyWarnForMediaSeekingError: true, ...otherProps }));
37
39
  };
@@ -4,5 +4,6 @@ export type VideoConfig = {
4
4
  fps: number;
5
5
  durationInFrames: number;
6
6
  id: string;
7
- defaultProps: Record<string, unknown> | undefined;
7
+ defaultProps: Record<string, unknown>;
8
+ props: Record<string, unknown>;
8
9
  };
@@ -58,7 +58,7 @@ function truthy(value) {
58
58
  }
59
59
 
60
60
  // Automatically generated on publish
61
- const VERSION = '4.1.0-alpha4';
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;
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
  })
@@ -398,7 +416,7 @@ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined,
398
416
  typeof calculatedProm === 'object' &&
399
417
  'then' in calculatedProm) {
400
418
  return calculatedProm.then((c) => {
401
- var _a, _b;
419
+ var _a, _b, _c;
402
420
  const { height, width, durationInFrames, fps } = validateCalculated({
403
421
  calculated: c,
404
422
  composition,
@@ -409,7 +427,8 @@ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined,
409
427
  fps,
410
428
  durationInFrames,
411
429
  id: composition.id,
412
- defaultProps: (_b = (_a = c.props) !== null && _a !== void 0 ? _a : composition.defaultProps) !== null && _b !== void 0 ? _b : {},
430
+ defaultProps: (_a = composition.defaultProps) !== null && _a !== void 0 ? _a : {},
431
+ props: (_c = (_b = c.props) !== null && _b !== void 0 ? _b : composition.defaultProps) !== null && _c !== void 0 ? _c : {},
413
432
  };
414
433
  });
415
434
  }
@@ -421,40 +440,34 @@ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined,
421
440
  return {
422
441
  ...data,
423
442
  id: composition.id,
424
- defaultProps: (_d = composition === null || composition === void 0 ? void 0 : composition.defaultProps) !== null && _d !== void 0 ? _d : {},
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
+ },
425
448
  };
426
449
  }
427
450
  return {
428
451
  ...data,
429
452
  id: composition.id,
430
- defaultProps: (_f = (_e = calculatedProm === null || calculatedProm === void 0 ? void 0 : calculatedProm.props) !== null && _e !== void 0 ? _e : composition.defaultProps) !== null && _f !== void 0 ? _f : {},
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 : {},
431
455
  };
432
456
  };
433
457
  const validateCalculated = ({ composition, calculated, }) => {
434
458
  var _a, _b, _c, _d, _e, _f, _g, _h;
435
- const potentialErrorLocation = `calculated by calculateMetadata() for the composition "${composition.id}"`;
436
- 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;
437
- if (!width) {
438
- throw new TypeError('Composition width was neither specified via the `width` prop nor the `calculateMetadata()` function.');
439
- }
440
- validateDimension(width, 'width', potentialErrorLocation);
441
- 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;
442
- if (!height) {
443
- throw new TypeError('Composition height was neither specified via the `height` prop nor the `calculateMetadata()` function.');
444
- }
445
- 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);
446
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;
447
- if (!fps) {
448
- throw new TypeError('Composition fps was neither specified via the `fps` prop nor the `calculateMetadata()` function.');
449
- }
466
+ validateFps(fps, (calculated === null || calculated === void 0 ? void 0 : calculated.fps) ? calculateMetadataErrorLocation : defaultErrorLocation, false);
450
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;
451
- if (!durationInFrames) {
452
- throw new TypeError('Composition durationInFrames was neither specified via the `durationInFrames` prop nor the `calculateMetadata()` function.');
453
- }
454
- validateDurationInFrames({
455
- durationInFrames,
456
- component: potentialErrorLocation,
468
+ validateDurationInFrames(durationInFrames, {
457
469
  allowFloats: false,
470
+ component: `of the "<Composition />" component with the id "${composition.id}"`,
458
471
  });
459
472
  return { width, height, fps, durationInFrames };
460
473
  };
@@ -481,12 +494,23 @@ const ResolveCompositionConfig = ({ children }) => {
481
494
  : {};
482
495
  }, [allEditorProps, renderModalComposition]);
483
496
  const doResolution = useCallback((composition, editorProps) => {
497
+ var _a;
484
498
  const controller = new AbortController();
485
499
  if (currentCompositionMetadata) {
486
500
  return controller;
487
501
  }
502
+ const inputProps = typeof window === 'undefined' ||
503
+ getRemotionEnvironment() === 'player-development' ||
504
+ getRemotionEnvironment() === 'player-production'
505
+ ? {}
506
+ : (_a = getInputProps()) !== null && _a !== void 0 ? _a : {};
488
507
  const { signal } = controller;
489
- const promOrNot = resolveVideoConfig({ composition, editorProps, signal });
508
+ const promOrNot = resolveVideoConfig({
509
+ composition,
510
+ editorProps,
511
+ inputProps,
512
+ signal,
513
+ });
490
514
  if (typeof promOrNot === 'object' && 'then' in promOrNot) {
491
515
  setResolvedConfigs((r) => ({
492
516
  ...r,
@@ -601,7 +625,7 @@ const useResolvedVideoConfig = (preferredCompositionId) => {
601
625
  return composition ? (_a = allEditorProps[composition.id]) !== null && _a !== void 0 ? _a : {} : {};
602
626
  }, [allEditorProps, composition]);
603
627
  return useMemo(() => {
604
- var _a, _b, _c;
628
+ var _a, _b, _c, _d;
605
629
  if (!composition) {
606
630
  return null;
607
631
  }
@@ -611,7 +635,8 @@ const useResolvedVideoConfig = (preferredCompositionId) => {
611
635
  result: {
612
636
  ...currentCompositionMetadata,
613
637
  id: composition.id,
614
- defaultProps: (_a = currentCompositionMetadata.defaultProps) !== null && _a !== void 0 ? _a : {},
638
+ props: currentCompositionMetadata.props,
639
+ defaultProps: (_a = composition.defaultProps) !== null && _a !== void 0 ? _a : {},
615
640
  },
616
641
  };
617
642
  }
@@ -619,15 +644,20 @@ const useResolvedVideoConfig = (preferredCompositionId) => {
619
644
  return {
620
645
  type: 'success',
621
646
  result: {
622
- ...composition,
623
- defaultProps: {
624
- ...((_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {}),
647
+ width: composition.width,
648
+ height: composition.height,
649
+ fps: composition.fps,
650
+ id: composition.id,
651
+ durationInFrames: composition.durationInFrames,
652
+ defaultProps: (_b = composition.defaultProps) !== null && _b !== void 0 ? _b : {},
653
+ props: {
654
+ ...((_c = composition.defaultProps) !== null && _c !== void 0 ? _c : {}),
625
655
  ...(selectedEditorProps !== null && selectedEditorProps !== void 0 ? selectedEditorProps : {}),
626
656
  ...(typeof window === 'undefined' ||
627
657
  getRemotionEnvironment() === 'player-development' ||
628
658
  getRemotionEnvironment() === 'player-production'
629
659
  ? {}
630
- : (_c = getInputProps()) !== null && _c !== void 0 ? _c : {}),
660
+ : (_d = getInputProps()) !== null && _d !== void 0 ? _d : {}),
631
661
  },
632
662
  },
633
663
  };
@@ -646,7 +676,7 @@ const useVideo = () => {
646
676
  });
647
677
  const resolved = useResolvedVideoConfig(context.currentComposition);
648
678
  return useMemo(() => {
649
- var _a;
679
+ var _a, _b;
650
680
  if (!resolved) {
651
681
  return null;
652
682
  }
@@ -661,18 +691,18 @@ const useVideo = () => {
661
691
  }
662
692
  return {
663
693
  ...resolved.result,
664
- defaultProps: selected.defaultProps,
694
+ defaultProps: (_a = selected.defaultProps) !== null && _a !== void 0 ? _a : {},
665
695
  id: selected.id,
666
696
  // We override the selected metadata with the metadata that was passed to renderMedia(),
667
697
  // and don't allow it to be changed during render anymore
668
- ...((_a = context.currentCompositionMetadata) !== null && _a !== void 0 ? _a : {}),
698
+ ...((_b = context.currentCompositionMetadata) !== null && _b !== void 0 ? _b : {}),
669
699
  component: selected.component,
670
700
  };
671
701
  }, [context.currentCompositionMetadata, resolved, selected]);
672
702
  };
673
703
 
674
704
  const TimelineContext = createContext({
675
- frame: 0,
705
+ frame: {},
676
706
  playing: false,
677
707
  playbackRate: 1,
678
708
  rootId: '',
@@ -692,16 +722,32 @@ const SetTimelineContext = createContext({
692
722
  throw new Error('default');
693
723
  },
694
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
+ };
695
738
  const useTimelinePosition = () => {
739
+ var _a, _b;
696
740
  const videoConfig = useVideo();
697
741
  const state = useContext(TimelineContext);
698
- // A dynamically calculated duration using calculateMetadata()
699
- // may lead to the frame being bigger than the duration.
700
- // If we have the config, we clamp the frame to the duration.
701
742
  if (!videoConfig) {
702
- return state.frame;
743
+ return typeof window === 'undefined'
744
+ ? 0
745
+ : (_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0;
703
746
  }
704
- 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);
705
751
  };
706
752
  const useTimelineSetFrame = () => {
707
753
  const { setFrame } = useContext(SetTimelineContext);
@@ -717,6 +763,8 @@ var TimelinePosition = /*#__PURE__*/Object.freeze({
717
763
  __proto__: null,
718
764
  TimelineContext: TimelineContext,
719
765
  SetTimelineContext: SetTimelineContext,
766
+ persistCurrentFrame: persistCurrentFrame,
767
+ getFrameForComposition: getFrameForComposition,
720
768
  useTimelinePosition: useTimelinePosition,
721
769
  useTimelineSetFrame: useTimelineSetFrame,
722
770
  usePlayingState: usePlayingState
@@ -736,7 +784,7 @@ const useUnsafeVideoConfig = () => {
736
784
  if (!video) {
737
785
  return null;
738
786
  }
739
- const { id, durationInFrames, fps, height, width, defaultProps } = video;
787
+ const { id, durationInFrames, fps, height, width, defaultProps, props } = video;
740
788
  return {
741
789
  id,
742
790
  width,
@@ -744,6 +792,7 @@ const useUnsafeVideoConfig = () => {
744
792
  fps,
745
793
  durationInFrames: ctxDuration !== null && ctxDuration !== void 0 ? ctxDuration : durationInFrames,
746
794
  defaultProps,
795
+ props,
747
796
  };
748
797
  }, [ctxDuration, video]);
749
798
  };
@@ -917,8 +966,7 @@ const useCurrentFrame = () => {
917
966
  const Loop = ({ durationInFrames, times = Infinity, children, name, ...props }) => {
918
967
  const currentFrame = useCurrentFrame();
919
968
  const { durationInFrames: compDuration } = useVideoConfig();
920
- validateDurationInFrames({
921
- durationInFrames,
969
+ validateDurationInFrames(durationInFrames, {
922
970
  component: 'of the <Loop /> component',
923
971
  allowFloats: true,
924
972
  });
@@ -2393,24 +2441,6 @@ const validateDefaultAndInputProps = (defaultProps, name, compositionId) => {
2393
2441
  }
2394
2442
  };
2395
2443
 
2396
- const validateFps = (fps, location, isGif) => {
2397
- if (typeof fps !== 'number') {
2398
- throw new Error(`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`);
2399
- }
2400
- if (!Number.isFinite(fps)) {
2401
- throw new Error(`"fps" must be a finite, but you passed ${fps} ${location}`);
2402
- }
2403
- if (isNaN(fps)) {
2404
- throw new Error(`"fps" must not be NaN, but got ${fps} ${location}`);
2405
- }
2406
- if (fps <= 0) {
2407
- throw new TypeError(`"fps" must be positive, but got ${fps} ${location}`);
2408
- }
2409
- if (isGif && fps > 50) {
2410
- 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`);
2411
- }
2412
- };
2413
-
2414
2444
  const Fallback = () => {
2415
2445
  useEffect(() => {
2416
2446
  const fallback = delayRender('Waiting for Root component to unsuspend');
@@ -2445,20 +2475,12 @@ const Composition = ({ width, height, fps, durationInFrames, id, defaultProps, s
2445
2475
  throw new Error('No id for composition passed.');
2446
2476
  }
2447
2477
  validateCompositionId(id);
2448
- validateDimension(width, 'width', 'of the <Composition/> component');
2449
- validateDimension(height, 'height', 'of the <Composition/> component');
2450
- validateDurationInFrames({
2451
- durationInFrames,
2452
- component: 'of the <Composition/> component',
2453
- allowFloats: false,
2454
- });
2455
- validateFps(fps, 'as a prop of the <Composition/> component', false);
2456
2478
  validateDefaultAndInputProps(defaultProps, 'defaultProps', id);
2457
2479
  registerComposition({
2458
- durationInFrames,
2459
- fps,
2460
- height,
2461
- 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,
2462
2484
  id,
2463
2485
  folderName,
2464
2486
  component: lazy,
@@ -2493,14 +2515,14 @@ const Composition = ({ width, height, fps, durationInFrames, id, defaultProps, s
2493
2515
  if (resolved === null || resolved.type !== 'success') {
2494
2516
  return null;
2495
2517
  }
2496
- return createPortal(jsx(ClipComposition, { children: jsx(CanUseRemotionHooksProvider, { children: jsx(Suspense, { fallback: jsx(Loading, {}), children: jsx(Comp, { ...((_a = resolved.result.defaultProps) !== null && _a !== void 0 ? _a : {}) }) }) }) }), portalNode());
2518
+ return createPortal(jsx(ClipComposition, { children: jsx(CanUseRemotionHooksProvider, { children: jsx(Suspense, { fallback: jsx(Loading, {}), children: jsx(Comp, { ...((_a = resolved.result.props) !== null && _a !== void 0 ? _a : {}) }) }) }) }), portalNode());
2497
2519
  }
2498
2520
  if (environment === 'rendering' && video && video.component === lazy) {
2499
2521
  const Comp = lazy;
2500
2522
  if (resolved === null || resolved.type !== 'success') {
2501
2523
  return null;
2502
2524
  }
2503
- return createPortal(jsx(CanUseRemotionHooksProvider, { children: jsx(Suspense, { fallback: jsx(Fallback, {}), children: jsx(Comp, { ...((_b = resolved.result.defaultProps) !== null && _b !== void 0 ? _b : {}) }) }) }), portalNode());
2525
+ return createPortal(jsx(CanUseRemotionHooksProvider, { children: jsx(Suspense, { fallback: jsx(Fallback, {}), children: jsx(Comp, { ...((_b = resolved.result.props) !== null && _b !== void 0 ? _b : {}) }) }) }), portalNode());
2504
2526
  }
2505
2527
  return null;
2506
2528
  };
@@ -2712,6 +2734,7 @@ class Easing {
2712
2734
  * @see [Documentation](https://www.remotion.dev/docs/freeze)
2713
2735
  */
2714
2736
  const Freeze = ({ frame, children }) => {
2737
+ const videoConfig = useVideoConfig();
2715
2738
  if (typeof frame === 'undefined') {
2716
2739
  throw new Error(`The <Freeze /> component requires a 'frame' prop, but none was passed.`);
2717
2740
  }
@@ -2732,9 +2755,11 @@ const Freeze = ({ frame, children }) => {
2732
2755
  imperativePlaying: {
2733
2756
  current: false,
2734
2757
  },
2735
- frame,
2758
+ frame: {
2759
+ [videoConfig.id]: frame,
2760
+ },
2736
2761
  };
2737
- }, [context, frame]);
2762
+ }, [context, frame, videoConfig.id]);
2738
2763
  return (jsx(TimelineContext.Provider, { value: value, children: jsx(SequenceContext.Provider, { value: null, children: children }) }));
2739
2764
  };
2740
2765
 
@@ -3455,9 +3480,8 @@ const waitForRoot = (fn) => {
3455
3480
  };
3456
3481
 
3457
3482
  const RemotionRoot = ({ children, numberOfAudioTags }) => {
3458
- var _a;
3459
3483
  const [remotionRootId] = useState(() => String(random(null)));
3460
- const [frame, setFrame] = useState((_a = window.remotion_initialFrame) !== null && _a !== void 0 ? _a : 0);
3484
+ const [frame, setFrame] = useState({});
3461
3485
  const [playing, setPlaying] = useState(false);
3462
3486
  const imperativePlaying = useRef(false);
3463
3487
  const [fastRefreshes, setFastRefreshes] = useState(0);
@@ -3466,9 +3490,12 @@ const RemotionRoot = ({ children, numberOfAudioTags }) => {
3466
3490
  if (typeof window !== 'undefined') {
3467
3491
  // eslint-disable-next-line react-hooks/rules-of-hooks
3468
3492
  useLayoutEffect(() => {
3469
- window.remotion_setFrame = (f) => {
3493
+ window.remotion_setFrame = (f, composition) => {
3470
3494
  const id = delayRender(`Setting the current frame to ${f}`);
3471
- setFrame(f);
3495
+ setFrame((s) => ({
3496
+ ...s,
3497
+ [composition]: f,
3498
+ }));
3472
3499
  requestAnimationFrame(() => continueRender(id));
3473
3500
  };
3474
3501
  window.remotion_isPlayer = false;
@@ -3662,6 +3689,8 @@ const Internals = {
3662
3689
  REMOTION_STUDIO_CONTAINER_ELEMENT,
3663
3690
  AssetManager,
3664
3691
  bundleName: 'bundle.js',
3692
+ persistCurrentFrame,
3693
+ useTimelineSetFrame,
3665
3694
  };
3666
3695
 
3667
3696
  const flattenChildren = (children) => {
@@ -3711,8 +3740,7 @@ const Series = ({ children }) => {
3711
3740
  const { durationInFrames, children: _children, from, ...passedProps } = castedChild.props; // `from` is not accepted and must be filtered out if used in JS
3712
3741
  if (i !== flattenedChildren.length - 1 ||
3713
3742
  durationInFramesProp !== Infinity) {
3714
- validateDurationInFrames({
3715
- durationInFrames: durationInFramesProp,
3743
+ validateDurationInFrames(durationInFramesProp, {
3716
3744
  component: `of a <Series.Sequence /> component`,
3717
3745
  allowFloats: true,
3718
3746
  });
@@ -3964,7 +3992,7 @@ function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durati
3964
3992
  };
3965
3993
  const frame = (reverse
3966
3994
  ? (passedDurationInFrames !== null && passedDurationInFrames !== void 0 ? passedDurationInFrames : naturalDurationGetter.get()) - passedFrame
3967
- : passedFrame) - delay;
3995
+ : passedFrame) - (reverse ? -delay : delay);
3968
3996
  const spr = springCalculation({
3969
3997
  fps,
3970
3998
  frame: passedDurationInFrames === undefined
@@ -4030,6 +4058,14 @@ const inner = (path) => {
4030
4058
  }
4031
4059
  return `/${trimLeadingSlash(path)}`;
4032
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
+ };
4033
4069
  /**
4034
4070
  * @description Reference a file from the public/ folder. If the file does not appear in the autocomplete, type the path manually.
4035
4071
  * @see [Documentation](https://www.remotion.dev/docs/staticfile)
@@ -4057,9 +4093,10 @@ const staticFile = (path) => {
4057
4093
  }
4058
4094
  const includesHex = includesHexOfUnsafeChar(path);
4059
4095
  if (includesHex.containsHex) {
4060
- 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.`);
4061
4097
  }
4062
- const preparsed = inner(encodeURIComponent(path));
4098
+ const preprocessed = encodeBySplitting(path);
4099
+ const preparsed = inner(preprocessed);
4063
4100
  if (!preparsed.startsWith('/')) {
4064
4101
  return `/${preparsed}`;
4065
4102
  }
@@ -4616,7 +4653,7 @@ const Config = new Proxy(proxyObj, {
4616
4653
  console.warn('+ Replace:');
4617
4654
  console.warn('import {Config} from "@remotion/cli/config";');
4618
4655
  console.warn();
4619
- 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.');
4620
4657
  process.exit(1);
4621
4658
  };
4622
4659
  },
@@ -1,4 +1,4 @@
1
1
  // Automatically generated on publish
2
- const VERSION = '4.1.0-alpha4';
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-alpha4",
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",