remotion 4.0.71 → 4.0.73

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.
@@ -59,7 +59,7 @@ function truthy(value) {
59
59
  }
60
60
 
61
61
  // Automatically generated on publish
62
- const VERSION = '4.0.71';
62
+ const VERSION = '4.0.73';
63
63
 
64
64
  const checkMultipleRemotionVersions = () => {
65
65
  if (typeof globalThis === 'undefined') {
@@ -426,35 +426,6 @@ const staticFile = (path) => {
426
426
  // Must keep this file in sync with the one in packages/lambda/src/shared/serialize-props.ts!
427
427
  const DATE_TOKEN = 'remotion-date:';
428
428
  const FILE_TOKEN = 'remotion-file:';
429
- const serializeJSONWithDate = ({ data, indent, staticBase, }) => {
430
- let customDateUsed = false;
431
- let customFileUsed = false;
432
- let mapUsed = false;
433
- let setUsed = false;
434
- const serializedString = JSON.stringify(data, function (key, value) {
435
- const item = this[key];
436
- if (item instanceof Date) {
437
- customDateUsed = true;
438
- return `${DATE_TOKEN}${item.toISOString()}`;
439
- }
440
- if (item instanceof Map) {
441
- mapUsed = true;
442
- return value;
443
- }
444
- if (item instanceof Set) {
445
- setUsed = true;
446
- return value;
447
- }
448
- if (typeof item === 'string' &&
449
- staticBase !== null &&
450
- item.startsWith(staticBase)) {
451
- customFileUsed = true;
452
- return `${FILE_TOKEN}${item.replace(staticBase + '/', '')}`;
453
- }
454
- return value;
455
- }, indent);
456
- return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
457
- };
458
429
  const deserializeJSONWithCustomFields = (data) => {
459
430
  return JSON.parse(data, (_, value) => {
460
431
  if (typeof value === 'string' && value.startsWith(DATE_TOKEN)) {
@@ -1907,6 +1878,14 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
1907
1878
  const { fps } = useVideoConfig();
1908
1879
  const mediaStartsAt = useMediaStartsAt();
1909
1880
  const playbackRate = localPlaybackRate * globalPlaybackRate;
1881
+ // For short audio, a lower acceptable time shift is used
1882
+ const acceptableTimeShiftButLessThanDuration = (() => {
1883
+ var _a;
1884
+ if ((_a = mediaRef.current) === null || _a === void 0 ? void 0 : _a.duration) {
1885
+ return Math.min(mediaRef.current.duration, acceptableTimeshift !== null && acceptableTimeshift !== void 0 ? acceptableTimeshift : DEFAULT_ACCEPTABLE_TIMESHIFT);
1886
+ }
1887
+ return acceptableTimeshift;
1888
+ })();
1910
1889
  useEffect(() => {
1911
1890
  var _a;
1912
1891
  if (!playing) {
@@ -1933,13 +1912,25 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
1933
1912
  startFrom: -mediaStartsAt,
1934
1913
  mediaType,
1935
1914
  });
1915
+ console.log({
1916
+ desiredUnclampedTime,
1917
+ cur: mediaRef.current.currentTime,
1918
+ paused: mediaRef.current.paused,
1919
+ ended: mediaRef.current.ended,
1920
+ loadedStart: mediaRef.current.seekable.length > 0
1921
+ ? mediaRef.current.seekable.start(0)
1922
+ : null,
1923
+ loadedEnd: mediaRef.current.seekable.length > 0
1924
+ ? mediaRef.current.seekable.end(0)
1925
+ : null,
1926
+ });
1936
1927
  const { duration } = mediaRef.current;
1937
1928
  const shouldBeTime = !Number.isNaN(duration) && Number.isFinite(duration)
1938
1929
  ? Math.min(duration, desiredUnclampedTime)
1939
1930
  : desiredUnclampedTime;
1940
1931
  const isTime = mediaRef.current.currentTime;
1941
1932
  const timeShift = Math.abs(shouldBeTime - isTime);
1942
- if (timeShift > acceptableTimeshift) {
1933
+ if (timeShift > acceptableTimeShiftButLessThanDuration) {
1943
1934
  // If scrubbing around, adjust timing
1944
1935
  // or if time shift is bigger than 0.45sec
1945
1936
  seek(mediaRef, shouldBeTime);
@@ -1978,6 +1969,7 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
1978
1969
  localPlaybackRate,
1979
1970
  onlyWarnForMediaSeekingError,
1980
1971
  acceptableTimeshift,
1972
+ acceptableTimeShiftButLessThanDuration,
1981
1973
  ]);
1982
1974
  };
1983
1975
 
@@ -2279,7 +2271,7 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
2279
2271
  const [mediaVolume] = useMediaVolumeState();
2280
2272
  const [mediaMuted] = useMediaMutedState();
2281
2273
  const volumePropFrame = useFrameForVolumeProp();
2282
- const { volume, muted, playbackRate, shouldPreMountAudioTags, src, onDuration, acceptableTimeShiftInSeconds, _remotionInternalNeedsDurationCalculation, allowAmplificationDuringRender, name, ...nativeProps } = props;
2274
+ const { volume, muted, playbackRate, shouldPreMountAudioTags, src, onDuration, acceptableTimeShiftInSeconds, _remotionInternalNeedsDurationCalculation, _remotionInternalNativeLoopPassed, allowAmplificationDuringRender, name, ...nativeProps } = props;
2283
2275
  if (!src) {
2284
2276
  throw new TypeError("No 'src' was passed to <Audio>.");
2285
2277
  }
@@ -2288,9 +2280,16 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
2288
2280
  return {
2289
2281
  muted: muted || mediaMuted,
2290
2282
  src: preloadedSrc,
2283
+ loop: _remotionInternalNativeLoopPassed,
2291
2284
  ...nativeProps,
2292
2285
  };
2293
- }, [mediaMuted, muted, nativeProps, preloadedSrc]);
2286
+ }, [
2287
+ _remotionInternalNativeLoopPassed,
2288
+ mediaMuted,
2289
+ muted,
2290
+ nativeProps,
2291
+ preloadedSrc,
2292
+ ]);
2294
2293
  const sequenceContext = useContext(SequenceContext);
2295
2294
  // Generate a string that's as unique as possible for this asset
2296
2295
  // but at the same time deterministic. We use it to combat strict mode issues.
@@ -2492,7 +2491,7 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
2492
2491
  sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
2493
2492
  sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
2494
2493
  ]);
2495
- const { volume: volumeProp, playbackRate, allowAmplificationDuringRender, onDuration, toneFrequency, _remotionInternalNeedsDurationCalculation, acceptableTimeShiftInSeconds, name, ...nativeProps } = props;
2494
+ const { volume: volumeProp, playbackRate, allowAmplificationDuringRender, onDuration, toneFrequency, _remotionInternalNeedsDurationCalculation, _remotionInternalNativeLoopPassed, acceptableTimeShiftInSeconds, name, ...nativeProps } = props;
2496
2495
  const volume = evaluateVolume({
2497
2496
  volume: volumeProp,
2498
2497
  frame: volumePropFrame,
@@ -2584,7 +2583,7 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
2584
2583
  const AudioForRendering = forwardRef(AudioForRenderingRefForwardingFunction);
2585
2584
 
2586
2585
  const AudioRefForwardingFunction = (props, ref) => {
2587
- var _a;
2586
+ var _a, _b;
2588
2587
  const audioContext = useContext(SharedAudioContext);
2589
2588
  const { startFrom, endAt, name, ...otherProps } = props;
2590
2589
  const { loop, ...propsOtherThanLoop } = props;
@@ -2617,7 +2616,7 @@ const AudioRefForwardingFunction = (props, ref) => {
2617
2616
  mediaDuration: duration,
2618
2617
  playbackRate: (_a = props.playbackRate) !== null && _a !== void 0 ? _a : 1,
2619
2618
  startFrom,
2620
- }), children: jsx(Audio, { ...propsOtherThanLoop, ref: ref }) }));
2619
+ }), children: jsx(Audio, { ...propsOtherThanLoop, ref: ref, _remotionInternalNativeLoopPassed: true }) }));
2621
2620
  }
2622
2621
  if (typeof startFrom !== 'undefined' || typeof endAt !== 'undefined') {
2623
2622
  validateStartFromProps(startFrom, endAt);
@@ -2629,7 +2628,7 @@ const AudioRefForwardingFunction = (props, ref) => {
2629
2628
  if (environment.isRendering) {
2630
2629
  return (jsx(AudioForRendering, { onDuration: onDuration, ...props, ref: ref, onError: onError, _remotionInternalNeedsDurationCalculation: Boolean(loop) }));
2631
2630
  }
2632
- return (jsx(AudioForDevelopment, { shouldPreMountAudioTags: audioContext !== null && audioContext.numberOfAudioTags > 0, ...props, ref: ref, onError: onError, onDuration: onDuration, _remotionInternalNeedsDurationCalculation: Boolean(loop) }));
2631
+ return (jsx(AudioForDevelopment, { _remotionInternalNativeLoopPassed: (_b = props._remotionInternalNativeLoopPassed) !== null && _b !== void 0 ? _b : false, shouldPreMountAudioTags: audioContext !== null && audioContext.numberOfAudioTags > 0, ...props, ref: ref, onError: onError, onDuration: onDuration, _remotionInternalNeedsDurationCalculation: Boolean(loop) }));
2633
2632
  };
2634
2633
  /**
2635
2634
  * @description With this component, you can add audio to your video. All audio formats which are supported by Chromium are supported by the component.
@@ -3387,133 +3386,395 @@ const getPreviewDomElement = () => {
3387
3386
  return document.getElementById(REMOTION_STUDIO_CONTAINER_ELEMENT);
3388
3387
  };
3389
3388
 
3389
+ let Root = null;
3390
+ let listeners = [];
3390
3391
  /**
3391
- * Copied from:
3392
- * https://github.com/software-mansion/react-native-reanimated/blob/master/src/reanimated2/Colors.ts
3392
+ * @description This function registers the root component of the Remotion project
3393
+ * @see [Documentation](https://www.remotion.dev/docs/register-root)
3393
3394
  */
3394
- // var INTEGER = '[-+]?\\d+';
3395
- const NUMBER = '[-+]?\\d*\\.?\\d+';
3396
- const PERCENTAGE = NUMBER + '%';
3397
- function call(...args) {
3398
- return '\\(\\s*(' + args.join(')\\s*,\\s*(') + ')\\s*\\)';
3399
- }
3400
- function getMatchers() {
3401
- const cachedMatchers = {
3402
- rgb: undefined,
3403
- rgba: undefined,
3404
- hsl: undefined,
3405
- hsla: undefined,
3406
- hex3: undefined,
3407
- hex4: undefined,
3408
- hex5: undefined,
3409
- hex6: undefined,
3410
- hex8: undefined,
3411
- };
3412
- if (cachedMatchers.rgb === undefined) {
3413
- cachedMatchers.rgb = new RegExp('rgb' + call(NUMBER, NUMBER, NUMBER));
3414
- cachedMatchers.rgba = new RegExp('rgba' + call(NUMBER, NUMBER, NUMBER, NUMBER));
3415
- cachedMatchers.hsl = new RegExp('hsl' + call(NUMBER, PERCENTAGE, PERCENTAGE));
3416
- cachedMatchers.hsla = new RegExp('hsla' + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER));
3417
- cachedMatchers.hex3 = /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
3418
- cachedMatchers.hex4 =
3419
- /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
3420
- cachedMatchers.hex6 = /^#([0-9a-fA-F]{6})$/;
3421
- cachedMatchers.hex8 = /^#([0-9a-fA-F]{8})$/;
3422
- }
3423
- return cachedMatchers;
3424
- }
3425
- function hue2rgb(p, q, t) {
3426
- if (t < 0) {
3427
- t += 1;
3428
- }
3429
- if (t > 1) {
3430
- t -= 1;
3431
- }
3432
- if (t < 1 / 6) {
3433
- return p + (q - p) * 6 * t;
3395
+ const registerRoot = (comp) => {
3396
+ if (!comp) {
3397
+ throw new Error(`You must pass a React component to registerRoot(), but ${JSON.stringify(comp)} was passed.`);
3434
3398
  }
3435
- if (t < 1 / 2) {
3436
- return q;
3399
+ if (Root) {
3400
+ throw new Error('registerRoot() was called more than once.');
3437
3401
  }
3438
- if (t < 2 / 3) {
3439
- return p + (q - p) * (2 / 3 - t) * 6;
3402
+ Root = comp;
3403
+ listeners.forEach((l) => {
3404
+ l(comp);
3405
+ });
3406
+ };
3407
+ const getRoot = () => {
3408
+ return Root;
3409
+ };
3410
+ const waitForRoot = (fn) => {
3411
+ if (Root) {
3412
+ fn(Root);
3413
+ return () => undefined;
3440
3414
  }
3441
- return p;
3442
- }
3443
- function hslToRgb(h, s, l) {
3444
- const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
3445
- const p = 2 * l - q;
3446
- const r = hue2rgb(p, q, h + 1 / 3);
3447
- const g = hue2rgb(p, q, h);
3448
- const b = hue2rgb(p, q, h - 1 / 3);
3449
- return ((Math.round(r * 255) << 24) |
3450
- (Math.round(g * 255) << 16) |
3451
- (Math.round(b * 255) << 8));
3452
- }
3453
- function parse255(str) {
3454
- const int = Number.parseInt(str, 10);
3455
- if (int < 0) {
3456
- return 0;
3415
+ listeners.push(fn);
3416
+ return () => {
3417
+ listeners = listeners.filter((l) => l !== fn);
3418
+ };
3419
+ };
3420
+
3421
+ const RemotionRoot = ({ children, numberOfAudioTags }) => {
3422
+ const [remotionRootId] = useState(() => String(random(null)));
3423
+ const [frame, setFrame] = useState({});
3424
+ const [playing, setPlaying] = useState(false);
3425
+ const imperativePlaying = useRef(false);
3426
+ const [fastRefreshes, setFastRefreshes] = useState(0);
3427
+ const [playbackRate, setPlaybackRate] = useState(1);
3428
+ const audioAndVideoTags = useRef([]);
3429
+ if (typeof window !== 'undefined') {
3430
+ // eslint-disable-next-line react-hooks/rules-of-hooks
3431
+ useLayoutEffect(() => {
3432
+ window.remotion_setFrame = (f, composition) => {
3433
+ const id = delayRender(`Setting the current frame to ${f}`);
3434
+ setFrame((s) => ({
3435
+ ...s,
3436
+ [composition]: f,
3437
+ }));
3438
+ requestAnimationFrame(() => continueRender(id));
3439
+ };
3440
+ window.remotion_isPlayer = false;
3441
+ }, []);
3457
3442
  }
3458
- if (int > 255) {
3459
- return 255;
3443
+ const timelineContextValue = useMemo(() => {
3444
+ return {
3445
+ frame,
3446
+ playing,
3447
+ imperativePlaying,
3448
+ rootId: remotionRootId,
3449
+ playbackRate,
3450
+ setPlaybackRate,
3451
+ audioAndVideoTags,
3452
+ };
3453
+ }, [frame, playbackRate, playing, remotionRootId]);
3454
+ const setTimelineContextValue = useMemo(() => {
3455
+ return {
3456
+ setFrame,
3457
+ setPlaying,
3458
+ };
3459
+ }, []);
3460
+ const nonceContext = useMemo(() => {
3461
+ let counter = 0;
3462
+ return {
3463
+ getNonce: () => counter++,
3464
+ fastRefreshes,
3465
+ };
3466
+ }, [fastRefreshes]);
3467
+ useEffect(() => {
3468
+ if (typeof __webpack_module__ !== 'undefined') {
3469
+ if (__webpack_module__.hot) {
3470
+ __webpack_module__.hot.addStatusHandler((status) => {
3471
+ if (status === 'idle') {
3472
+ setFastRefreshes((i) => i + 1);
3473
+ }
3474
+ });
3475
+ }
3476
+ }
3477
+ }, []);
3478
+ return (jsx(NonceContext.Provider, { value: nonceContext, children: jsx(TimelineContext.Provider, { value: timelineContextValue, children: jsx(SetTimelineContext.Provider, { value: setTimelineContextValue, children: jsx(EditorPropsProvider, { children: jsx(PrefetchProvider, { children: jsx(NativeLayersProvider, { children: jsx(CompositionManagerProvider, { numberOfAudioTags: numberOfAudioTags, children: jsx(DurationsContextProvider, { children: children }) }) }) }) }) }) }) }));
3479
+ };
3480
+
3481
+ const getEnvVariables = () => {
3482
+ if (getRemotionEnvironment().isRendering) {
3483
+ const param = window.remotion_envVariables;
3484
+ if (!param) {
3485
+ return {};
3486
+ }
3487
+ return { ...JSON.parse(param), NODE_ENV: process.env.NODE_ENV };
3460
3488
  }
3461
- return int;
3462
- }
3463
- function parse360(str) {
3464
- const int = Number.parseFloat(str);
3465
- return (((int % 360) + 360) % 360) / 360;
3466
- }
3467
- function parse1(str) {
3468
- const num = Number.parseFloat(str);
3469
- if (num < 0) {
3470
- return 0;
3489
+ if (getRemotionEnvironment().isStudio) {
3490
+ // For the Studio, we already set the environment variables in index-html.ts.
3491
+ // We just add NODE_ENV here.
3492
+ return {
3493
+ NODE_ENV: 'development',
3494
+ };
3471
3495
  }
3472
- if (num > 1) {
3473
- return 255;
3496
+ throw new Error('Can only call getEnvVariables() if environment is `rendering` or `preview`');
3497
+ };
3498
+ const setupEnvVariables = () => {
3499
+ const env = getEnvVariables();
3500
+ if (!window.process) {
3501
+ window.process = {};
3474
3502
  }
3475
- return Math.round(num * 255);
3476
- }
3477
- function parsePercentage(str) {
3478
- // parseFloat conveniently ignores the final %
3479
- const int = Number.parseFloat(str);
3480
- if (int < 0) {
3481
- return 0;
3503
+ if (!window.process.env) {
3504
+ window.process.env = {};
3482
3505
  }
3483
- if (int > 100) {
3484
- return 1;
3506
+ Object.keys(env).forEach((key) => {
3507
+ window.process.env[key] = env[key];
3508
+ });
3509
+ };
3510
+
3511
+ const WATCH_REMOTION_STATIC_FILES = 'remotion_staticFilesChanged';
3512
+ /**
3513
+ * @description Watch for changes in a specific static file.
3514
+ * @param {string} fileName - The name of the static file to watch for changes.
3515
+ * @param {WatcherCallback} callback - A callback function to be called when the file changes.
3516
+ * @returns {{cancel: () => void}} A function that can be used to cancel the event listener.
3517
+ * @see [Documentation](https://www.remotion.dev/docs/watchstaticfile)
3518
+ */
3519
+ const watchStaticFile = (fileName, callback) => {
3520
+ // Check if function is called in Remotion Studio
3521
+ if (!getRemotionEnvironment().isStudio) {
3522
+ console.warn('The API is only available while using the Remotion Studio.');
3523
+ return { cancel: () => undefined };
3485
3524
  }
3486
- return int / 100;
3487
- }
3488
- const names = {
3489
- transparent: 0x00000000,
3490
- // http://www.w3.org/TR/css3-color/#svg-color
3491
- aliceblue: 0xf0f8ffff,
3492
- antiquewhite: 0xfaebd7ff,
3493
- aqua: 0x00ffffff,
3494
- aquamarine: 0x7fffd4ff,
3495
- azure: 0xf0ffffff,
3496
- beige: 0xf5f5dcff,
3497
- bisque: 0xffe4c4ff,
3498
- black: 0x000000ff,
3499
- blanchedalmond: 0xffebcdff,
3500
- blue: 0x0000ffff,
3501
- blueviolet: 0x8a2be2ff,
3502
- brown: 0xa52a2aff,
3503
- burlywood: 0xdeb887ff,
3504
- burntsienna: 0xea7e5dff,
3505
- cadetblue: 0x5f9ea0ff,
3506
- chartreuse: 0x7fff00ff,
3507
- chocolate: 0xd2691eff,
3508
- coral: 0xff7f50ff,
3509
- cornflowerblue: 0x6495edff,
3510
- cornsilk: 0xfff8dcff,
3511
- crimson: 0xdc143cff,
3512
- cyan: 0x00ffffff,
3513
- darkblue: 0x00008bff,
3514
- darkcyan: 0x008b8bff,
3515
- darkgoldenrod: 0xb8860bff,
3516
- darkgray: 0xa9a9a9ff,
3525
+ let prevFileData = window.remotion_staticFiles.find((file) => file.name === fileName);
3526
+ // Check if the specified static file has updated or deleted
3527
+ const checkFile = (event) => {
3528
+ const staticFiles = event.detail.files;
3529
+ // Check for user specified file
3530
+ const newFileData = staticFiles.find((file) => file.name === fileName);
3531
+ if (!newFileData) {
3532
+ // File is deleted
3533
+ if (prevFileData !== undefined) {
3534
+ callback(null);
3535
+ }
3536
+ prevFileData = undefined;
3537
+ return;
3538
+ }
3539
+ if (prevFileData === undefined ||
3540
+ prevFileData.lastModified !== newFileData.lastModified) {
3541
+ callback(newFileData); // File is added or modified
3542
+ prevFileData = newFileData;
3543
+ }
3544
+ };
3545
+ window.addEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
3546
+ const cancel = () => {
3547
+ return window.removeEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
3548
+ };
3549
+ return { cancel };
3550
+ };
3551
+
3552
+ function useRemotionContexts() {
3553
+ const compositionManagerCtx = React.useContext(CompositionManager);
3554
+ const timelineContext = React.useContext(TimelineContext);
3555
+ const setTimelineContext = React.useContext(SetTimelineContext);
3556
+ const sequenceContext = React.useContext(SequenceContext);
3557
+ const nonceContext = React.useContext(NonceContext);
3558
+ const canUseRemotionHooksContext = React.useContext(CanUseRemotionHooks);
3559
+ const nativeLayersContext = React.useContext(NativeLayersContext);
3560
+ const preloadContext = React.useContext(PreloadContext);
3561
+ const resolveCompositionContext = React.useContext(ResolveCompositionContext);
3562
+ const renderAssetManagerContext = React.useContext(RenderAssetManager);
3563
+ const sequenceManagerContext = React.useContext(SequenceManager);
3564
+ return useMemo(() => ({
3565
+ compositionManagerCtx,
3566
+ timelineContext,
3567
+ setTimelineContext,
3568
+ sequenceContext,
3569
+ nonceContext,
3570
+ canUseRemotionHooksContext,
3571
+ nativeLayersContext,
3572
+ preloadContext,
3573
+ resolveCompositionContext,
3574
+ renderAssetManagerContext,
3575
+ sequenceManagerContext,
3576
+ }), [
3577
+ compositionManagerCtx,
3578
+ nonceContext,
3579
+ sequenceContext,
3580
+ setTimelineContext,
3581
+ timelineContext,
3582
+ canUseRemotionHooksContext,
3583
+ nativeLayersContext,
3584
+ preloadContext,
3585
+ resolveCompositionContext,
3586
+ renderAssetManagerContext,
3587
+ sequenceManagerContext,
3588
+ ]);
3589
+ }
3590
+ const RemotionContextProvider = (props) => {
3591
+ const { children, contexts } = props;
3592
+ 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 }) }) }) }) }) }) }) }) }) }) }));
3593
+ };
3594
+
3595
+ // Mark them as Internals so use don't assume this is public
3596
+ // API and are less likely to use it
3597
+ const Internals = {
3598
+ useUnsafeVideoConfig,
3599
+ Timeline: TimelinePosition,
3600
+ CompositionManager,
3601
+ SequenceManager,
3602
+ RemotionRoot,
3603
+ useVideo,
3604
+ getRoot,
3605
+ useMediaVolumeState,
3606
+ useMediaMutedState,
3607
+ useLazyComponent,
3608
+ truthy,
3609
+ SequenceContext,
3610
+ useRemotionContexts,
3611
+ RemotionContextProvider,
3612
+ CSSUtils,
3613
+ setupEnvVariables,
3614
+ MediaVolumeContext,
3615
+ SetMediaVolumeContext,
3616
+ getRemotionEnvironment,
3617
+ SharedAudioContext,
3618
+ SharedAudioContextProvider,
3619
+ invalidCompositionErrorMessage,
3620
+ isCompositionIdValid,
3621
+ getPreviewDomElement,
3622
+ compositionsRef,
3623
+ portalNode,
3624
+ waitForRoot,
3625
+ CanUseRemotionHooksProvider,
3626
+ CanUseRemotionHooks,
3627
+ PrefetchProvider,
3628
+ DurationsContextProvider,
3629
+ IsPlayerContextProvider,
3630
+ useIsPlayer,
3631
+ EditorPropsProvider,
3632
+ EditorPropsContext,
3633
+ usePreload,
3634
+ NonceContext,
3635
+ resolveVideoConfig,
3636
+ useResolvedVideoConfig,
3637
+ resolveCompositionsRef,
3638
+ ResolveCompositionConfig,
3639
+ REMOTION_STUDIO_CONTAINER_ELEMENT,
3640
+ RenderAssetManager,
3641
+ persistCurrentFrame,
3642
+ useTimelineSetFrame,
3643
+ FILE_TOKEN,
3644
+ DATE_TOKEN,
3645
+ NativeLayersProvider,
3646
+ ClipComposition,
3647
+ isIosSafari,
3648
+ WATCH_REMOTION_STATIC_FILES,
3649
+ };
3650
+
3651
+ /**
3652
+ * Copied from:
3653
+ * https://github.com/software-mansion/react-native-reanimated/blob/master/src/reanimated2/Colors.ts
3654
+ */
3655
+ // var INTEGER = '[-+]?\\d+';
3656
+ const NUMBER = '[-+]?\\d*\\.?\\d+';
3657
+ const PERCENTAGE = NUMBER + '%';
3658
+ function call(...args) {
3659
+ return '\\(\\s*(' + args.join(')\\s*,\\s*(') + ')\\s*\\)';
3660
+ }
3661
+ function getMatchers() {
3662
+ const cachedMatchers = {
3663
+ rgb: undefined,
3664
+ rgba: undefined,
3665
+ hsl: undefined,
3666
+ hsla: undefined,
3667
+ hex3: undefined,
3668
+ hex4: undefined,
3669
+ hex5: undefined,
3670
+ hex6: undefined,
3671
+ hex8: undefined,
3672
+ };
3673
+ if (cachedMatchers.rgb === undefined) {
3674
+ cachedMatchers.rgb = new RegExp('rgb' + call(NUMBER, NUMBER, NUMBER));
3675
+ cachedMatchers.rgba = new RegExp('rgba' + call(NUMBER, NUMBER, NUMBER, NUMBER));
3676
+ cachedMatchers.hsl = new RegExp('hsl' + call(NUMBER, PERCENTAGE, PERCENTAGE));
3677
+ cachedMatchers.hsla = new RegExp('hsla' + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER));
3678
+ cachedMatchers.hex3 = /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
3679
+ cachedMatchers.hex4 =
3680
+ /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
3681
+ cachedMatchers.hex6 = /^#([0-9a-fA-F]{6})$/;
3682
+ cachedMatchers.hex8 = /^#([0-9a-fA-F]{8})$/;
3683
+ }
3684
+ return cachedMatchers;
3685
+ }
3686
+ function hue2rgb(p, q, t) {
3687
+ if (t < 0) {
3688
+ t += 1;
3689
+ }
3690
+ if (t > 1) {
3691
+ t -= 1;
3692
+ }
3693
+ if (t < 1 / 6) {
3694
+ return p + (q - p) * 6 * t;
3695
+ }
3696
+ if (t < 1 / 2) {
3697
+ return q;
3698
+ }
3699
+ if (t < 2 / 3) {
3700
+ return p + (q - p) * (2 / 3 - t) * 6;
3701
+ }
3702
+ return p;
3703
+ }
3704
+ function hslToRgb(h, s, l) {
3705
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
3706
+ const p = 2 * l - q;
3707
+ const r = hue2rgb(p, q, h + 1 / 3);
3708
+ const g = hue2rgb(p, q, h);
3709
+ const b = hue2rgb(p, q, h - 1 / 3);
3710
+ return ((Math.round(r * 255) << 24) |
3711
+ (Math.round(g * 255) << 16) |
3712
+ (Math.round(b * 255) << 8));
3713
+ }
3714
+ function parse255(str) {
3715
+ const int = Number.parseInt(str, 10);
3716
+ if (int < 0) {
3717
+ return 0;
3718
+ }
3719
+ if (int > 255) {
3720
+ return 255;
3721
+ }
3722
+ return int;
3723
+ }
3724
+ function parse360(str) {
3725
+ const int = Number.parseFloat(str);
3726
+ return (((int % 360) + 360) % 360) / 360;
3727
+ }
3728
+ function parse1(str) {
3729
+ const num = Number.parseFloat(str);
3730
+ if (num < 0) {
3731
+ return 0;
3732
+ }
3733
+ if (num > 1) {
3734
+ return 255;
3735
+ }
3736
+ return Math.round(num * 255);
3737
+ }
3738
+ function parsePercentage(str) {
3739
+ // parseFloat conveniently ignores the final %
3740
+ const int = Number.parseFloat(str);
3741
+ if (int < 0) {
3742
+ return 0;
3743
+ }
3744
+ if (int > 100) {
3745
+ return 1;
3746
+ }
3747
+ return int / 100;
3748
+ }
3749
+ const names = {
3750
+ transparent: 0x00000000,
3751
+ // http://www.w3.org/TR/css3-color/#svg-color
3752
+ aliceblue: 0xf0f8ffff,
3753
+ antiquewhite: 0xfaebd7ff,
3754
+ aqua: 0x00ffffff,
3755
+ aquamarine: 0x7fffd4ff,
3756
+ azure: 0xf0ffffff,
3757
+ beige: 0xf5f5dcff,
3758
+ bisque: 0xffe4c4ff,
3759
+ black: 0x000000ff,
3760
+ blanchedalmond: 0xffebcdff,
3761
+ blue: 0x0000ffff,
3762
+ blueviolet: 0x8a2be2ff,
3763
+ brown: 0xa52a2aff,
3764
+ burlywood: 0xdeb887ff,
3765
+ burntsienna: 0xea7e5dff,
3766
+ cadetblue: 0x5f9ea0ff,
3767
+ chartreuse: 0x7fff00ff,
3768
+ chocolate: 0xd2691eff,
3769
+ coral: 0xff7f50ff,
3770
+ cornflowerblue: 0x6495edff,
3771
+ cornsilk: 0xfff8dcff,
3772
+ crimson: 0xdc143cff,
3773
+ cyan: 0x00ffffff,
3774
+ darkblue: 0x00008bff,
3775
+ darkcyan: 0x008b8bff,
3776
+ darkgoldenrod: 0xb8860bff,
3777
+ darkgray: 0xa9a9a9ff,
3517
3778
  darkgreen: 0x006400ff,
3518
3779
  darkgrey: 0xa9a9a9ff,
3519
3780
  darkkhaki: 0xbdb76bff,
@@ -3683,223 +3944,101 @@ function normalizeColor(color) {
3683
3944
  'ff', // a
3684
3945
  16) >>> 0);
3685
3946
  }
3686
- }
3687
- // https://drafts.csswg.org/css-color-4/#hex-notation
3688
- if (matchers.hex8) {
3689
- if ((match = matchers.hex8.exec(color))) {
3690
- return Number.parseInt(match[1], 16) >>> 0;
3691
- }
3692
- }
3693
- if (matchers.hex4) {
3694
- if ((match = matchers.hex4.exec(color))) {
3695
- return (Number.parseInt(match[1] +
3696
- match[1] + // r
3697
- match[2] +
3698
- match[2] + // g
3699
- match[3] +
3700
- match[3] + // b
3701
- match[4] +
3702
- match[4], // a
3703
- 16) >>> 0);
3704
- }
3705
- }
3706
- if (matchers.hsl) {
3707
- if ((match = matchers.hsl.exec(color))) {
3708
- return ((hslToRgb(parse360(match[1]), // h
3709
- parsePercentage(match[2]), // s
3710
- parsePercentage(match[3])) |
3711
- 0x000000ff) >>> // a
3712
- 0);
3713
- }
3714
- }
3715
- if (matchers.hsla) {
3716
- if ((match = matchers.hsla.exec(color))) {
3717
- return ((hslToRgb(parse360(match[1]), // h
3718
- parsePercentage(match[2]), // s
3719
- parsePercentage(match[3])) |
3720
- parse1(match[4])) >>> // a
3721
- 0);
3722
- }
3723
- }
3724
- throw new Error(`invalid color string ${color} provided`);
3725
- }
3726
- const opacity = (c) => {
3727
- return ((c >> 24) & 255) / 255;
3728
- };
3729
- const red = (c) => {
3730
- return (c >> 16) & 255;
3731
- };
3732
- const green = (c) => {
3733
- return (c >> 8) & 255;
3734
- };
3735
- const blue = (c) => {
3736
- return c & 255;
3737
- };
3738
- const rgbaColor = (r, g, b, alpha) => {
3739
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
3740
- };
3741
- function processColor(color) {
3742
- const normalizedColor = normalizeColor(color);
3743
- return ((normalizedColor << 24) | (normalizedColor >>> 8)) >>> 0; // argb
3744
- }
3745
- const interpolateColorsRGB = (value, inputRange, colors) => {
3746
- const [r, g, b, a] = [red, green, blue, opacity].map((f) => {
3747
- const unrounded = interpolate(value, inputRange, colors.map((c) => f(c)), {
3748
- extrapolateLeft: 'clamp',
3749
- extrapolateRight: 'clamp',
3750
- });
3751
- if (f === opacity) {
3752
- return Number(unrounded.toFixed(3));
3753
- }
3754
- return Math.round(unrounded);
3755
- });
3756
- return rgbaColor(r, g, b, a);
3757
- };
3758
- /**
3759
- * @description This function allows you to map a range of values to colors using a concise syntax.
3760
- * @see [Documentation](https://www.remotion.dev/docs/interpolate-colors)
3761
- */
3762
- const interpolateColors = (input, inputRange, outputRange) => {
3763
- if (typeof input === 'undefined') {
3764
- throw new TypeError('input can not be undefined');
3765
- }
3766
- if (typeof inputRange === 'undefined') {
3767
- throw new TypeError('inputRange can not be undefined');
3768
- }
3769
- if (typeof outputRange === 'undefined') {
3770
- throw new TypeError('outputRange can not be undefined');
3771
- }
3772
- if (inputRange.length !== outputRange.length) {
3773
- throw new TypeError('inputRange (' +
3774
- inputRange.length +
3775
- ' values provided) and outputRange (' +
3776
- outputRange.length +
3777
- ' values provided) must have the same length');
3778
- }
3779
- const processedOutputRange = outputRange.map((c) => processColor(c));
3780
- return interpolateColorsRGB(input, inputRange, processedOutputRange);
3781
- };
3782
-
3783
- let Root = null;
3784
- let listeners = [];
3785
- /**
3786
- * @description This function registers the root component of the Remotion project
3787
- * @see [Documentation](https://www.remotion.dev/docs/register-root)
3788
- */
3789
- const registerRoot = (comp) => {
3790
- if (!comp) {
3791
- throw new Error(`You must pass a React component to registerRoot(), but ${JSON.stringify(comp)} was passed.`);
3792
- }
3793
- if (Root) {
3794
- throw new Error('registerRoot() was called more than once.');
3795
- }
3796
- Root = comp;
3797
- listeners.forEach((l) => {
3798
- l(comp);
3799
- });
3800
- };
3801
- const getRoot = () => {
3802
- return Root;
3803
- };
3804
- const waitForRoot = (fn) => {
3805
- if (Root) {
3806
- fn(Root);
3807
- return () => undefined;
3808
- }
3809
- listeners.push(fn);
3810
- return () => {
3811
- listeners = listeners.filter((l) => l !== fn);
3812
- };
3813
- };
3814
-
3815
- const RemotionRoot = ({ children, numberOfAudioTags }) => {
3816
- const [remotionRootId] = useState(() => String(random(null)));
3817
- const [frame, setFrame] = useState({});
3818
- const [playing, setPlaying] = useState(false);
3819
- const imperativePlaying = useRef(false);
3820
- const [fastRefreshes, setFastRefreshes] = useState(0);
3821
- const [playbackRate, setPlaybackRate] = useState(1);
3822
- const audioAndVideoTags = useRef([]);
3823
- if (typeof window !== 'undefined') {
3824
- // eslint-disable-next-line react-hooks/rules-of-hooks
3825
- useLayoutEffect(() => {
3826
- window.remotion_setFrame = (f, composition) => {
3827
- const id = delayRender(`Setting the current frame to ${f}`);
3828
- setFrame((s) => ({
3829
- ...s,
3830
- [composition]: f,
3831
- }));
3832
- requestAnimationFrame(() => continueRender(id));
3833
- };
3834
- window.remotion_isPlayer = false;
3835
- }, []);
3836
- }
3837
- const timelineContextValue = useMemo(() => {
3838
- return {
3839
- frame,
3840
- playing,
3841
- imperativePlaying,
3842
- rootId: remotionRootId,
3843
- playbackRate,
3844
- setPlaybackRate,
3845
- audioAndVideoTags,
3846
- };
3847
- }, [frame, playbackRate, playing, remotionRootId]);
3848
- const setTimelineContextValue = useMemo(() => {
3849
- return {
3850
- setFrame,
3851
- setPlaying,
3852
- };
3853
- }, []);
3854
- const nonceContext = useMemo(() => {
3855
- let counter = 0;
3856
- return {
3857
- getNonce: () => counter++,
3858
- fastRefreshes,
3859
- };
3860
- }, [fastRefreshes]);
3861
- useEffect(() => {
3862
- if (typeof __webpack_module__ !== 'undefined') {
3863
- if (__webpack_module__.hot) {
3864
- __webpack_module__.hot.addStatusHandler((status) => {
3865
- if (status === 'idle') {
3866
- setFastRefreshes((i) => i + 1);
3867
- }
3868
- });
3869
- }
3870
- }
3871
- }, []);
3872
- return (jsx(NonceContext.Provider, { value: nonceContext, children: jsx(TimelineContext.Provider, { value: timelineContextValue, children: jsx(SetTimelineContext.Provider, { value: setTimelineContextValue, children: jsx(EditorPropsProvider, { children: jsx(PrefetchProvider, { children: jsx(NativeLayersProvider, { children: jsx(CompositionManagerProvider, { numberOfAudioTags: numberOfAudioTags, children: jsx(DurationsContextProvider, { children: children }) }) }) }) }) }) }) }));
3873
- };
3874
-
3875
- const getEnvVariables = () => {
3876
- if (getRemotionEnvironment().isRendering) {
3877
- const param = window.remotion_envVariables;
3878
- if (!param) {
3879
- return {};
3947
+ }
3948
+ // https://drafts.csswg.org/css-color-4/#hex-notation
3949
+ if (matchers.hex8) {
3950
+ if ((match = matchers.hex8.exec(color))) {
3951
+ return Number.parseInt(match[1], 16) >>> 0;
3880
3952
  }
3881
- return { ...JSON.parse(param), NODE_ENV: process.env.NODE_ENV };
3882
3953
  }
3883
- if (getRemotionEnvironment().isStudio) {
3884
- // For the Studio, we already set the environment variables in index-html.ts.
3885
- // We just add NODE_ENV here.
3886
- return {
3887
- NODE_ENV: 'development',
3888
- };
3954
+ if (matchers.hex4) {
3955
+ if ((match = matchers.hex4.exec(color))) {
3956
+ return (Number.parseInt(match[1] +
3957
+ match[1] + // r
3958
+ match[2] +
3959
+ match[2] + // g
3960
+ match[3] +
3961
+ match[3] + // b
3962
+ match[4] +
3963
+ match[4], // a
3964
+ 16) >>> 0);
3965
+ }
3889
3966
  }
3890
- throw new Error('Can only call getEnvVariables() if environment is `rendering` or `preview`');
3891
- };
3892
- const setupEnvVariables = () => {
3893
- const env = getEnvVariables();
3894
- if (!window.process) {
3895
- window.process = {};
3967
+ if (matchers.hsl) {
3968
+ if ((match = matchers.hsl.exec(color))) {
3969
+ return ((hslToRgb(parse360(match[1]), // h
3970
+ parsePercentage(match[2]), // s
3971
+ parsePercentage(match[3])) |
3972
+ 0x000000ff) >>> // a
3973
+ 0);
3974
+ }
3896
3975
  }
3897
- if (!window.process.env) {
3898
- window.process.env = {};
3976
+ if (matchers.hsla) {
3977
+ if ((match = matchers.hsla.exec(color))) {
3978
+ return ((hslToRgb(parse360(match[1]), // h
3979
+ parsePercentage(match[2]), // s
3980
+ parsePercentage(match[3])) |
3981
+ parse1(match[4])) >>> // a
3982
+ 0);
3983
+ }
3899
3984
  }
3900
- Object.keys(env).forEach((key) => {
3901
- window.process.env[key] = env[key];
3985
+ throw new Error(`invalid color string ${color} provided`);
3986
+ }
3987
+ const opacity = (c) => {
3988
+ return ((c >> 24) & 255) / 255;
3989
+ };
3990
+ const red = (c) => {
3991
+ return (c >> 16) & 255;
3992
+ };
3993
+ const green = (c) => {
3994
+ return (c >> 8) & 255;
3995
+ };
3996
+ const blue = (c) => {
3997
+ return c & 255;
3998
+ };
3999
+ const rgbaColor = (r, g, b, alpha) => {
4000
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
4001
+ };
4002
+ function processColor(color) {
4003
+ const normalizedColor = normalizeColor(color);
4004
+ return ((normalizedColor << 24) | (normalizedColor >>> 8)) >>> 0; // argb
4005
+ }
4006
+ const interpolateColorsRGB = (value, inputRange, colors) => {
4007
+ const [r, g, b, a] = [red, green, blue, opacity].map((f) => {
4008
+ const unrounded = interpolate(value, inputRange, colors.map((c) => f(c)), {
4009
+ extrapolateLeft: 'clamp',
4010
+ extrapolateRight: 'clamp',
4011
+ });
4012
+ if (f === opacity) {
4013
+ return Number(unrounded.toFixed(3));
4014
+ }
4015
+ return Math.round(unrounded);
3902
4016
  });
4017
+ return rgbaColor(r, g, b, a);
4018
+ };
4019
+ /**
4020
+ * @description This function allows you to map a range of values to colors using a concise syntax.
4021
+ * @see [Documentation](https://www.remotion.dev/docs/interpolate-colors)
4022
+ */
4023
+ const interpolateColors = (input, inputRange, outputRange) => {
4024
+ if (typeof input === 'undefined') {
4025
+ throw new TypeError('input can not be undefined');
4026
+ }
4027
+ if (typeof inputRange === 'undefined') {
4028
+ throw new TypeError('inputRange can not be undefined');
4029
+ }
4030
+ if (typeof outputRange === 'undefined') {
4031
+ throw new TypeError('outputRange can not be undefined');
4032
+ }
4033
+ if (inputRange.length !== outputRange.length) {
4034
+ throw new TypeError('inputRange (' +
4035
+ inputRange.length +
4036
+ ' values provided) and outputRange (' +
4037
+ outputRange.length +
4038
+ ' values provided) must have the same length');
4039
+ }
4040
+ const processedOutputRange = outputRange.map((c) => processColor(c));
4041
+ return interpolateColorsRGB(input, inputRange, processedOutputRange);
3903
4042
  };
3904
4043
 
3905
4044
  const validateFrame = ({ allowFloats, durationInFrames, frame, }) => {
@@ -3923,157 +4062,6 @@ const validateFrame = ({ allowFloats, durationInFrames, frame, }) => {
3923
4062
  }
3924
4063
  };
3925
4064
 
3926
- const WATCH_REMOTION_STATIC_FILES = 'remotion_staticFilesChanged';
3927
- /**
3928
- * @description Watch for changes in a specific static file.
3929
- * @param {string} fileName - The name of the static file to watch for changes.
3930
- * @param {WatcherCallback} callback - A callback function to be called when the file changes.
3931
- * @returns {{cancel: () => void}} A function that can be used to cancel the event listener.
3932
- * @see [Documentation](https://www.remotion.dev/docs/watchstaticfile)
3933
- */
3934
- const watchStaticFile = (fileName, callback) => {
3935
- // Check if function is called in Remotion Studio
3936
- if (!getRemotionEnvironment().isStudio) {
3937
- console.warn('The API is only available while using the Remotion Studio.');
3938
- return { cancel: () => undefined };
3939
- }
3940
- let prevFileData = window.remotion_staticFiles.find((file) => file.name === fileName);
3941
- // Check if the specified static file has updated or deleted
3942
- const checkFile = (event) => {
3943
- const staticFiles = event.detail.files;
3944
- // Check for user specified file
3945
- const newFileData = staticFiles.find((file) => file.name === fileName);
3946
- if (!newFileData) {
3947
- // File is deleted
3948
- if (prevFileData !== undefined) {
3949
- callback(null);
3950
- }
3951
- prevFileData = undefined;
3952
- return;
3953
- }
3954
- if (prevFileData === undefined ||
3955
- prevFileData.lastModified !== newFileData.lastModified) {
3956
- callback(newFileData); // File is added or modified
3957
- prevFileData = newFileData;
3958
- }
3959
- };
3960
- window.addEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
3961
- const cancel = () => {
3962
- return window.removeEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
3963
- };
3964
- return { cancel };
3965
- };
3966
-
3967
- function useRemotionContexts() {
3968
- const compositionManagerCtx = React.useContext(CompositionManager);
3969
- const timelineContext = React.useContext(TimelineContext);
3970
- const setTimelineContext = React.useContext(SetTimelineContext);
3971
- const sequenceContext = React.useContext(SequenceContext);
3972
- const nonceContext = React.useContext(NonceContext);
3973
- const canUseRemotionHooksContext = React.useContext(CanUseRemotionHooks);
3974
- const nativeLayersContext = React.useContext(NativeLayersContext);
3975
- const preloadContext = React.useContext(PreloadContext);
3976
- const resolveCompositionContext = React.useContext(ResolveCompositionContext);
3977
- const renderAssetManagerContext = React.useContext(RenderAssetManager);
3978
- const sequenceManagerContext = React.useContext(SequenceManager);
3979
- return useMemo(() => ({
3980
- compositionManagerCtx,
3981
- timelineContext,
3982
- setTimelineContext,
3983
- sequenceContext,
3984
- nonceContext,
3985
- canUseRemotionHooksContext,
3986
- nativeLayersContext,
3987
- preloadContext,
3988
- resolveCompositionContext,
3989
- renderAssetManagerContext,
3990
- sequenceManagerContext,
3991
- }), [
3992
- compositionManagerCtx,
3993
- nonceContext,
3994
- sequenceContext,
3995
- setTimelineContext,
3996
- timelineContext,
3997
- canUseRemotionHooksContext,
3998
- nativeLayersContext,
3999
- preloadContext,
4000
- resolveCompositionContext,
4001
- renderAssetManagerContext,
4002
- sequenceManagerContext,
4003
- ]);
4004
- }
4005
- const RemotionContextProvider = (props) => {
4006
- const { children, contexts } = props;
4007
- 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 }) }) }) }) }) }) }) }) }) }) }));
4008
- };
4009
-
4010
- // Mark them as Internals so use don't assume this is public
4011
- // API and are less likely to use it
4012
- const Internals = {
4013
- useUnsafeVideoConfig,
4014
- Timeline: TimelinePosition,
4015
- CompositionManager,
4016
- SequenceManager,
4017
- RemotionRoot,
4018
- useVideo,
4019
- getRoot,
4020
- useMediaVolumeState,
4021
- useMediaMutedState,
4022
- useLazyComponent,
4023
- truthy,
4024
- SequenceContext,
4025
- useRemotionContexts,
4026
- RemotionContextProvider,
4027
- CSSUtils,
4028
- setupEnvVariables,
4029
- MediaVolumeContext,
4030
- SetMediaVolumeContext,
4031
- validateDurationInFrames,
4032
- validateFps,
4033
- validateDefaultAndInputProps,
4034
- validateDimension,
4035
- getRemotionEnvironment,
4036
- SharedAudioContext,
4037
- SharedAudioContextProvider,
4038
- invalidCompositionErrorMessage,
4039
- isCompositionIdValid,
4040
- getPreviewDomElement,
4041
- compositionsRef,
4042
- DELAY_RENDER_CALLSTACK_TOKEN,
4043
- portalNode,
4044
- waitForRoot,
4045
- CanUseRemotionHooksProvider,
4046
- CanUseRemotionHooks,
4047
- PrefetchProvider,
4048
- DurationsContextProvider,
4049
- IsPlayerContextProvider,
4050
- useIsPlayer,
4051
- validateFrame,
4052
- EditorPropsProvider,
4053
- EditorPropsContext,
4054
- usePreload,
4055
- processColor,
4056
- NonceContext,
4057
- resolveVideoConfig,
4058
- useResolvedVideoConfig,
4059
- resolveCompositionsRef,
4060
- ResolveCompositionConfig,
4061
- REMOTION_STUDIO_CONTAINER_ELEMENT,
4062
- RenderAssetManager,
4063
- bundleName: 'bundle.js',
4064
- bundleMapName: 'bundle.js.map',
4065
- persistCurrentFrame,
4066
- useTimelineSetFrame,
4067
- serializeJSONWithDate,
4068
- deserializeJSONWithCustomFields,
4069
- FILE_TOKEN,
4070
- DATE_TOKEN,
4071
- NativeLayersProvider,
4072
- ClipComposition,
4073
- isIosSafari,
4074
- WATCH_REMOTION_STATIC_FILES,
4075
- };
4076
-
4077
4065
  const flattenChildren = (children) => {
4078
4066
  const childrenArray = React.Children.toArray(children);
4079
4067
  return childrenArray.reduce((flatChildren, child) => {
@@ -4526,7 +4514,7 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
4526
4514
  const parentSequence = useContext(SequenceContext);
4527
4515
  const { volume, muted, playbackRate, onlyWarnForMediaSeekingError, src, onDuration,
4528
4516
  // @ts-expect-error
4529
- acceptableTimeShift, acceptableTimeShiftInSeconds, toneFrequency, name, ...nativeProps } = props;
4517
+ acceptableTimeShift, acceptableTimeShiftInSeconds, toneFrequency, name, _remotionInternalNativeLoopPassed, ...nativeProps } = props;
4530
4518
  if (typeof acceptableTimeShift !== 'undefined') {
4531
4519
  throw new Error('acceptableTimeShift has been removed. Use acceptableTimeShiftInSeconds instead.');
4532
4520
  }
@@ -4634,7 +4622,7 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
4634
4622
  current.preload = 'auto';
4635
4623
  }
4636
4624
  }, []);
4637
- return (jsx("video", { ref: videoRef, muted: muted || mediaMuted, playsInline: true, src: actualSrc, ...nativeProps }));
4625
+ return (jsx("video", { ref: videoRef, muted: muted || mediaMuted, playsInline: true, src: actualSrc, loop: _remotionInternalNativeLoopPassed, ...nativeProps }));
4638
4626
  };
4639
4627
  // Copy types from forwardRef but not necessary to remove ref
4640
4628
  const VideoForDevelopment = forwardRef(VideoForDevelopmentRefForwardingFunction);
@@ -4666,10 +4654,10 @@ const OffthreadVideo = (props) => {
4666
4654
  return jsx(OffthreadVideoForRendering, { ...otherProps });
4667
4655
  }
4668
4656
  const { transparent, ...withoutTransparent } = otherProps;
4669
- return (jsx(VideoForDevelopment, { onDuration: onDuration, onlyWarnForMediaSeekingError: true, ...withoutTransparent }));
4657
+ return (jsx(VideoForDevelopment, { _remotionInternalNativeLoopPassed: false, onDuration: onDuration, onlyWarnForMediaSeekingError: true, ...withoutTransparent }));
4670
4658
  };
4671
4659
 
4672
- const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAmplificationDuringRender, playbackRate, onDuration, toneFrequency, name, ...props }, ref) => {
4660
+ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAmplificationDuringRender, playbackRate, onDuration, toneFrequency, name, acceptableTimeShiftInSeconds, ...props }, ref) => {
4673
4661
  const absoluteFrame = useTimelinePosition();
4674
4662
  const frame = useCurrentFrame();
4675
4663
  const volumePropsFrame = useFrameForVolumeProp();
@@ -4863,7 +4851,7 @@ const VideoForRendering = forwardRef(VideoForRenderingForwardFunction);
4863
4851
 
4864
4852
  const VideoForwardingFunction = (props, ref) => {
4865
4853
  var _a;
4866
- const { startFrom, endAt, name, ...otherProps } = props;
4854
+ const { startFrom, endAt, name, _remotionInternalNativeLoopPassed, ...otherProps } = props;
4867
4855
  const { loop, ...propsOtherThanLoop } = props;
4868
4856
  const { fps } = useVideoConfig();
4869
4857
  const environment = getRemotionEnvironment();
@@ -4885,7 +4873,7 @@ const VideoForwardingFunction = (props, ref) => {
4885
4873
  mediaDuration,
4886
4874
  playbackRate: (_a = props.playbackRate) !== null && _a !== void 0 ? _a : 1,
4887
4875
  startFrom,
4888
- }), layout: "none", name: name, children: jsx(Video, { ...propsOtherThanLoop, ref: ref }) }));
4876
+ }), layout: "none", name: name, children: jsx(Video, { ...propsOtherThanLoop, ref: ref, _remotionInternalNativeLoopPassed: true }) }));
4889
4877
  }
4890
4878
  if (typeof startFrom !== 'undefined' || typeof endAt !== 'undefined') {
4891
4879
  validateStartFromProps(startFrom, endAt);
@@ -4897,7 +4885,7 @@ const VideoForwardingFunction = (props, ref) => {
4897
4885
  if (environment.isRendering) {
4898
4886
  return (jsx(VideoForRendering, { onDuration: onDuration, ...otherProps, ref: ref }));
4899
4887
  }
4900
- return (jsx(VideoForDevelopment, { onlyWarnForMediaSeekingError: false, ...otherProps, ref: ref, onDuration: onDuration }));
4888
+ return (jsx(VideoForDevelopment, { onlyWarnForMediaSeekingError: false, ...otherProps, ref: ref, onDuration: onDuration, _remotionInternalNativeLoopPassed: _remotionInternalNativeLoopPassed !== null && _remotionInternalNativeLoopPassed !== void 0 ? _remotionInternalNativeLoopPassed : false }));
4901
4889
  };
4902
4890
  const forward = forwardRef;
4903
4891
  /**