remotion 4.0.63 → 4.0.66

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.
@@ -24,7 +24,12 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
24
24
  const id = (0, react_1.useMemo)(() => {
25
25
  var _a;
26
26
  return `audio-${(0, random_js_1.random)((_a = props.src) !== null && _a !== void 0 ? _a : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}`;
27
- }, [props.src, sequenceContext]);
27
+ }, [
28
+ props.src,
29
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
30
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
31
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
32
+ ]);
28
33
  const { volume: volumeProp, playbackRate, allowAmplificationDuringRender, onDuration, toneFrequency, _remotionInternalNeedsDurationCalculation, acceptableTimeShiftInSeconds, ...nativeProps } = props;
29
34
  const volume = (0, volume_prop_js_1.evaluateVolume)({
30
35
  volume: volumeProp,
@@ -57,7 +57,7 @@ function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durati
57
57
  const durationProcessed = passedDurationInFrames === undefined
58
58
  ? delayProcessed
59
59
  : delayProcessed / (passedDurationInFrames / naturalDurationGetter.get());
60
- if (passedDurationInFrames && durationProcessed > passedDurationInFrames) {
60
+ if (passedDurationInFrames && delayProcessed > passedDurationInFrames) {
61
61
  return to;
62
62
  }
63
63
  const spr = (0, spring_utils_js_1.springCalculation)({
@@ -1 +1 @@
1
- export declare const VERSION = "4.0.63";
1
+ export declare const VERSION = "4.0.66";
@@ -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.0.63';
5
+ exports.VERSION = '4.0.66';
@@ -59,7 +59,7 @@ function truthy(value) {
59
59
  }
60
60
 
61
61
  // Automatically generated on publish
62
- const VERSION = '4.0.63';
62
+ const VERSION = '4.0.66';
63
63
 
64
64
  const checkMultipleRemotionVersions = () => {
65
65
  if (typeof globalThis === 'undefined') {
@@ -318,11 +318,11 @@ const CompositionManager = createContext({
318
318
  unregisterComposition: () => undefined,
319
319
  registerFolder: () => undefined,
320
320
  unregisterFolder: () => undefined,
321
- currentComposition: null,
322
- setCurrentComposition: () => undefined,
323
321
  setCurrentCompositionMetadata: () => undefined,
324
322
  folders: [],
325
323
  currentCompositionMetadata: null,
324
+ canvasContent: null,
325
+ setCanvasContent: () => undefined,
326
326
  });
327
327
 
328
328
  const problematicCharacters = {
@@ -515,6 +515,31 @@ const EditorPropsProvider = ({ children }) => {
515
515
  return (jsx(EditorPropsContext.Provider, { value: ctx, children: children }));
516
516
  };
517
517
 
518
+ const validCodecs = [
519
+ 'h264',
520
+ 'h265',
521
+ 'vp8',
522
+ 'vp9',
523
+ 'mp3',
524
+ 'aac',
525
+ 'wav',
526
+ 'prores',
527
+ 'h264-mkv',
528
+ 'gif',
529
+ ];
530
+
531
+ function validateDefaultCodec(defaultCodec, location) {
532
+ if (typeof defaultCodec === 'undefined') {
533
+ return;
534
+ }
535
+ if (typeof defaultCodec !== 'string') {
536
+ throw new TypeError(`The "defaultCodec" prop ${location} must be a string, but you passed a value of type ${typeof defaultCodec}.`);
537
+ }
538
+ if (!validCodecs.includes(defaultCodec)) {
539
+ throw new Error(`The "defaultCodec" prop ${location} must be one of ${validCodecs.join(', ')}, but you passed ${defaultCodec}.`);
540
+ }
541
+ }
542
+
518
543
  function validateDimension(amount, nameOfProp, location) {
519
544
  if (typeof amount !== 'number') {
520
545
  throw new Error(`The "${nameOfProp}" prop ${location} must be a number, but you passed a value of type ${typeof amount}`);
@@ -570,6 +595,25 @@ function validateFps(fps, location, isGif) {
570
595
  }
571
596
  }
572
597
 
598
+ const validateCalculated = ({ composition, calculated, }) => {
599
+ var _a, _b, _c, _d, _e, _f, _g, _h;
600
+ const calculateMetadataErrorLocation = `calculated by calculateMetadata() for the composition "${composition.id}"`;
601
+ const defaultErrorLocation = `of the "<Composition />" component with the id "${composition.id}"`;
602
+ 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;
603
+ validateDimension(width, 'width', (calculated === null || calculated === void 0 ? void 0 : calculated.width) ? calculateMetadataErrorLocation : defaultErrorLocation);
604
+ 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;
605
+ validateDimension(height, 'height', (calculated === null || calculated === void 0 ? void 0 : calculated.height) ? calculateMetadataErrorLocation : defaultErrorLocation);
606
+ 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;
607
+ validateFps(fps, (calculated === null || calculated === void 0 ? void 0 : calculated.fps) ? calculateMetadataErrorLocation : defaultErrorLocation, false);
608
+ 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;
609
+ validateDurationInFrames(durationInFrames, {
610
+ allowFloats: false,
611
+ component: `of the "<Composition />" component with the id "${composition.id}"`,
612
+ });
613
+ const defaultCodec = calculated === null || calculated === void 0 ? void 0 : calculated.defaultCodec;
614
+ validateDefaultCodec(defaultCodec, calculateMetadataErrorLocation);
615
+ return { width, height, fps, durationInFrames, defaultCodec };
616
+ };
573
617
  const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined, signal, inputProps, }) => {
574
618
  var _a, _b, _c, _d, _e, _f, _g;
575
619
  const calculatedProm = composition.calculateMetadata
@@ -592,7 +636,7 @@ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined,
592
636
  'then' in calculatedProm) {
593
637
  return calculatedProm.then((c) => {
594
638
  var _a, _b;
595
- const { height, width, durationInFrames, fps } = validateCalculated({
639
+ const { height, width, durationInFrames, fps, defaultCodec } = validateCalculated({
596
640
  calculated: c,
597
641
  composition,
598
642
  });
@@ -604,6 +648,7 @@ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined,
604
648
  id: composition.id,
605
649
  defaultProps: (_a = composition.defaultProps) !== null && _a !== void 0 ? _a : {},
606
650
  props: (_b = c.props) !== null && _b !== void 0 ? _b : fallbackProps,
651
+ defaultCodec: defaultCodec !== null && defaultCodec !== void 0 ? defaultCodec : null,
607
652
  };
608
653
  });
609
654
  }
@@ -617,39 +662,29 @@ const resolveVideoConfig = ({ composition, editorProps: editorPropsOrUndefined,
617
662
  id: composition.id,
618
663
  defaultProps: (_d = composition.defaultProps) !== null && _d !== void 0 ? _d : {},
619
664
  props: fallbackProps,
665
+ defaultCodec: null,
620
666
  };
621
667
  }
622
668
  return {
623
669
  ...data,
624
670
  id: composition.id,
625
671
  defaultProps: (_e = composition.defaultProps) !== null && _e !== void 0 ? _e : {},
626
- props: (_g = (_f = calculatedProm.props) !== null && _f !== void 0 ? _f : composition.defaultProps) !== null && _g !== void 0 ? _g : {},
672
+ props: (_f = calculatedProm.props) !== null && _f !== void 0 ? _f : fallbackProps,
673
+ defaultCodec: (_g = calculatedProm.defaultCodec) !== null && _g !== void 0 ? _g : null,
627
674
  };
628
675
  };
629
- const validateCalculated = ({ composition, calculated, }) => {
630
- var _a, _b, _c, _d, _e, _f, _g, _h;
631
- const calculateMetadataErrorLocation = `calculated by calculateMetadata() for the composition "${composition.id}"`;
632
- const defaultErrorLocation = `of the "<Composition />" component with the id "${composition.id}"`;
633
- 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;
634
- validateDimension(width, 'width', (calculated === null || calculated === void 0 ? void 0 : calculated.width) ? calculateMetadataErrorLocation : defaultErrorLocation);
635
- 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;
636
- validateDimension(height, 'height', (calculated === null || calculated === void 0 ? void 0 : calculated.height) ? calculateMetadataErrorLocation : defaultErrorLocation);
637
- 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;
638
- validateFps(fps, (calculated === null || calculated === void 0 ? void 0 : calculated.fps) ? calculateMetadataErrorLocation : defaultErrorLocation, false);
639
- 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;
640
- validateDurationInFrames(durationInFrames, {
641
- allowFloats: false,
642
- component: `of the "<Composition />" component with the id "${composition.id}"`,
643
- });
644
- return { width, height, fps, durationInFrames };
645
- };
646
676
 
647
677
  const ResolveCompositionContext = createContext(null);
648
678
  const resolveCompositionsRef = createRef();
679
+ const needsResolution = (composition) => {
680
+ return Boolean(composition.calculateMetadata);
681
+ };
649
682
  const ResolveCompositionConfig = ({ children }) => {
650
683
  const [currentRenderModalComposition, setCurrentRenderModalComposition] = useState(null);
651
- const { compositions, currentComposition, currentCompositionMetadata } = useContext(CompositionManager);
652
- const selectedComposition = compositions.find((c) => c.id === currentComposition);
684
+ const { compositions, canvasContent, currentCompositionMetadata } = useContext(CompositionManager);
685
+ const selectedComposition = compositions.find((c) => canvasContent &&
686
+ canvasContent.type === 'composition' &&
687
+ canvasContent.compositionId === c.id);
653
688
  const renderModalComposition = compositions.find((c) => c.id === currentRenderModalComposition);
654
689
  const { props: allEditorProps } = useContext(EditorPropsContext);
655
690
  const [resolvedConfigs, setResolvedConfigs] = useState({});
@@ -725,6 +760,7 @@ const ResolveCompositionConfig = ({ children }) => {
725
760
  }
726
761
  return controller;
727
762
  }, [currentCompositionMetadata]);
763
+ const currentComposition = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? canvasContent.compositionId : null;
728
764
  useImperativeHandle(resolveCompositionsRef, () => {
729
765
  return {
730
766
  setCurrentRenderModalComposition: (id) => {
@@ -781,13 +817,11 @@ const ResolveCompositionConfig = ({ children }) => {
781
817
  }, [compositions, resolvedConfigs]);
782
818
  return (jsx(ResolveCompositionContext.Provider, { value: resolvedConfigsIncludingStaticOnes, children: children }));
783
819
  };
784
- const needsResolution = (composition) => {
785
- return Boolean(composition.calculateMetadata);
786
- };
787
820
  const useResolvedVideoConfig = (preferredCompositionId) => {
788
821
  const context = useContext(ResolveCompositionContext);
789
822
  const { props: allEditorProps } = useContext(EditorPropsContext);
790
- const { compositions, currentComposition, currentCompositionMetadata } = useContext(CompositionManager);
823
+ const { compositions, canvasContent, currentCompositionMetadata } = useContext(CompositionManager);
824
+ const currentComposition = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? canvasContent.compositionId : null;
791
825
  const compositionId = preferredCompositionId !== null && preferredCompositionId !== void 0 ? preferredCompositionId : currentComposition;
792
826
  const composition = compositions.find((c) => c.id === compositionId);
793
827
  const selectedEditorProps = useMemo(() => {
@@ -807,6 +841,7 @@ const useResolvedVideoConfig = (preferredCompositionId) => {
807
841
  id: composition.id,
808
842
  props: currentCompositionMetadata.props,
809
843
  defaultProps: (_a = composition.defaultProps) !== null && _a !== void 0 ? _a : {},
844
+ defaultCodec: currentCompositionMetadata.defaultCodec,
810
845
  },
811
846
  };
812
847
  }
@@ -828,6 +863,7 @@ const useResolvedVideoConfig = (preferredCompositionId) => {
828
863
  ? {}
829
864
  : (_d = getInputProps()) !== null && _d !== void 0 ? _d : {}),
830
865
  },
866
+ defaultCodec: null,
831
867
  },
832
868
  };
833
869
  }
@@ -839,13 +875,15 @@ const useResolvedVideoConfig = (preferredCompositionId) => {
839
875
  };
840
876
 
841
877
  const useVideo = () => {
842
- const context = useContext(CompositionManager);
843
- const selected = context.compositions.find((c) => {
844
- return c.id === context.currentComposition;
878
+ var _a;
879
+ const { canvasContent, compositions, currentCompositionMetadata } = useContext(CompositionManager);
880
+ const selected = compositions.find((c) => {
881
+ return ((canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' &&
882
+ c.id === canvasContent.compositionId);
845
883
  });
846
- const resolved = useResolvedVideoConfig(context.currentComposition);
884
+ const resolved = useResolvedVideoConfig((_a = selected === null || selected === void 0 ? void 0 : selected.id) !== null && _a !== void 0 ? _a : null);
847
885
  return useMemo(() => {
848
- var _a, _b;
886
+ var _a;
849
887
  if (!resolved) {
850
888
  return null;
851
889
  }
@@ -864,10 +902,10 @@ const useVideo = () => {
864
902
  id: selected.id,
865
903
  // We override the selected metadata with the metadata that was passed to renderMedia(),
866
904
  // and don't allow it to be changed during render anymore
867
- ...((_b = context.currentCompositionMetadata) !== null && _b !== void 0 ? _b : {}),
905
+ ...(currentCompositionMetadata !== null && currentCompositionMetadata !== void 0 ? currentCompositionMetadata : {}),
868
906
  component: selected.component,
869
907
  };
870
- }, [context.currentCompositionMetadata, resolved, selected]);
908
+ }, [currentCompositionMetadata, resolved, selected]);
871
909
  };
872
910
 
873
911
  const TimelineContext = createContext({
@@ -953,7 +991,7 @@ const useUnsafeVideoConfig = () => {
953
991
  if (!video) {
954
992
  return null;
955
993
  }
956
- const { id, durationInFrames, fps, height, width, defaultProps, props } = video;
994
+ const { id, durationInFrames, fps, height, width, defaultProps, props, defaultCodec, } = video;
957
995
  return {
958
996
  id,
959
997
  width,
@@ -962,6 +1000,7 @@ const useUnsafeVideoConfig = () => {
962
1000
  durationInFrames: ctxDuration !== null && ctxDuration !== void 0 ? ctxDuration : durationInFrames,
963
1001
  defaultProps,
964
1002
  props,
1003
+ defaultCodec,
965
1004
  };
966
1005
  }, [ctxDuration, video]);
967
1006
  };
@@ -1082,7 +1121,9 @@ const SequenceRefForwardingFunction = ({ from = 0, durationInFrames = Infinity,
1082
1121
  nonce,
1083
1122
  loopDisplay,
1084
1123
  ]);
1085
- const endThreshold = cumulatedFrom + from + durationInFrames - 1;
1124
+ // Ceil to support floats
1125
+ // https://github.com/remotion-dev/remotion/issues/2958
1126
+ const endThreshold = Math.ceil(cumulatedFrom + from + durationInFrames - 1);
1086
1127
  const content = absoluteFrame < cumulatedFrom + from
1087
1128
  ? null
1088
1129
  : absoluteFrame > endThreshold
@@ -1102,7 +1143,7 @@ const SequenceRefForwardingFunction = ({ from = 0, durationInFrames = Infinity,
1102
1143
  };
1103
1144
  /**
1104
1145
  * @description A component that time-shifts its children and wraps them in an absolutely positioned <div>.
1105
- * @see [Documentation](https://www.remotion.dev/docs/sequence]
1146
+ * @see [Documentation](https://www.remotion.dev/docs/sequence)
1106
1147
  */
1107
1148
  const Sequence = forwardRef(SequenceRefForwardingFunction);
1108
1149
 
@@ -1318,10 +1359,18 @@ const prefetch = (src, options) => {
1318
1359
  if (!buf) {
1319
1360
  return;
1320
1361
  }
1362
+ if (!buf.type.startsWith('video/') &&
1363
+ !buf.type.startsWith('audio/') &&
1364
+ !(options === null || options === void 0 ? void 0 : options.contentType)) {
1365
+ console.warn(`Called prefetch() on ${src} which returned a "Content-Type" of ${buf.type}. Prefetched content should have a proper content type (video/... or audio/...) or a contentType passed the options of prefetch(). Otherwise, prefetching will not work properly in all browsers.`);
1366
+ }
1367
+ const actualBlob = (options === null || options === void 0 ? void 0 : options.contentType)
1368
+ ? new Blob([buf], { type: options.contentType })
1369
+ : buf;
1321
1370
  if (method === 'base64') {
1322
- return blobToBase64(buf);
1371
+ return blobToBase64(actualBlob);
1323
1372
  }
1324
- return URL.createObjectURL(buf);
1373
+ return URL.createObjectURL(actualBlob);
1325
1374
  })
1326
1375
  .then((url) => {
1327
1376
  if (canceled) {
@@ -1749,33 +1798,6 @@ const getMediaTime = ({ fps, frame, src, playbackRate, startFrom, mediaType, })
1749
1798
  const toSeconds = (time, fps) => {
1750
1799
  return Math.round((time / fps) * 100) / 100;
1751
1800
  };
1752
- const isSubsetOfDuration = (prevStartFrom, newStartFrom, prevDuration, newDuration) => {
1753
- return (prevStartFrom <= newStartFrom &&
1754
- prevStartFrom + prevDuration >= newStartFrom + newDuration);
1755
- };
1756
- const useAppendVideoFragment = ({ actualSrc: initialActualSrc, actualFrom: initialActualFrom, duration: initialDuration, fps, }) => {
1757
- const actualFromRef = useRef(initialActualFrom);
1758
- const actualDuration = useRef(initialDuration);
1759
- const actualSrc = useRef(initialActualSrc);
1760
- if (!isSubsetOfDuration || initialActualSrc !== actualSrc.current) {
1761
- actualFromRef.current = initialActualFrom;
1762
- actualDuration.current = initialDuration;
1763
- actualSrc.current = initialActualSrc;
1764
- }
1765
- const appended = appendVideoFragment({
1766
- actualSrc: actualSrc.current,
1767
- actualFrom: actualFromRef.current,
1768
- duration: actualDuration.current,
1769
- fps,
1770
- });
1771
- return appended;
1772
- };
1773
- const isIosSafari = () => {
1774
- return typeof window === 'undefined'
1775
- ? false
1776
- : /iP(ad|od|hone)/i.test(window.navigator.userAgent) &&
1777
- Boolean(navigator.userAgent.match(/Version\/[\d.]+.*Safari/));
1778
- };
1779
1801
  // https://github.com/remotion-dev/remotion/issues/1655
1780
1802
  const isIOSSafariCase = (actualSrc) => {
1781
1803
  return typeof window === 'undefined'
@@ -1806,6 +1828,33 @@ const appendVideoFragment = ({ actualSrc, actualFrom, duration, fps, }) => {
1806
1828
  actualSrc += `,${toSeconds(duration, fps)}`;
1807
1829
  return actualSrc;
1808
1830
  };
1831
+ const isSubsetOfDuration = (prevStartFrom, newStartFrom, prevDuration, newDuration) => {
1832
+ return (prevStartFrom <= newStartFrom &&
1833
+ prevStartFrom + prevDuration >= newStartFrom + newDuration);
1834
+ };
1835
+ const useAppendVideoFragment = ({ actualSrc: initialActualSrc, actualFrom: initialActualFrom, duration: initialDuration, fps, }) => {
1836
+ const actualFromRef = useRef(initialActualFrom);
1837
+ const actualDuration = useRef(initialDuration);
1838
+ const actualSrc = useRef(initialActualSrc);
1839
+ if (!isSubsetOfDuration || initialActualSrc !== actualSrc.current) {
1840
+ actualFromRef.current = initialActualFrom;
1841
+ actualDuration.current = initialDuration;
1842
+ actualSrc.current = initialActualSrc;
1843
+ }
1844
+ const appended = appendVideoFragment({
1845
+ actualSrc: actualSrc.current,
1846
+ actualFrom: actualFromRef.current,
1847
+ duration: actualDuration.current,
1848
+ fps,
1849
+ });
1850
+ return appended;
1851
+ };
1852
+ const isIosSafari = () => {
1853
+ return typeof window === 'undefined'
1854
+ ? false
1855
+ : /iP(ad|od|hone)/i.test(window.navigator.userAgent) &&
1856
+ Boolean(navigator.userAgent.match(/Version\/[\d.]+.*Safari/));
1857
+ };
1809
1858
 
1810
1859
  const alreadyWarned = {};
1811
1860
  const warnAboutNonSeekableMedia = (ref, type) => {
@@ -2389,6 +2438,7 @@ const continueRender = (handle) => {
2389
2438
  };
2390
2439
 
2391
2440
  const RenderAssetManager = createContext({
2441
+ // Must be undefined, otherwise error in Player
2392
2442
  registerRenderAsset: () => undefined,
2393
2443
  unregisterRenderAsset: () => undefined,
2394
2444
  renderAssets: [],
@@ -2435,8 +2485,13 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
2435
2485
  const id = useMemo(() => {
2436
2486
  var _a;
2437
2487
  return `audio-${random((_a = props.src) !== null && _a !== void 0 ? _a : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}`;
2438
- }, [props.src, sequenceContext]);
2439
- const { volume: volumeProp, playbackRate, allowAmplificationDuringRender, onDuration, _remotionInternalNeedsDurationCalculation, acceptableTimeShiftInSeconds, ...nativeProps } = props;
2488
+ }, [
2489
+ props.src,
2490
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
2491
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
2492
+ sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
2493
+ ]);
2494
+ const { volume: volumeProp, playbackRate, allowAmplificationDuringRender, onDuration, toneFrequency, _remotionInternalNeedsDurationCalculation, acceptableTimeShiftInSeconds, ...nativeProps } = props;
2440
2495
  const volume = evaluateVolume({
2441
2496
  volume: volumeProp,
2442
2497
  frame: volumePropFrame,
@@ -2469,6 +2524,7 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
2469
2524
  mediaFrame: frame,
2470
2525
  playbackRate: (_a = props.playbackRate) !== null && _a !== void 0 ? _a : 1,
2471
2526
  allowAmplificationDuringRender: allowAmplificationDuringRender !== null && allowAmplificationDuringRender !== void 0 ? allowAmplificationDuringRender : false,
2527
+ toneFrequency: toneFrequency !== null && toneFrequency !== void 0 ? toneFrequency : null,
2472
2528
  });
2473
2529
  return () => unregisterRenderAsset(id);
2474
2530
  }, [
@@ -2484,6 +2540,7 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
2484
2540
  playbackRate,
2485
2541
  props.playbackRate,
2486
2542
  allowAmplificationDuringRender,
2543
+ toneFrequency,
2487
2544
  ]);
2488
2545
  const { src } = props;
2489
2546
  // The <audio> tag is only rendered if the duration needs to be calculated for the `loop`
@@ -2578,6 +2635,8 @@ const AudioRefForwardingFunction = (props, ref) => {
2578
2635
  */
2579
2636
  const Audio = forwardRef(AudioRefForwardingFunction);
2580
2637
 
2638
+ const getRegex$1 = () => /^([a-zA-Z0-9-])+$/g;
2639
+ const isFolderNameValid = (name) => name.match(getRegex$1());
2581
2640
  const validateFolderName = (name) => {
2582
2641
  if (name === undefined || name === null) {
2583
2642
  throw new TypeError('You must pass a name to a <Folder />.');
@@ -2589,8 +2648,6 @@ const validateFolderName = (name) => {
2589
2648
  throw new Error(`Folder name can only contain a-z, A-Z, 0-9 and -. You passed ${name}`);
2590
2649
  }
2591
2650
  };
2592
- const getRegex$1 = () => /^([a-zA-Z0-9-])+$/g;
2593
- const isFolderNameValid = (name) => name.match(getRegex$1());
2594
2651
 
2595
2652
  const FolderContext = createContext({
2596
2653
  folderName: null,
@@ -2693,13 +2750,13 @@ const useLazyComponent = (compProps) => {
2693
2750
  return lazy;
2694
2751
  };
2695
2752
 
2753
+ const getRegex = () => /^([a-zA-Z0-9-])+$/g;
2754
+ const isCompositionIdValid = (id) => id.match(getRegex());
2696
2755
  const validateCompositionId = (id) => {
2697
2756
  if (!isCompositionIdValid(id)) {
2698
2757
  throw new Error(`Composition id can only contain a-z, A-Z, 0-9 and -. You passed ${id}`);
2699
2758
  }
2700
2759
  };
2701
- const getRegex = () => /^([a-zA-Z0-9-])+$/g;
2702
- const isCompositionIdValid = (id) => id.match(getRegex());
2703
2760
  const invalidCompositionErrorMessage = `Composition ID must match ${String(getRegex())}`;
2704
2761
 
2705
2762
  const validateDefaultAndInputProps = (defaultProps, name, compositionId) => {
@@ -2714,6 +2771,20 @@ const validateDefaultAndInputProps = (defaultProps, name, compositionId) => {
2714
2771
  }
2715
2772
  };
2716
2773
 
2774
+ const ClipComposition = ({ children }) => {
2775
+ const { clipRegion } = useContext(NativeLayersContext);
2776
+ const style = useMemo(() => {
2777
+ return {
2778
+ display: 'flex',
2779
+ flexDirection: 'row',
2780
+ opacity: clipRegion === 'hide' ? 0 : 1,
2781
+ clipPath: clipRegion && clipRegion !== 'hide'
2782
+ ? `polygon(${clipRegion.x}px ${clipRegion.y}px, ${clipRegion.x}px ${clipRegion.height + clipRegion.y}px, ${clipRegion.width + clipRegion.x}px ${clipRegion.height + clipRegion.y}px, ${clipRegion.width + clipRegion.x}px ${clipRegion.y}px)`
2783
+ : undefined,
2784
+ };
2785
+ }, [clipRegion]);
2786
+ return jsx(AbsoluteFill, { style: style, children: children });
2787
+ };
2717
2788
  const Fallback = () => {
2718
2789
  useEffect(() => {
2719
2790
  const fallback = delayRender('Waiting for Root component to unsuspend');
@@ -2799,20 +2870,6 @@ const Composition = ({ width, height, fps, durationInFrames, id, defaultProps, s
2799
2870
  }
2800
2871
  return null;
2801
2872
  };
2802
- const ClipComposition = ({ children }) => {
2803
- const { clipRegion } = useContext(NativeLayersContext);
2804
- const style = useMemo(() => {
2805
- return {
2806
- display: 'flex',
2807
- flexDirection: 'row',
2808
- opacity: clipRegion === 'hide' ? 0 : 1,
2809
- clipPath: clipRegion && clipRegion !== 'hide'
2810
- ? `polygon(${clipRegion.x}px ${clipRegion.y}px, ${clipRegion.x}px ${clipRegion.height + clipRegion.y}px, ${clipRegion.width + clipRegion.x}px ${clipRegion.height + clipRegion.y}px, ${clipRegion.width + clipRegion.x}px ${clipRegion.y}px)`
2811
- : undefined,
2812
- };
2813
- }, [clipRegion]);
2814
- return jsx(AbsoluteFill, { style: style, children: children });
2815
- };
2816
2873
 
2817
2874
  // Taken from https://github.com/facebook/react-native/blob/0b9ea60b4fee8cacc36e7160e31b91fc114dbc0d/Libraries/Animated/src/bezier.js
2818
2875
  const NEWTON_ITERATIONS = 4;
@@ -3191,8 +3248,8 @@ const CompositionManagerProvider = ({ children, numberOfAudioTags }) => {
3191
3248
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
3192
3249
  const [compositions, setCompositions] = useState([]);
3193
3250
  const currentcompositionsRef = useRef(compositions);
3194
- const [currentComposition, setCurrentComposition] = useState(null);
3195
3251
  const [folders, setFolders] = useState([]);
3252
+ const [canvasContent, setCanvasContent] = useState(null);
3196
3253
  const [currentCompositionMetadata, setCurrentCompositionMetadata] = useState(null);
3197
3254
  const updateCompositions = useCallback((
3198
3255
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -3241,29 +3298,32 @@ const CompositionManagerProvider = ({ children, numberOfAudioTags }) => {
3241
3298
  getCompositions: () => currentcompositionsRef.current,
3242
3299
  };
3243
3300
  }, []);
3244
- const composition = compositions.find((c) => c.id === currentComposition);
3301
+ const composition = compositions.find((c) => (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition'
3302
+ ? c.id === canvasContent.compositionId
3303
+ : null);
3245
3304
  const contextValue = useMemo(() => {
3246
3305
  return {
3247
3306
  compositions,
3248
3307
  registerComposition,
3249
3308
  unregisterComposition,
3250
- currentComposition,
3251
- setCurrentComposition,
3252
3309
  folders,
3253
3310
  registerFolder,
3254
3311
  unregisterFolder,
3255
3312
  currentCompositionMetadata,
3256
3313
  setCurrentCompositionMetadata,
3314
+ canvasContent,
3315
+ setCanvasContent,
3257
3316
  };
3258
3317
  }, [
3259
3318
  compositions,
3260
3319
  registerComposition,
3261
3320
  unregisterComposition,
3262
- currentComposition,
3263
3321
  folders,
3264
3322
  registerFolder,
3265
3323
  unregisterFolder,
3266
3324
  currentCompositionMetadata,
3325
+ canvasContent,
3326
+ setCanvasContent,
3267
3327
  ]);
3268
3328
  return (jsx(CompositionManager.Provider, { value: contextValue, children: jsx(SequenceManagerProvider, { children: jsx(RenderAssetManagerProvider, { children: jsx(ResolveCompositionConfig, { children: jsx(SharedAudioContextProvider, { numberOfAudioTags: numberOfAudioTags, component: (_a = composition === null || composition === void 0 ? void 0 : composition.component) !== null && _a !== void 0 ? _a : null, children: children }) }) }) }) }));
3269
3329
  };
@@ -3861,6 +3921,47 @@ const validateFrame = ({ allowFloats, durationInFrames, frame, }) => {
3861
3921
  }
3862
3922
  };
3863
3923
 
3924
+ const WATCH_REMOTION_STATIC_FILES = 'remotion_staticFilesChanged';
3925
+ /**
3926
+ * @description Watch for changes in a specific static file.
3927
+ * @param {string} fileName - The name of the static file to watch for changes.
3928
+ * @param {WatcherCallback} callback - A callback function to be called when the file changes.
3929
+ * @returns {{cancel: () => void}} A function that can be used to cancel the event listener.
3930
+ * @see [Documentation](https://www.remotion.dev/docs/watchstaticfile)
3931
+ */
3932
+ const watchStaticFile = (fileName, callback) => {
3933
+ // Check if function is called in Remotion Studio
3934
+ if (!getRemotionEnvironment().isStudio) {
3935
+ console.warn('The API is only available while using the Remotion Studio.');
3936
+ return { cancel: () => undefined };
3937
+ }
3938
+ let prevFileData = window.remotion_staticFiles.find((file) => file.name === fileName);
3939
+ // Check if the specified static file has updated or deleted
3940
+ const checkFile = (event) => {
3941
+ const staticFiles = event.detail.files;
3942
+ // Check for user specified file
3943
+ const newFileData = staticFiles.find((file) => file.name === fileName);
3944
+ if (!newFileData) {
3945
+ // File is deleted
3946
+ if (prevFileData !== undefined) {
3947
+ callback(null);
3948
+ }
3949
+ prevFileData = undefined;
3950
+ return;
3951
+ }
3952
+ if (prevFileData === undefined ||
3953
+ prevFileData.lastModified !== newFileData.lastModified) {
3954
+ callback(newFileData); // File is added or modified
3955
+ prevFileData = newFileData;
3956
+ }
3957
+ };
3958
+ window.addEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
3959
+ const cancel = () => {
3960
+ return window.removeEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
3961
+ };
3962
+ return { cancel };
3963
+ };
3964
+
3864
3965
  function useRemotionContexts() {
3865
3966
  const compositionManagerCtx = React.useContext(CompositionManager);
3866
3967
  const timelineContext = React.useContext(TimelineContext);
@@ -3904,12 +4005,11 @@ const RemotionContextProvider = (props) => {
3904
4005
  return (jsx(CanUseRemotionHooks.Provider, { value: contexts.canUseRemotionHooksContext, children: jsx(NonceContext.Provider, { value: contexts.nonceContext, children: jsx(NativeLayersContext.Provider, { value: contexts.nativeLayersContext, children: jsx(PreloadContext.Provider, { value: contexts.preloadContext, children: jsx(CompositionManager.Provider, { value: contexts.compositionManagerCtx, children: jsx(SequenceManager.Provider, { value: contexts.sequenceManagerContext, children: jsx(RenderAssetManager.Provider, { value: contexts.renderAssetManagerContext, children: jsx(ResolveCompositionContext.Provider, { value: contexts.resolveCompositionContext, children: jsx(TimelineContext.Provider, { value: contexts.timelineContext, children: jsx(SetTimelineContext.Provider, { value: contexts.setTimelineContext, children: jsx(SequenceContext.Provider, { value: contexts.sequenceContext, children: children }) }) }) }) }) }) }) }) }) }) }));
3905
4006
  };
3906
4007
 
3907
- const Timeline = TimelinePosition;
3908
4008
  // Mark them as Internals so use don't assume this is public
3909
4009
  // API and are less likely to use it
3910
4010
  const Internals = {
3911
4011
  useUnsafeVideoConfig,
3912
- Timeline,
4012
+ Timeline: TimelinePosition,
3913
4013
  CompositionManager,
3914
4014
  SequenceManager,
3915
4015
  RemotionRoot,
@@ -3968,6 +4068,8 @@ const Internals = {
3968
4068
  DATE_TOKEN,
3969
4069
  NativeLayersProvider,
3970
4070
  ClipComposition,
4071
+ isIosSafari,
4072
+ WATCH_REMOTION_STATIC_FILES,
3971
4073
  };
3972
4074
 
3973
4075
  const flattenChildren = (children) => {
@@ -4004,10 +4106,10 @@ const Series = ({ children }) => {
4004
4106
  if (castedChild.trim() === '') {
4005
4107
  return null;
4006
4108
  }
4007
- throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as it's children, but you passed a string "${castedChild}"`);
4109
+ throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as its children, but you passed a string "${castedChild}"`);
4008
4110
  }
4009
4111
  if (castedChild.type !== SeriesSequence) {
4010
- throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as it's children, but got ${castedChild} instead`);
4112
+ throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as its children, but got ${castedChild} instead`);
4011
4113
  }
4012
4114
  const debugInfo = `index = ${i}, duration = ${castedChild.props.durationInFrames}`;
4013
4115
  if (!(castedChild === null || castedChild === void 0 ? void 0 : castedChild.props.children)) {
@@ -4160,6 +4262,7 @@ function springCalculation({ from = 0, to = 1, frame, fps, config = {}, }) {
4160
4262
  return animation;
4161
4263
  }
4162
4264
 
4265
+ const cache = new Map();
4163
4266
  /**
4164
4267
  * @description The function returns how long it takes for a spring animation to settle
4165
4268
  * @see [Documentation](https://www.remotion.dev/docs/measure-spring)
@@ -4183,6 +4286,19 @@ function measureSpring({ fps, config = {}, threshold = 0.005, from = 0, to = 1,
4183
4286
  if (threshold < 0) {
4184
4287
  throw new TypeError('Threshold is below 0');
4185
4288
  }
4289
+ const cacheKey = [
4290
+ fps,
4291
+ config.damping,
4292
+ config.mass,
4293
+ config.overshootClamping,
4294
+ config.stiffness,
4295
+ from,
4296
+ to,
4297
+ threshold,
4298
+ ].join('-');
4299
+ if (cache.has(cacheKey)) {
4300
+ return cache.get(cacheKey);
4301
+ }
4186
4302
  validateFps(fps, 'to the measureSpring() function', false);
4187
4303
  const range = Math.abs(from - to);
4188
4304
  let frame = 0;
@@ -4220,6 +4336,7 @@ function measureSpring({ fps, config = {}, threshold = 0.005, from = 0, to = 1,
4220
4336
  finishedFrame = frame + 1;
4221
4337
  }
4222
4338
  }
4339
+ cache.set(cacheKey, finishedFrame);
4223
4340
  return finishedFrame;
4224
4341
  }
4225
4342
 
@@ -4267,14 +4384,19 @@ function spring({ frame: passedFrame, fps, config = {}, from = 0, to = 1, durati
4267
4384
  throw new Error('did not calculate natural duration, this is an error with Remotion. Please report');
4268
4385
  },
4269
4386
  };
4270
- const frame = (reverse
4387
+ const reverseProcessed = reverse
4271
4388
  ? (passedDurationInFrames !== null && passedDurationInFrames !== void 0 ? passedDurationInFrames : naturalDurationGetter.get()) - passedFrame
4272
- : passedFrame) - (reverse ? -delay : delay);
4389
+ : passedFrame;
4390
+ const delayProcessed = reverseProcessed + (reverse ? delay : -delay);
4391
+ const durationProcessed = passedDurationInFrames === undefined
4392
+ ? delayProcessed
4393
+ : delayProcessed / (passedDurationInFrames / naturalDurationGetter.get());
4394
+ if (passedDurationInFrames && delayProcessed > passedDurationInFrames) {
4395
+ return to;
4396
+ }
4273
4397
  const spr = springCalculation({
4274
4398
  fps,
4275
- frame: passedDurationInFrames === undefined
4276
- ? frame
4277
- : frame / (passedDurationInFrames / naturalDurationGetter.get()),
4399
+ frame: durationProcessed,
4278
4400
  config,
4279
4401
  from,
4280
4402
  to,
@@ -4302,7 +4424,7 @@ const Still = (props) => {
4302
4424
  return React.createElement((Composition), newProps);
4303
4425
  };
4304
4426
 
4305
- const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate, src, muted, allowAmplificationDuringRender, transparent = false, ...props }) => {
4427
+ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate, src, muted, allowAmplificationDuringRender, transparent = false, toneFrequency, ...props }) => {
4306
4428
  const absoluteFrame = useTimelinePosition();
4307
4429
  const frame = useCurrentFrame();
4308
4430
  const volumePropsFrame = useFrameForVolumeProp();
@@ -4352,6 +4474,7 @@ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate,
4352
4474
  mediaFrame: frame,
4353
4475
  playbackRate: playbackRate !== null && playbackRate !== void 0 ? playbackRate : 1,
4354
4476
  allowAmplificationDuringRender: allowAmplificationDuringRender !== null && allowAmplificationDuringRender !== void 0 ? allowAmplificationDuringRender : false,
4477
+ toneFrequency: toneFrequency !== null && toneFrequency !== void 0 ? toneFrequency : null,
4355
4478
  });
4356
4479
  return () => unregisterRenderAsset(id);
4357
4480
  }, [
@@ -4365,6 +4488,7 @@ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate,
4365
4488
  absoluteFrame,
4366
4489
  playbackRate,
4367
4490
  allowAmplificationDuringRender,
4491
+ toneFrequency,
4368
4492
  ]);
4369
4493
  const currentTime = useMemo(() => {
4370
4494
  return (getExpectedMediaFrameUncorrected({
@@ -4400,7 +4524,7 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
4400
4524
  const parentSequence = useContext(SequenceContext);
4401
4525
  const { volume, muted, playbackRate, onlyWarnForMediaSeekingError, src, onDuration,
4402
4526
  // @ts-expect-error
4403
- acceptableTimeShift, acceptableTimeShiftInSeconds, ...nativeProps } = props;
4527
+ acceptableTimeShift, acceptableTimeShiftInSeconds, toneFrequency, ...nativeProps } = props;
4404
4528
  if (typeof acceptableTimeShift !== 'undefined') {
4405
4529
  throw new Error('acceptableTimeShift has been removed. Use acceptableTimeShiftInSeconds instead.');
4406
4530
  }
@@ -4529,7 +4653,7 @@ const OffthreadVideo = (props) => {
4529
4653
  return (jsx(VideoForDevelopment, { onDuration: onDuration, onlyWarnForMediaSeekingError: true, ...withoutTransparent }));
4530
4654
  };
4531
4655
 
4532
- const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAmplificationDuringRender, playbackRate, onDuration, ...props }, ref) => {
4656
+ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAmplificationDuringRender, playbackRate, onDuration, toneFrequency, ...props }, ref) => {
4533
4657
  const absoluteFrame = useTimelinePosition();
4534
4658
  const frame = useCurrentFrame();
4535
4659
  const volumePropsFrame = useFrameForVolumeProp();
@@ -4581,6 +4705,7 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
4581
4705
  mediaFrame: frame,
4582
4706
  playbackRate: playbackRate !== null && playbackRate !== void 0 ? playbackRate : 1,
4583
4707
  allowAmplificationDuringRender: allowAmplificationDuringRender !== null && allowAmplificationDuringRender !== void 0 ? allowAmplificationDuringRender : false,
4708
+ toneFrequency: toneFrequency !== null && toneFrequency !== void 0 ? toneFrequency : null,
4584
4709
  });
4585
4710
  return () => unregisterRenderAsset(id);
4586
4711
  }, [
@@ -4594,6 +4719,7 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
4594
4719
  absoluteFrame,
4595
4720
  playbackRate,
4596
4721
  allowAmplificationDuringRender,
4722
+ toneFrequency,
4597
4723
  ]);
4598
4724
  useImperativeHandle(ref, () => {
4599
4725
  return videoRef.current;
@@ -4742,7 +4868,7 @@ const VideoForwardingFunction = (props, ref) => {
4742
4868
  mediaDuration,
4743
4869
  playbackRate: (_a = props.playbackRate) !== null && _a !== void 0 ? _a : 1,
4744
4870
  startFrom,
4745
- }), children: jsx(Video, { ...propsOtherThanLoop, ref: ref }) }));
4871
+ }), layout: "none", children: jsx(Video, { ...propsOtherThanLoop, ref: ref }) }));
4746
4872
  }
4747
4873
  if (typeof startFrom !== 'undefined' || typeof endAt !== 'undefined') {
4748
4874
  validateStartFromProps(startFrom, endAt);
@@ -4763,47 +4889,6 @@ const forward = forwardRef;
4763
4889
  */
4764
4890
  const Video = forward(VideoForwardingFunction);
4765
4891
 
4766
- const WATCH_REMOTION_STATIC_FILES = 'remotion_staticFilesChanged';
4767
- /**
4768
- * @description Watch for changes in a specific static file.
4769
- * @param {string} fileName - The name of the static file to watch for changes.
4770
- * @param {WatcherCallback} callback - A callback function to be called when the file changes.
4771
- * @returns {{cancel: () => void}} A function that can be used to cancel the event listener.
4772
- * @see [Documentation](https://www.remotion.dev/docs/watchstaticfile)
4773
- */
4774
- const watchStaticFile = (fileName, callback) => {
4775
- // Check if function is called in Remotion Studio
4776
- if (!getRemotionEnvironment().isStudio) {
4777
- console.warn('The API is only available while using the Remotion Studio.');
4778
- return { cancel: () => undefined };
4779
- }
4780
- let prevFileData = window.remotion_staticFiles.find((file) => file.name === fileName);
4781
- // Check if the specified static file has updated or deleted
4782
- const checkFile = (event) => {
4783
- const staticFiles = event.detail.files;
4784
- // Check for user specified file
4785
- const newFileData = staticFiles.find((file) => file.name === fileName);
4786
- if (!newFileData) {
4787
- // File is deleted
4788
- if (prevFileData !== undefined) {
4789
- callback(null);
4790
- }
4791
- prevFileData = undefined;
4792
- return;
4793
- }
4794
- if (prevFileData === undefined ||
4795
- prevFileData.lastModified !== newFileData.lastModified) {
4796
- callback(newFileData); // File is added or modified
4797
- prevFileData = newFileData;
4798
- }
4799
- };
4800
- window.addEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
4801
- const cancel = () => {
4802
- return window.removeEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
4803
- };
4804
- return { cancel };
4805
- };
4806
-
4807
4892
  checkMultipleRemotionVersions();
4808
4893
  const Experimental = {
4809
4894
  /**
@@ -1,4 +1,4 @@
1
1
  // Automatically generated on publish
2
- const VERSION = '4.0.63';
2
+ const VERSION = '4.0.66';
3
3
 
4
4
  export { VERSION };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remotion",
3
- "version": "4.0.63",
3
+ "version": "4.0.66",
4
4
  "description": "Render videos in React",
5
5
  "main": "dist/cjs/index.js",
6
6
  "types": "dist/cjs/index.d.ts",