@remotion/promo-pages 4.0.540 → 4.0.541

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.
package/dist/Automate.js CHANGED
@@ -1689,7 +1689,7 @@ var setComponentIdentityResolver = (resolver) => {
1689
1689
  var resolveComponentIdentity = (component) => {
1690
1690
  return componentIdentityResolver?.(component) ?? component;
1691
1691
  };
1692
- var getSingleChildComponent = (children) => {
1692
+ var getSingleChildElement = (children) => {
1693
1693
  const mountedChildren = React4.Children.toArray(children);
1694
1694
  if (mountedChildren.length !== 1) {
1695
1695
  return null;
@@ -1699,12 +1699,19 @@ var getSingleChildComponent = (children) => {
1699
1699
  return null;
1700
1700
  }
1701
1701
  if (child.type === IsNotInsideSeriesProvider) {
1702
- return getSingleChildComponent(child.props.children);
1702
+ return getSingleChildElement(child.props.children);
1703
1703
  }
1704
1704
  if (typeof child.type !== "function" && typeof child.type !== "object") {
1705
1705
  return null;
1706
1706
  }
1707
- return resolveComponentIdentity(child.type);
1707
+ return child;
1708
+ };
1709
+ var getSingleChildComponent = (children) => {
1710
+ const child = getSingleChildElement(children);
1711
+ return child === null ? null : resolveComponentIdentity(child.type);
1712
+ };
1713
+ var getSingleChildProps = (children) => {
1714
+ return getSingleChildElement(children)?.props ?? null;
1708
1715
  };
1709
1716
  var CompositionRegistryFallbackContext = createContext5(null);
1710
1717
  var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect3 : useLayoutEffect;
@@ -3112,9 +3119,11 @@ var makeOriginalSourceStack = ({
3112
3119
  fileName,
3113
3120
  lineNumber,
3114
3121
  columnNumber
3115
- }) => {
3116
- return `Error
3122
+ }, compiledSourceHash = null) => {
3123
+ const location = `Error
3117
3124
  at remotionOriginalSource (${ORIGINAL_SOURCE_STACK_PREFIX}${encodeURIComponent(fileName)}:${lineNumber}:${columnNumber})`;
3125
+ return compiledSourceHash === null ? location : `${location}
3126
+ at remotionCompiledSource (remotion-source-sha256:${compiledSourceHash})`;
3118
3127
  };
3119
3128
  var parseOriginalSourceStack = (stack) => {
3120
3129
  if (!stack) {
@@ -3144,7 +3153,7 @@ var setStackForControls = (controls, stack) => {
3144
3153
  var getStackForControls = (controls) => {
3145
3154
  return stacksByControls.get(controls) ?? null;
3146
3155
  };
3147
- var VERSION = "4.0.540";
3156
+ var VERSION = "4.0.541";
3148
3157
  var checkMultipleRemotionVersions = () => {
3149
3158
  if (typeof globalThis === "undefined") {
3150
3159
  return;
@@ -6900,7 +6909,7 @@ function hslToRgb2(h, s, l) {
6900
6909
  return Math.round(r * 255) << 24 | Math.round(g * 255) << 16 | Math.round(b * 255) << 8;
6901
6910
  }
6902
6911
  function parse255(str) {
6903
- const int = Number.parseInt(str, 10);
6912
+ const int = Math.round(Number.parseFloat(str));
6904
6913
  if (int < 0) {
6905
6914
  return 0;
6906
6915
  }
@@ -8652,6 +8661,7 @@ var setSequenceWrapperRef = (ref, wrapperRef, node) => {
8652
8661
  ref.current = node;
8653
8662
  }
8654
8663
  };
8664
+ var getSingleChildPropsFromRef = (childrenRef) => getSingleChildProps(childrenRef.current);
8655
8665
  var RegularSequenceContentRefForwardingFunction = ({
8656
8666
  timing,
8657
8667
  from = 0,
@@ -8672,6 +8682,7 @@ var RegularSequenceContentRefForwardingFunction = ({
8672
8682
  _remotionInternalLoopDisplay: loopDisplay,
8673
8683
  _remotionInternalStack: stack,
8674
8684
  _remotionInternalSingleChildComponent: childComponentOverride,
8685
+ _remotionInternalSingleChildren: authoredChildrenOverride,
8675
8686
  _remotionInternalDocumentationLink: documentationLink,
8676
8687
  _remotionInternalPremountDisplay: premountDisplay,
8677
8688
  _remotionInternalPostmountDisplay: postmountDisplay,
@@ -8722,6 +8733,7 @@ var RegularSequenceContentRefForwardingFunction = ({
8722
8733
  loopPeriod,
8723
8734
  loopIteration,
8724
8735
  contentVisible,
8736
+ inheritedFrozenFrame,
8725
8737
  currentFrameRef
8726
8738
  } = timing;
8727
8739
  if (typeof contentDurationInFrames !== "number") {
@@ -8846,7 +8858,13 @@ var RegularSequenceContentRefForwardingFunction = ({
8846
8858
  }, [name]);
8847
8859
  const resolvedDocumentationLink = documentationLink ?? "https://www.remotion.dev/docs/sequence";
8848
8860
  const isInsideSeries = useContext28(IsInsideSeriesContext);
8849
- const singleChildComponent = useMemo22(() => childComponentOverride === undefined ? getSingleChildComponent(children) : childComponentOverride, [children, childComponentOverride]);
8861
+ const authoredChildren = authoredChildrenOverride === undefined ? children : authoredChildrenOverride;
8862
+ const singleChildComponent = useMemo22(() => childComponentOverride === undefined ? getSingleChildComponent(authoredChildren) : childComponentOverride, [authoredChildren, childComponentOverride]);
8863
+ const childrenRef = useRef8(authoredChildren);
8864
+ useLayoutEffect9(() => {
8865
+ childrenRef.current = authoredChildren;
8866
+ }, [authoredChildren]);
8867
+ const getRegisteredSingleChildProps = useMemo22(() => childComponentOverride === undefined ? getSingleChildPropsFromRef.bind(null, childrenRef) : null, [childComponentOverride]);
8850
8868
  const registrationStack = controls ? getStackForControls(controls) ?? stack ?? null : stack ?? null;
8851
8869
  const getStack = useMemo22(() => getSequenceStack.bind(null, registrationStack), [registrationStack]);
8852
8870
  const registeredFrozenFrame = typeof freeze === "number" ? freeze : null;
@@ -8855,7 +8873,8 @@ var RegularSequenceContentRefForwardingFunction = ({
8855
8873
  const parentCumulatedNegativeFrom = parentSequence?.cumulatedNegativeFrom ?? 0;
8856
8874
  const startMediaFrom = isMedia && isMedia.type !== "image" ? isMedia.data.startMediaFrom + parentCumulatedNegativeFrom - cumulatedNegativeFrom : null;
8857
8875
  const mediaFrameAtSequenceZero = isMedia && isMedia.type !== "image" ? isMedia.data.startMediaFrom + parentCumulatedNegativeFrom : null;
8858
- const frozenMediaFrame = isMedia && isMedia.type !== "image" && mediaFrameAtSequenceZero !== null ? registeredFrozenFrame === null ? null : mediaFrameAtSequenceZero + (resolvedLoopDisplay ? registeredFrozenFrame % resolvedLoopDisplay.durationInFrames : registeredFrozenFrame) * isMedia.data.playbackRate : null;
8876
+ const mediaFreezeFrame = registeredFrozenFrame ?? (contentVisible && !parentDormant && !premounting && !postmounting ? inheritedFrozenFrame : null);
8877
+ const frozenMediaFrame = isMedia && isMedia.type !== "image" && mediaFrameAtSequenceZero !== null && mediaFreezeFrame !== null ? mediaFrameAtSequenceZero + (resolvedLoopDisplay ? mediaFreezeFrame % resolvedLoopDisplay.durationInFrames : mediaFreezeFrame) * isMedia.data.playbackRate : null;
8859
8878
  const controlsSchema = controls?.schema;
8860
8879
  const controlsRuntimeValues = controls?.runtimeValues;
8861
8880
  const controlsOverrideId = controls?.overrideId;
@@ -8863,8 +8882,7 @@ var RegularSequenceContentRefForwardingFunction = ({
8863
8882
  const controlsComponentIdentity = controls?.componentIdentity;
8864
8883
  const controlsComponentName = controls?.componentName;
8865
8884
  const controlsVideoConfigValues = controls?.videoConfigValues;
8866
- const isInsideNonPremountFreeze = useIsInsideNonPremountFreeze();
8867
- const canInferDuration = (controlsComponentIdentity === "dev.remotion.remotion.Series" || controlsComponentIdentity === "dev.remotion.transitions.TransitionSeries") && !loop && registeredFrozenFrame === null && !isInsideNonPremountFreeze && !hidden;
8885
+ const canInferDuration = (controlsComponentIdentity === "dev.remotion.remotion.Series" || controlsComponentIdentity === "dev.remotion.transitions.TransitionSeries") && !loop && registeredFrozenFrame === null && inheritedFrozenFrame === null && !hidden;
8868
8886
  const autoDuration = canInferDuration && durationInFrames === undefined;
8869
8887
  const isSeriesChild = controlsComponentIdentity === "dev.remotion.remotion.Series.Sequence" || controlsComponentIdentity === "dev.remotion.transitions.TransitionSeries.Sequence" || controlsComponentIdentity === "dev.remotion.transitions.TransitionSeries.Transition" || controlsComponentIdentity === "dev.remotion.transitions.TransitionSeries.Overlay";
8870
8888
  const effectRuntimeValues = useMemo22(() => _remotionInternalEffects?.runtimeValues ?? null, [_remotionInternalEffects]);
@@ -8926,7 +8944,8 @@ var RegularSequenceContentRefForwardingFunction = ({
8926
8944
  refForOutline: refForOutline ?? null,
8927
8945
  isInsideSeries,
8928
8946
  frozenFrame: registeredFrozenFrame,
8929
- singleChildComponent: singleChildComponent ?? null
8947
+ singleChildComponent: singleChildComponent ?? null,
8948
+ getSingleChildProps: getRegisteredSingleChildProps
8930
8949
  };
8931
8950
  }
8932
8951
  return {
@@ -8959,7 +8978,8 @@ var RegularSequenceContentRefForwardingFunction = ({
8959
8978
  isInsideSeries,
8960
8979
  frozenFrame: registeredFrozenFrame,
8961
8980
  frozenMediaFrame,
8962
- singleChildComponent: singleChildComponent ?? null
8981
+ singleChildComponent: singleChildComponent ?? null,
8982
+ getSingleChildProps: getRegisteredSingleChildProps
8963
8983
  };
8964
8984
  }
8965
8985
  return {
@@ -8989,7 +9009,8 @@ var RegularSequenceContentRefForwardingFunction = ({
8989
9009
  refForOutline: refForOutline ?? null,
8990
9010
  isInsideSeries,
8991
9011
  frozenFrame: registeredFrozenFrame,
8992
- singleChildComponent: singleChildComponent ?? null
9012
+ singleChildComponent: singleChildComponent ?? null,
9013
+ getSingleChildProps: getRegisteredSingleChildProps
8993
9014
  };
8994
9015
  }, [
8995
9016
  id,
@@ -9023,7 +9044,8 @@ var RegularSequenceContentRefForwardingFunction = ({
9023
9044
  startMediaFrom,
9024
9045
  mediaFrameAtSequenceZero,
9025
9046
  frozenMediaFrame,
9026
- singleChildComponent
9047
+ singleChildComponent,
9048
+ getRegisteredSingleChildProps
9027
9049
  ]);
9028
9050
  const getSequenceForRegistration = useMemo22(() => getSequenceRegistration.bind(null, sequenceForRegistration), [sequenceForRegistration]);
9029
9051
  const registration = useSequenceRegistration({
@@ -9187,6 +9209,7 @@ var RegularSequenceRefForwardingFunction = (props, ref) => {
9187
9209
  const loopOffset = loopPeriod === null ? 0 : loopIteration * loopPeriod;
9188
9210
  const currentSequenceStart = cumulatedFrom + (from + loopOffset - trimBefore / playbackRate) / parentPlaybackRate;
9189
9211
  const currentFrame = typeof freeze === "number" ? freeze : (absoluteFrame - currentSequenceStart) * (parentPlaybackRate * playbackRate);
9212
+ const inheritedFrozenFrame = useIsInsideNonPremountFreeze() ? currentFrame : null;
9190
9213
  const currentFrameRef = useRef8(currentFrame);
9191
9214
  const timing = useMemo22(() => ({
9192
9215
  contentDurationInFrames,
@@ -9195,6 +9218,7 @@ var RegularSequenceRefForwardingFunction = (props, ref) => {
9195
9218
  loopPeriod,
9196
9219
  loopIteration,
9197
9220
  contentVisible,
9221
+ inheritedFrozenFrame,
9198
9222
  currentFrameRef
9199
9223
  }), [
9200
9224
  contentDurationInFrames,
@@ -9202,7 +9226,8 @@ var RegularSequenceRefForwardingFunction = (props, ref) => {
9202
9226
  actualDurationInFrames,
9203
9227
  loopPeriod,
9204
9228
  loopIteration,
9205
- contentVisible
9229
+ contentVisible,
9230
+ inheritedFrozenFrame
9206
9231
  ]);
9207
9232
  return /* @__PURE__ */ jsxs22(React27.Fragment, {
9208
9233
  children: [
@@ -9482,6 +9507,16 @@ var AbsoluteFill = withInteractivitySchema({
9482
9507
  supportsEffects: false
9483
9508
  });
9484
9509
  addSequenceStackTraces(AbsoluteFill);
9510
+ var getCanvasPropsFromSequenceProps = (props) => {
9511
+ const canvasProps = {};
9512
+ const mutableCanvasProps = canvasProps;
9513
+ for (const key in props) {
9514
+ if (Object.prototype.hasOwnProperty.call(props, key) && (key.startsWith("data-") || key.startsWith("aria-"))) {
9515
+ mutableCanvasProps[key] = props[key];
9516
+ }
9517
+ }
9518
+ return canvasProps;
9519
+ };
9485
9520
  var useCropStyle = ({
9486
9521
  cropLeft,
9487
9522
  cropRight,
@@ -10769,16 +10804,6 @@ var animatedImageSchema = {
10769
10804
  ...borderSchema,
10770
10805
  ...borderRadiusSchema
10771
10806
  };
10772
- var getCanvasPropsFromSequenceProps = (props) => {
10773
- const canvasProps = {};
10774
- const mutableCanvasProps = canvasProps;
10775
- for (const key in props) {
10776
- if (Object.prototype.hasOwnProperty.call(props, key) && (key.startsWith("data-") || key.startsWith("aria-"))) {
10777
- mutableCanvasProps[key] = props[key];
10778
- }
10779
- }
10780
- return canvasProps;
10781
- };
10782
10807
  var AnimatedImageContent = forwardRef4(({
10783
10808
  src,
10784
10809
  width,
@@ -11264,6 +11289,16 @@ var RenderAssetManagerProvider = ({ children, collectAssets }) => {
11264
11289
  });
11265
11290
  };
11266
11291
  var ArtifactThumbnail = Symbol("Thumbnail");
11292
+ var encodeBinaryArtifact = (bytes) => {
11293
+ if ("toBase64" in bytes && typeof bytes.toBase64 === "function") {
11294
+ return bytes.toBase64();
11295
+ }
11296
+ let binary = "";
11297
+ for (let offset = 0;offset < bytes.length; offset += 32768) {
11298
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
11299
+ }
11300
+ return btoa(binary);
11301
+ };
11267
11302
  var Artifact = ({ filename, content, downloadBehavior }) => {
11268
11303
  const { registerRenderAsset, unregisterRenderAsset } = useContext30(RenderAssetManager);
11269
11304
  const env = useRemotionEnvironment();
@@ -11279,7 +11314,7 @@ var Artifact = ({ filename, content, downloadBehavior }) => {
11279
11314
  registerRenderAsset({
11280
11315
  type: "artifact",
11281
11316
  id,
11282
- content: btoa(new TextDecoder("utf8").decode(content)),
11317
+ content: encodeBinaryArtifact(content),
11283
11318
  filename,
11284
11319
  frame,
11285
11320
  contentType: "binary",
@@ -13251,9 +13286,7 @@ var getMediaSyncAction = (input) => {
13251
13286
  ended,
13252
13287
  desiredUnclampedTime,
13253
13288
  mediaTagTime,
13254
- mediaTagLastUpdate,
13255
13289
  rvcTime,
13256
- rvcLastUpdate,
13257
13290
  isVariableFpsVideo,
13258
13291
  acceptableTimeShift,
13259
13292
  lastSeekDueToShift,
@@ -13265,13 +13298,11 @@ var getMediaSyncAction = (input) => {
13265
13298
  onlyWarnForMediaSeekingError,
13266
13299
  isPremounting,
13267
13300
  isPostmounting,
13268
- pauseWhenBuffering
13301
+ pauseWhenBuffering,
13302
+ mediaType
13269
13303
  } = input;
13270
13304
  const shouldBeTime = !Number.isNaN(duration) && Number.isFinite(duration) ? Math.min(duration, desiredUnclampedTime) : desiredUnclampedTime;
13271
- const timeShiftMediaTag = Math.abs(shouldBeTime - mediaTagTime);
13272
- const timeShiftRvcTag = rvcTime ? Math.abs(shouldBeTime - rvcTime) : null;
13273
- const mostRecentTimeshift = rvcLastUpdate && rvcTime > mediaTagLastUpdate ? timeShiftRvcTag : timeShiftMediaTag;
13274
- const timeShift = timeShiftRvcTag && !isVariableFpsVideo ? mostRecentTimeshift : timeShiftMediaTag;
13305
+ const timeShift = Math.abs(shouldBeTime - mediaTagTime);
13275
13306
  if (timeShift > acceptableTimeShift && lastSeekDueToShift !== shouldBeTime) {
13276
13307
  return {
13277
13308
  type: "seek-due-to-shift",
@@ -13284,18 +13315,23 @@ var getMediaSyncAction = (input) => {
13284
13315
  }
13285
13316
  const seekThreshold = playing ? 0.15 : 0.01;
13286
13317
  const makesSenseToSeek = Math.abs(currentTime - shouldBeTime) > seekThreshold;
13318
+ const audioLead = currentTime - shouldBeTime;
13319
+ const holdAudioUntilTimelineCatchesUp = mediaType === "audio" && playing && playbackRate > 0 && makesSenseToSeek && audioLead > 0 && audioLead <= acceptableTimeShift;
13287
13320
  const isSomethingElseBuffering = playerBuffering && !mediaTagBufferingOrStalled;
13288
13321
  if (!playing || isSomethingElseBuffering) {
13289
13322
  return {
13290
13323
  type: "seek-if-not-playing",
13291
13324
  shouldBeTime,
13292
- why: makesSenseToSeek ? `not playing or something else is buffering. time offset is over seek threshold (${seekThreshold})` : null
13325
+ why: makesSenseToSeek && !holdAudioUntilTimelineCatchesUp ? `not playing or something else is buffering. time offset is over seek threshold (${seekThreshold})` : null
13293
13326
  };
13294
13327
  }
13295
13328
  if (!playing || playerBuffering) {
13296
13329
  return { type: "none" };
13297
13330
  }
13298
13331
  const pausedCondition = paused && !ended;
13332
+ if (pausedCondition && holdAudioUntilTimelineCatchesUp) {
13333
+ return { type: "none" };
13334
+ }
13299
13335
  const firstFrameCondition = absoluteFrame === 0;
13300
13336
  if (pausedCondition || firstFrameCondition) {
13301
13337
  const reason = pausedCondition ? "media tag is paused" : "absolute frame is 0";
@@ -13309,19 +13345,15 @@ var getMediaSyncAction = (input) => {
13309
13345
  }
13310
13346
  return { type: "none" };
13311
13347
  };
13312
- var useCurrentTimeOfMediaTagWithUpdateTimeStamp = (mediaRef) => {
13313
- const lastUpdate = React35.useRef({
13314
- time: mediaRef.current?.currentTime ?? 0,
13315
- lastUpdate: performance.now()
13348
+ var useCurrentTimeOfMediaTag = (mediaRef) => {
13349
+ const currentTime = React35.useRef({
13350
+ time: mediaRef.current?.currentTime ?? 0
13316
13351
  });
13317
13352
  const nowCurrentTime = mediaRef.current?.currentTime ?? null;
13318
13353
  if (nowCurrentTime !== null) {
13319
- if (lastUpdate.current.time !== nowCurrentTime) {
13320
- lastUpdate.current.time = nowCurrentTime;
13321
- lastUpdate.current.lastUpdate = performance.now();
13322
- }
13354
+ currentTime.current.time = nowCurrentTime;
13323
13355
  }
13324
- return lastUpdate;
13356
+ return currentTime;
13325
13357
  };
13326
13358
  var seek = ({
13327
13359
  mediaRef,
@@ -13488,8 +13520,7 @@ var useRequestVideoCallbackTime = ({
13488
13520
  const { current } = mediaRef;
13489
13521
  if (current) {
13490
13522
  currentTime.current = {
13491
- time: current.currentTime,
13492
- lastUpdate: performance.now()
13523
+ time: current.currentTime
13493
13524
  };
13494
13525
  } else {
13495
13526
  currentTime.current = null;
@@ -13519,8 +13550,7 @@ var useRequestVideoCallbackTime = ({
13519
13550
  }
13520
13551
  }
13521
13552
  currentTime.current = {
13522
- time: info.mediaTime,
13523
- lastUpdate: performance.now()
13553
+ time: info.mediaTime
13524
13554
  };
13525
13555
  request();
13526
13556
  });
@@ -13651,7 +13681,7 @@ var useMediaPlayback = ({
13651
13681
  lastSeek,
13652
13682
  onVariableFpsVideoDetected
13653
13683
  });
13654
- const mediaTagCurrentTime = useCurrentTimeOfMediaTagWithUpdateTimeStamp(mediaRef);
13684
+ const mediaTagCurrentTime = useCurrentTimeOfMediaTag(mediaRef);
13655
13685
  const desiredUnclampedTime = getMediaTime({
13656
13686
  frame,
13657
13687
  playbackRate: localPlaybackRate,
@@ -13732,9 +13762,7 @@ var useMediaPlayback = ({
13732
13762
  ended: current.ended,
13733
13763
  desiredUnclampedTime,
13734
13764
  mediaTagTime: mediaTagCurrentTime.current.time,
13735
- mediaTagLastUpdate: mediaTagCurrentTime.current.lastUpdate,
13736
13765
  rvcTime: rvcCurrentTime.current?.time ?? null,
13737
- rvcLastUpdate: rvcCurrentTime.current?.lastUpdate ?? null,
13738
13766
  isVariableFpsVideo: Boolean(isVariableFpsVideoMap.current[src]),
13739
13767
  acceptableTimeShift: acceptableTimeShiftButLessThanDuration,
13740
13768
  lastSeekDueToShift: lastSeekDueToShift.current,
@@ -13746,7 +13774,8 @@ var useMediaPlayback = ({
13746
13774
  onlyWarnForMediaSeekingError,
13747
13775
  isPremounting,
13748
13776
  isPostmounting,
13749
- pauseWhenBuffering
13777
+ pauseWhenBuffering,
13778
+ mediaType
13750
13779
  });
13751
13780
  if (action.type === "none") {
13752
13781
  return;
@@ -14591,7 +14620,8 @@ var SolidInner = ({
14591
14620
  pixelDensity,
14592
14621
  overrideId,
14593
14622
  videoConfigValues,
14594
- reference
14623
+ reference,
14624
+ canvasProps
14595
14625
  }) => {
14596
14626
  const { delayRender, continueRender, cancelRender } = useDelayRender();
14597
14627
  const resolvedPixelDensity = resolveSolidPixelDensity(pixelDensity);
@@ -14679,6 +14709,7 @@ var SolidInner = ({
14679
14709
  };
14680
14710
  }, [height, style, width]);
14681
14711
  return /* @__PURE__ */ jsx31("canvas", {
14712
+ ...canvasProps,
14682
14713
  ref: canvasRef,
14683
14714
  width: canvasWidth,
14684
14715
  height: canvasHeight,
@@ -14775,6 +14806,7 @@ var SolidOuter = forwardRef8(({
14775
14806
  _remotionInternalIsPostmounting: postmountingActive,
14776
14807
  children: /* @__PURE__ */ jsx31(SequenceContent, {
14777
14808
  children: /* @__PURE__ */ jsx31(SolidInner, {
14809
+ canvasProps: getCanvasPropsFromSequenceProps(props),
14778
14810
  reference: actualRef,
14779
14811
  videoConfigValues: controls?.videoConfigValues ?? null,
14780
14812
  overrideId: controls?.overrideId ?? null,
@@ -17185,7 +17217,7 @@ var createElementSourceProxy = (api, sourceArgumentIndex, getSourceFileName) =>
17185
17217
  fileName: getSourceFileName(source.fileName),
17186
17218
  lineNumber: source.lineNumber,
17187
17219
  columnNumber: source.columnNumber - 1
17188
- });
17220
+ }, typeof source.__remotionCompiledSourceHash === "string" ? source.__remotionCompiledSourceHash : null);
17189
17221
  } else {
17190
17222
  const { stackTraceLimit } = Error;
17191
17223
  const canLimitStack = typeof stackTraceLimit === "number" && stackTraceLimit > 2 && Object.getOwnPropertyDescriptor(Error, "stackTraceLimit")?.writable;
@@ -19704,14 +19736,29 @@ import React9 from "react";
19704
19736
  import { useEffect as useEffect25, useState as useState30 } from "react";
19705
19737
  import { useContext as useContext55, useLayoutEffect as useLayoutEffect25 } from "react";
19706
19738
  import { jsx as jsx310 } from "react/jsx-runtime";
19707
- import React32 from "react";
19708
- import { useEffect as useEffect26, useState as useState210 } from "react";
19739
+ import { useCallback as useCallback72, useEffect as useEffect72, useMemo as useMemo92, useRef as useRef52, useState as useState92 } from "react";
19740
+ import { jsx as jsx410 } from "react/jsx-runtime";
19741
+ import { useCallback as useCallback27, useMemo as useMemo210, useRef as useRef34, useState as useState43 } from "react";
19742
+ import React32, { useCallback as useCallback28, useMemo as useMemo54, useState as useState210 } from "react";
19743
+ import { jsx as jsx53, jsxs as jsxs33 } from "react/jsx-runtime";
19744
+ import { useEffect as useEffect26, useState as useState33 } from "react";
19745
+ import { jsx as jsx63, jsxs as jsxs42 } from "react/jsx-runtime";
19746
+ import { useCallback as useCallback32, useEffect as useEffect42, useMemo as useMemo310, useState as useState62 } from "react";
19747
+ import { useEffect as useEffect33, useRef as useRef210, useState as useState52 } from "react";
19748
+ import { jsx as jsx73, jsxs as jsxs52 } from "react/jsx-runtime";
19749
+ import { useCallback as useCallback62, useEffect as useEffect62, useMemo as useMemo62, useRef as useRef43, useState as useState82 } from "react";
19750
+ import { useCallback as useCallback42, useContext as useContext210, useMemo as useMemo410, useRef as useRef35 } from "react";
19751
+ import { useCallback as useCallback52, useEffect as useEffect53, useMemo as useMemo55, useState as useState72 } from "react";
19752
+ import { jsx as jsx82, jsxs as jsxs62 } from "react/jsx-runtime";
19753
+ import { useMemo as useMemo72 } from "react";
19754
+ import { jsxs as jsxs72 } from "react/jsx-runtime";
19755
+ import { useMemo as useMemo82 } from "react";
19756
+ import { jsx as jsx92, jsxs as jsxs8, Fragment as Fragment22 } from "react/jsx-runtime";
19757
+ import React82 from "react";
19709
19758
  import { useLayoutEffect as useLayoutEffect26 } from "react";
19710
- import { useContext as useContext310, useEffect as useEffect53, useRef as useRef43 } from "react";
19711
- import { useEffect as useEffect33, useRef as useRef210 } from "react";
19712
- import { useCallback as useCallback27, useContext as useContext210, useMemo as useMemo54, useRef as useRef34 } from "react";
19713
- import { useEffect as useEffect42, useRef as useRef35 } from "react";
19714
- import { useCallback as useCallback28, useEffect as useEffect62, useMemo as useMemo210, useState as useState33 } from "react";
19759
+ import { useContext as useContext310, useEffect as useEffect102, useRef as useRef82 } from "react";
19760
+ import { useEffect as useEffect82, useRef as useRef62 } from "react";
19761
+ import { useEffect as useEffect92, useRef as useRef72 } from "react";
19715
19762
  import React132, {
19716
19763
  forwardRef as forwardRef23,
19717
19764
  useCallback as useCallback122,
@@ -21686,7 +21733,7 @@ function hslToRgb3(h, s, l) {
21686
21733
  return Math.round(r * 255) << 24 | Math.round(g * 255) << 16 | Math.round(b * 255) << 8;
21687
21734
  }
21688
21735
  function parse2552(str) {
21689
- const int = Number.parseInt(str, 10);
21736
+ const int = Math.round(Number.parseFloat(str));
21690
21737
  if (int < 0) {
21691
21738
  return 0;
21692
21739
  }
@@ -22301,25 +22348,10 @@ import React112, {
22301
22348
  useRef as useRef102,
22302
22349
  useState as useState102
22303
22350
  } from "react";
22304
- import React42 from "react";
22305
- import { jsx as jsx410 } from "react/jsx-runtime";
22306
- import React53, { useEffect as useEffect72 } from "react";
22307
- import { jsx as jsx53 } from "react/jsx-runtime";
22308
- import { useCallback as useCallback72, useEffect as useEffect112, useMemo as useMemo92, useRef as useRef82, useState as useState92 } from "react";
22309
- import { jsx as jsx63 } from "react/jsx-runtime";
22310
- import { useCallback as useCallback42, useMemo as useMemo410, useRef as useRef52, useState as useState52 } from "react";
22311
- import React62, { useCallback as useCallback32, useMemo as useMemo310, useState as useState43 } from "react";
22312
- import { jsx as jsx73, jsxs as jsxs33 } from "react/jsx-runtime";
22313
- import { jsx as jsx82, jsxs as jsxs42 } from "react/jsx-runtime";
22314
- import { useCallback as useCallback52, useEffect as useEffect92, useMemo as useMemo55, useState as useState72 } from "react";
22315
- import { useEffect as useEffect82, useRef as useRef62, useState as useState62 } from "react";
22316
- import { jsx as jsx92, jsxs as jsxs52 } from "react/jsx-runtime";
22317
- import { useCallback as useCallback62, useEffect as useEffect102, useMemo as useMemo62, useRef as useRef72, useState as useState82 } from "react";
22318
- import { jsx as jsx102, jsxs as jsxs62 } from "react/jsx-runtime";
22319
- import { useMemo as useMemo72 } from "react";
22320
- import { jsxs as jsxs72 } from "react/jsx-runtime";
22321
- import { useMemo as useMemo82 } from "react";
22322
- import { jsx as jsx112, jsxs as jsxs8, Fragment as Fragment22 } from "react/jsx-runtime";
22351
+ import React92 from "react";
22352
+ import { jsx as jsx102 } from "react/jsx-runtime";
22353
+ import React102, { useEffect as useEffect112 } from "react";
22354
+ import { jsx as jsx112 } from "react/jsx-runtime";
22323
22355
  import { useCallback as useCallback92, useMemo as useMemo112 } from "react";
22324
22356
  import { useCallback as useCallback82, useMemo as useMemo102, useRef as useRef92 } from "react";
22325
22357
  import { jsx as jsx122, jsxs as jsxs9, Fragment as Fragment3 } from "react/jsx-runtime";
@@ -22819,9 +22851,122 @@ var PlayerEmitterProvider = ({ children, currentPlaybackRate }) => {
22819
22851
  children
22820
22852
  });
22821
22853
  };
22822
- var TimelineSequenceObserverContext = React32.createContext(null);
22854
+ var DefaultPlayPauseButton = ({ playing, buffering }) => {
22855
+ if (playing && buffering) {
22856
+ return /* @__PURE__ */ jsx410(BufferingIndicator, {
22857
+ type: "player"
22858
+ });
22859
+ }
22860
+ if (playing) {
22861
+ return /* @__PURE__ */ jsx410(PauseIcon, {});
22862
+ }
22863
+ return /* @__PURE__ */ jsx410(PlayIcon, {});
22864
+ };
22865
+ var KNOB_SIZE = 12;
22866
+ var BAR_HEIGHT = 5;
22867
+ var DefaultVolumeSlider = ({
22868
+ volume,
22869
+ isVertical,
22870
+ onBlur,
22871
+ inputRef,
22872
+ setVolume
22873
+ }) => {
22874
+ const sliderContainer = useMemo54(() => {
22875
+ const paddingLeft = 5;
22876
+ const common = {
22877
+ paddingLeft,
22878
+ height: ICON_SIZE2,
22879
+ width: VOLUME_SLIDER_WIDTH,
22880
+ display: "inline-flex",
22881
+ alignItems: "center"
22882
+ };
22883
+ if (isVertical) {
22884
+ return {
22885
+ ...common,
22886
+ position: "absolute",
22887
+ transform: `rotate(-90deg) translateX(${VOLUME_SLIDER_WIDTH / 2 + ICON_SIZE2 / 2}px)`
22888
+ };
22889
+ }
22890
+ return {
22891
+ ...common
22892
+ };
22893
+ }, [isVertical]);
22894
+ const randomId = typeof React32.useId === "undefined" ? "volume-slider" : React32.useId();
22895
+ const [randomClass] = useState210(() => `__remotion-volume-slider-${random(randomId)}`.replace(".", ""));
22896
+ const onVolumeChange = useCallback28((e) => {
22897
+ setVolume(parseFloat(e.target.value));
22898
+ }, [setVolume]);
22899
+ const inputStyle = useMemo54(() => {
22900
+ const commonStyle = {
22901
+ WebkitAppearance: "none",
22902
+ backgroundColor: "rgba(255, 255, 255, 0.5)",
22903
+ borderRadius: BAR_HEIGHT / 2,
22904
+ cursor: "pointer",
22905
+ height: BAR_HEIGHT,
22906
+ width: VOLUME_SLIDER_WIDTH,
22907
+ backgroundImage: `linear-gradient(
22908
+ to right,
22909
+ white ${volume * 100}%, rgba(255, 255, 255, 0) ${volume * 100}%
22910
+ )`
22911
+ };
22912
+ if (isVertical) {
22913
+ return {
22914
+ ...commonStyle,
22915
+ bottom: ICON_SIZE2 + VOLUME_SLIDER_WIDTH / 2
22916
+ };
22917
+ }
22918
+ return commonStyle;
22919
+ }, [isVertical, volume]);
22920
+ const sliderStyle = `
22921
+ .${randomClass}::-webkit-slider-thumb {
22922
+ -webkit-appearance: none;
22923
+ background-color: white;
22924
+ border-radius: ${KNOB_SIZE / 2}px;
22925
+ box-shadow: 0 0 2px black;
22926
+ height: ${KNOB_SIZE}px;
22927
+ width: ${KNOB_SIZE}px;
22928
+ }
22929
+
22930
+ .${randomClass}::-moz-range-thumb {
22931
+ -webkit-appearance: none;
22932
+ background-color: white;
22933
+ border-radius: ${KNOB_SIZE / 2}px;
22934
+ box-shadow: 0 0 2px black;
22935
+ height: ${KNOB_SIZE}px;
22936
+ width: ${KNOB_SIZE}px;
22937
+ }
22938
+ `;
22939
+ return /* @__PURE__ */ jsxs33("div", {
22940
+ style: sliderContainer,
22941
+ children: [
22942
+ /* @__PURE__ */ jsx53("style", {
22943
+ dangerouslySetInnerHTML: {
22944
+ __html: sliderStyle
22945
+ }
22946
+ }),
22947
+ /* @__PURE__ */ jsx53("input", {
22948
+ ref: inputRef,
22949
+ "aria-label": "Change volume",
22950
+ className: randomClass,
22951
+ max: 1,
22952
+ min: 0,
22953
+ onBlur,
22954
+ onChange: onVolumeChange,
22955
+ step: 0.01,
22956
+ type: "range",
22957
+ value: volume,
22958
+ style: inputStyle
22959
+ })
22960
+ ]
22961
+ });
22962
+ };
22963
+ var renderDefaultVolumeSlider = (props) => {
22964
+ return /* @__PURE__ */ jsx53(DefaultVolumeSlider, {
22965
+ ...props
22966
+ });
22967
+ };
22823
22968
  var useHoverState = (ref, hideControlsWhenPointerDoesntMove) => {
22824
- const [hovered, setHovered] = useState210(false);
22969
+ const [hovered, setHovered] = useState33(false);
22825
22970
  useEffect26(() => {
22826
22971
  const { current } = ref;
22827
22972
  if (!current) {
@@ -22860,6 +23005,322 @@ var useHoverState = (ref, hideControlsWhenPointerDoesntMove) => {
22860
23005
  }, [hideControlsWhenPointerDoesntMove, ref]);
22861
23006
  return hovered;
22862
23007
  };
23008
+ var VOLUME_SLIDER_WIDTH = 100;
23009
+ var MediaVolumeSlider = ({ displayVerticalVolumeSlider, renderMuteButton, renderVolumeSlider }) => {
23010
+ const [playerMuted, setPlayerMuted] = Internals.usePlayerMutedState();
23011
+ const [mediaVolume, setMediaVolume] = Internals.useMediaVolumeState();
23012
+ const [focused, setFocused] = useState43(false);
23013
+ const parentDivRef = useRef34(null);
23014
+ const inputRef = useRef34(null);
23015
+ const hover = useHoverState(parentDivRef, false);
23016
+ const onBlur = useCallback27(() => {
23017
+ setTimeout(() => {
23018
+ if (inputRef.current && document.activeElement !== inputRef.current) {
23019
+ setFocused(false);
23020
+ }
23021
+ }, 10);
23022
+ }, []);
23023
+ const isVolume0 = mediaVolume === 0;
23024
+ const onClick = useCallback27(() => {
23025
+ if (isVolume0) {
23026
+ setMediaVolume(1);
23027
+ setPlayerMuted(false);
23028
+ return;
23029
+ }
23030
+ setPlayerMuted((mute) => !mute);
23031
+ }, [isVolume0, setPlayerMuted, setMediaVolume]);
23032
+ const parentDivStyle = useMemo210(() => {
23033
+ return {
23034
+ display: "inline-flex",
23035
+ background: "none",
23036
+ border: "none",
23037
+ justifyContent: "center",
23038
+ alignItems: "center",
23039
+ touchAction: "none",
23040
+ ...displayVerticalVolumeSlider && { position: "relative" }
23041
+ };
23042
+ }, [displayVerticalVolumeSlider]);
23043
+ const volumeContainer = useMemo210(() => {
23044
+ return {
23045
+ display: "inline",
23046
+ width: ICON_SIZE2,
23047
+ height: ICON_SIZE2,
23048
+ cursor: "pointer",
23049
+ appearance: "none",
23050
+ background: "none",
23051
+ border: "none",
23052
+ padding: 0
23053
+ };
23054
+ }, []);
23055
+ const renderDefaultMuteButton = useCallback27(({ muted, volume }) => {
23056
+ const isMutedOrZero = muted || volume === 0;
23057
+ return /* @__PURE__ */ jsx63("button", {
23058
+ "aria-label": isMutedOrZero ? "Unmute sound" : "Mute sound",
23059
+ title: isMutedOrZero ? "Unmute sound" : "Mute sound",
23060
+ onClick,
23061
+ onBlur,
23062
+ onFocus: () => setFocused(true),
23063
+ style: volumeContainer,
23064
+ type: "button",
23065
+ children: isMutedOrZero ? /* @__PURE__ */ jsx63(VolumeOffIcon, {}) : /* @__PURE__ */ jsx63(VolumeOnIcon, {})
23066
+ });
23067
+ }, [onBlur, onClick, volumeContainer]);
23068
+ const muteButton = useMemo210(() => {
23069
+ return renderMuteButton ? renderMuteButton({ muted: playerMuted, volume: mediaVolume }) : renderDefaultMuteButton({ muted: playerMuted, volume: mediaVolume });
23070
+ }, [playerMuted, mediaVolume, renderDefaultMuteButton, renderMuteButton]);
23071
+ const volumeSlider = useMemo210(() => {
23072
+ return (focused || hover) && !playerMuted && !Internals.isIosSafari() ? (renderVolumeSlider ?? renderDefaultVolumeSlider)({
23073
+ isVertical: displayVerticalVolumeSlider,
23074
+ volume: mediaVolume,
23075
+ onBlur: () => setFocused(false),
23076
+ inputRef,
23077
+ setVolume: setMediaVolume
23078
+ }) : null;
23079
+ }, [
23080
+ displayVerticalVolumeSlider,
23081
+ focused,
23082
+ hover,
23083
+ playerMuted,
23084
+ mediaVolume,
23085
+ renderVolumeSlider,
23086
+ setMediaVolume
23087
+ ]);
23088
+ return /* @__PURE__ */ jsxs42("div", {
23089
+ ref: parentDivRef,
23090
+ style: parentDivStyle,
23091
+ children: [
23092
+ muteButton,
23093
+ volumeSlider
23094
+ ]
23095
+ });
23096
+ };
23097
+ function useComponentVisible(initialIsVisible) {
23098
+ const [isComponentVisible, setIsComponentVisible] = useState52(initialIsVisible);
23099
+ const ref = useRef210(null);
23100
+ useEffect33(() => {
23101
+ const handleClickOutside = (event) => {
23102
+ if (ref.current && !ref.current.contains(event.target)) {
23103
+ setIsComponentVisible(false);
23104
+ }
23105
+ };
23106
+ document.addEventListener("pointerup", handleClickOutside, true);
23107
+ return () => {
23108
+ document.removeEventListener("pointerup", handleClickOutside, true);
23109
+ };
23110
+ }, []);
23111
+ return { ref, isComponentVisible, setIsComponentVisible };
23112
+ }
23113
+ var BOTTOM = 35;
23114
+ var THRESHOLD = 70;
23115
+ var rateDiv = {
23116
+ height: 30,
23117
+ paddingRight: 15,
23118
+ paddingLeft: 12,
23119
+ display: "flex",
23120
+ flexDirection: "row",
23121
+ alignItems: "center"
23122
+ };
23123
+ var checkmarkContainer = {
23124
+ width: 22,
23125
+ display: "flex",
23126
+ alignItems: "center"
23127
+ };
23128
+ var checkmarkStyle = {
23129
+ width: 14,
23130
+ height: 14,
23131
+ color: "black"
23132
+ };
23133
+ var Checkmark = () => /* @__PURE__ */ jsx73("svg", {
23134
+ viewBox: "0 0 512 512",
23135
+ style: checkmarkStyle,
23136
+ children: /* @__PURE__ */ jsx73("path", {
23137
+ fill: "currentColor",
23138
+ d: "M435.848 83.466L172.804 346.51l-96.652-96.652c-4.686-4.686-12.284-4.686-16.971 0l-28.284 28.284c-4.686 4.686-4.686 12.284 0 16.971l133.421 133.421c4.686 4.686 12.284 4.686 16.971 0l299.813-299.813c4.686-4.686 4.686-12.284 0-16.971l-28.284-28.284c-4.686-4.686-12.284-4.686-16.97 0z"
23139
+ })
23140
+ });
23141
+ var formatPlaybackRate = (rate) => {
23142
+ const str = rate.toString();
23143
+ return str.includes(".") ? str : str + ".0";
23144
+ };
23145
+ var PlaybackrateOption = ({ rate, onSelect, selectedRate, keyboardSelectedRate }) => {
23146
+ const onClick = useCallback32((e) => {
23147
+ e.stopPropagation();
23148
+ e.preventDefault();
23149
+ onSelect(rate);
23150
+ }, [onSelect, rate]);
23151
+ const [hovered, setHovered] = useState62(false);
23152
+ const onMouseEnter = useCallback32(() => {
23153
+ setHovered(true);
23154
+ }, []);
23155
+ const onMouseLeave = useCallback32(() => {
23156
+ setHovered(false);
23157
+ }, []);
23158
+ const isFocused = keyboardSelectedRate === rate;
23159
+ const actualStyle = useMemo310(() => {
23160
+ return {
23161
+ ...rateDiv,
23162
+ backgroundColor: hovered || isFocused ? "#eee" : "transparent"
23163
+ };
23164
+ }, [hovered, isFocused]);
23165
+ return /* @__PURE__ */ jsxs52("div", {
23166
+ onPointerEnter: onMouseEnter,
23167
+ onPointerLeave: onMouseLeave,
23168
+ tabIndex: 0,
23169
+ style: actualStyle,
23170
+ onClick,
23171
+ children: [
23172
+ /* @__PURE__ */ jsx73("div", {
23173
+ style: checkmarkContainer,
23174
+ children: rate === selectedRate ? /* @__PURE__ */ jsx73(Checkmark, {}) : null
23175
+ }),
23176
+ formatPlaybackRate(rate),
23177
+ "x"
23178
+ ]
23179
+ }, rate);
23180
+ };
23181
+ var PlaybackPopup = ({ setIsComponentVisible, playbackRates, canvasSize }) => {
23182
+ const { setPlaybackRate, playbackRate } = Internals.usePlaybackRate();
23183
+ const [keyboardSelectedRate, setKeyboardSelectedRate] = useState62(playbackRate);
23184
+ useEffect42(() => {
23185
+ const listener = (e) => {
23186
+ if (e.ctrlKey || e.metaKey || e.altKey) {
23187
+ return;
23188
+ }
23189
+ if (e.key === "ArrowUp") {
23190
+ e.preventDefault();
23191
+ const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
23192
+ if (currentIndex === 0) {
23193
+ return;
23194
+ }
23195
+ if (currentIndex === -1) {
23196
+ setKeyboardSelectedRate(playbackRates[0]);
23197
+ } else {
23198
+ setKeyboardSelectedRate(playbackRates[currentIndex - 1]);
23199
+ }
23200
+ } else if (e.key === "ArrowDown") {
23201
+ e.preventDefault();
23202
+ const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
23203
+ if (currentIndex === playbackRates.length - 1) {
23204
+ return;
23205
+ }
23206
+ if (currentIndex === -1) {
23207
+ setKeyboardSelectedRate(playbackRates[playbackRates.length - 1]);
23208
+ } else {
23209
+ setKeyboardSelectedRate(playbackRates[currentIndex + 1]);
23210
+ }
23211
+ } else if (e.key === "Enter") {
23212
+ e.preventDefault();
23213
+ setPlaybackRate(keyboardSelectedRate);
23214
+ setIsComponentVisible(false);
23215
+ } else if (e.key === "Escape") {
23216
+ e.preventDefault();
23217
+ setIsComponentVisible(false);
23218
+ } else if (e.key === "Tab") {
23219
+ setIsComponentVisible(false);
23220
+ }
23221
+ };
23222
+ window.addEventListener("keydown", listener);
23223
+ return () => {
23224
+ window.removeEventListener("keydown", listener);
23225
+ };
23226
+ }, [
23227
+ playbackRates,
23228
+ keyboardSelectedRate,
23229
+ setPlaybackRate,
23230
+ setIsComponentVisible
23231
+ ]);
23232
+ const onSelect = useCallback32((rate) => {
23233
+ setPlaybackRate(rate);
23234
+ setIsComponentVisible(false);
23235
+ }, [setIsComponentVisible, setPlaybackRate]);
23236
+ const playbackPopup = useMemo310(() => {
23237
+ return {
23238
+ position: "absolute",
23239
+ right: 0,
23240
+ width: 125,
23241
+ maxHeight: canvasSize.height - THRESHOLD - BOTTOM,
23242
+ bottom: 35,
23243
+ background: "#fff",
23244
+ borderRadius: 4,
23245
+ overflow: "auto",
23246
+ color: "black",
23247
+ textAlign: "left"
23248
+ };
23249
+ }, [canvasSize.height]);
23250
+ return /* @__PURE__ */ jsx73("div", {
23251
+ style: playbackPopup,
23252
+ children: playbackRates.map((rate) => {
23253
+ return /* @__PURE__ */ jsx73(PlaybackrateOption, {
23254
+ selectedRate: playbackRate,
23255
+ onSelect,
23256
+ rate,
23257
+ keyboardSelectedRate
23258
+ }, rate);
23259
+ })
23260
+ });
23261
+ };
23262
+ var label2 = {
23263
+ fontSize: 13,
23264
+ fontWeight: "bold",
23265
+ color: "white",
23266
+ border: "2px solid white",
23267
+ borderRadius: 20,
23268
+ paddingLeft: 8,
23269
+ paddingRight: 8,
23270
+ paddingTop: 2,
23271
+ paddingBottom: 2
23272
+ };
23273
+ var playerButtonStyle = {
23274
+ appearance: "none",
23275
+ backgroundColor: "transparent",
23276
+ border: "none",
23277
+ cursor: "pointer",
23278
+ paddingLeft: 0,
23279
+ paddingRight: 0,
23280
+ paddingTop: 6,
23281
+ paddingBottom: 6,
23282
+ height: 37,
23283
+ display: "inline-flex",
23284
+ marginBottom: 0,
23285
+ marginTop: 0,
23286
+ alignItems: "center"
23287
+ };
23288
+ var button = {
23289
+ ...playerButtonStyle,
23290
+ position: "relative"
23291
+ };
23292
+ var PlaybackrateControl = ({ playbackRates, canvasSize }) => {
23293
+ const { ref, isComponentVisible, setIsComponentVisible } = useComponentVisible(false);
23294
+ const { playbackRate } = Internals.usePlaybackRate();
23295
+ const onClick = useCallback32((e) => {
23296
+ e.stopPropagation();
23297
+ e.preventDefault();
23298
+ setIsComponentVisible((prevIsComponentVisible) => !prevIsComponentVisible);
23299
+ }, [setIsComponentVisible]);
23300
+ return /* @__PURE__ */ jsx73("div", {
23301
+ ref,
23302
+ children: /* @__PURE__ */ jsxs52("button", {
23303
+ type: "button",
23304
+ "aria-label": "Change playback rate",
23305
+ style: button,
23306
+ onClick,
23307
+ children: [
23308
+ /* @__PURE__ */ jsxs52("div", {
23309
+ style: label2,
23310
+ children: [
23311
+ playbackRate,
23312
+ "x"
23313
+ ]
23314
+ }),
23315
+ isComponentVisible && /* @__PURE__ */ jsx73(PlaybackPopup, {
23316
+ canvasSize,
23317
+ playbackRates,
23318
+ setIsComponentVisible
23319
+ })
23320
+ ]
23321
+ })
23322
+ });
23323
+ };
22863
23324
  var usePlayerMethods = () => {
22864
23325
  const seekFrame = Internals.Timeline.useTimelineSeekFrame();
22865
23326
  const {
@@ -22879,20 +23340,20 @@ var usePlayerMethods = () => {
22879
23340
  const videoDurationInFrames = video?.durationInFrames ?? null;
22880
23341
  const config = Internals.useUnsafeVideoConfig();
22881
23342
  const emitter = useContext210(PlayerEventEmitterContext);
22882
- const playStart = useRef34(0);
22883
- const fallbackFrame = useRef34(null);
22884
- const nextPlayIsAutoPlayAttempt = useRef34(false);
23343
+ const playStart = useRef35(0);
23344
+ const fallbackFrame = useRef35(null);
23345
+ const nextPlayIsAutoPlayAttempt = useRef35(false);
22885
23346
  if (!emitter) {
22886
23347
  throw new TypeError("Expected Player event emitter context");
22887
23348
  }
22888
- const getCurrentFrame = useCallback27(() => {
23349
+ const getCurrentFrame = useCallback42(() => {
22889
23350
  if (videoId === null || videoDurationInFrames === null) {
22890
23351
  return fallbackFrame.current ?? (typeof window === "undefined" ? 0 : window.remotion_initialFrame ?? 0);
22891
23352
  }
22892
23353
  const unclamped = frameRef.current[videoId] ?? (environment.isPlayer ? 0 : Internals.Timeline.getFrameForComposition(videoId));
22893
23354
  return Internals.Timeline.clampFrameToCompositionRange(unclamped, videoDurationInFrames);
22894
23355
  }, [environment.isPlayer, frameRef, videoId, videoDurationInFrames]);
22895
- const seek = useCallback27((newFrame) => {
23356
+ const seek = useCallback42((newFrame) => {
22896
23357
  const frameToSeekTo = config ? Internals.TimelinePosition.clampFrameToCompositionRange(newFrame, config.durationInFrames) : Math.max(0, newFrame);
22897
23358
  fallbackFrame.current = frameToSeekTo;
22898
23359
  if (video?.id) {
@@ -22906,7 +23367,7 @@ var usePlayerMethods = () => {
22906
23367
  }
22907
23368
  emitter.dispatchSeek(frameToSeekTo);
22908
23369
  }, [config, emitter, frameRef, seekFrame, video?.id]);
22909
- const play = useCallback27((e) => {
23370
+ const play = useCallback42((e) => {
22910
23371
  const isAutoPlayAttempt = nextPlayIsAutoPlayAttempt.current;
22911
23372
  nextPlayIsAutoPlayAttempt.current = false;
22912
23373
  if (readIsPlaying()) {
@@ -22942,18 +23403,18 @@ var usePlayerMethods = () => {
22942
23403
  seek,
22943
23404
  setPlaying
22944
23405
  ]);
22945
- const playAsAutoPlay = useCallback27(() => {
23406
+ const playAsAutoPlay = useCallback42(() => {
22946
23407
  nextPlayIsAutoPlayAttempt.current = true;
22947
23408
  play();
22948
23409
  }, [play]);
22949
- const pause = useCallback27(() => {
23410
+ const pause = useCallback42(() => {
22950
23411
  if (readIsPlaying()) {
22951
23412
  setPlaying(false);
22952
23413
  emitter.dispatchPause();
22953
23414
  audioContext?.suspend();
22954
23415
  }
22955
23416
  }, [audioContext, emitter, readIsPlaying, setPlaying]);
22956
- const pauseAndReturnToPlayStart = useCallback27(() => {
23417
+ const pauseAndReturnToPlayStart = useCallback42(() => {
22957
23418
  if (readIsPlaying()) {
22958
23419
  setPlaying(false);
22959
23420
  fallbackFrame.current = playStart.current;
@@ -22971,7 +23432,7 @@ var usePlayerMethods = () => {
22971
23432
  }
22972
23433
  }, [config, emitter, frameRef, readIsPlaying, setPlaying, seekFrame]);
22973
23434
  const lastFrame = (config?.durationInFrames ?? 1) - 1;
22974
- const frameBack = useCallback27((frames) => {
23435
+ const frameBack = useCallback42((frames) => {
22975
23436
  if (!videoId) {
22976
23437
  return null;
22977
23438
  }
@@ -22989,7 +23450,7 @@ var usePlayerMethods = () => {
22989
23450
  [videoId]: newFrame
22990
23451
  };
22991
23452
  }, [frameRef, readIsPlaying, seekFrame, videoId]);
22992
- const frameForward = useCallback27((frames) => {
23453
+ const frameForward = useCallback42((frames) => {
22993
23454
  if (!videoId) {
22994
23455
  return null;
22995
23456
  }
@@ -23007,14 +23468,14 @@ var usePlayerMethods = () => {
23007
23468
  [videoId]: newFrame
23008
23469
  };
23009
23470
  }, [frameRef, lastFrame, readIsPlaying, seekFrame, videoId]);
23010
- const toggle = useCallback27((e) => {
23471
+ const toggle = useCallback42((e) => {
23011
23472
  if (readIsPlaying()) {
23012
23473
  pause();
23013
23474
  } else {
23014
23475
  play(e);
23015
23476
  }
23016
23477
  }, [pause, play, readIsPlaying]);
23017
- return useMemo54(() => {
23478
+ return useMemo410(() => {
23018
23479
  return {
23019
23480
  frameBack,
23020
23481
  frameForward,
@@ -23044,491 +23505,6 @@ var usePlayerMethods = () => {
23044
23505
  toggle
23045
23506
  ]);
23046
23507
  };
23047
- var useBrowserMediaSession = ({
23048
- browserMediaControlsBehavior,
23049
- videoConfig,
23050
- playbackRate
23051
- }) => {
23052
- const playing = Internals.usePlaying();
23053
- const { pause, play, emitter, getCurrentFrame, seek } = usePlayerMethods();
23054
- const hasEverPlayed = useRef210(false);
23055
- useEffect33(() => {
23056
- if (playing) {
23057
- hasEverPlayed.current = true;
23058
- }
23059
- if (!navigator.mediaSession) {
23060
- return;
23061
- }
23062
- if (browserMediaControlsBehavior.mode === "do-nothing") {
23063
- return;
23064
- }
23065
- if (playing) {
23066
- navigator.mediaSession.playbackState = "playing";
23067
- } else if (hasEverPlayed.current) {
23068
- navigator.mediaSession.playbackState = "paused";
23069
- }
23070
- }, [browserMediaControlsBehavior.mode, playing]);
23071
- useEffect33(() => {
23072
- if (!navigator.mediaSession) {
23073
- return;
23074
- }
23075
- if (browserMediaControlsBehavior.mode === "do-nothing") {
23076
- return;
23077
- }
23078
- const onTimeUpdate = () => {
23079
- if (!videoConfig) {
23080
- return;
23081
- }
23082
- if (navigator.mediaSession) {
23083
- navigator.mediaSession.setPositionState({
23084
- duration: videoConfig.durationInFrames / videoConfig.fps,
23085
- playbackRate,
23086
- position: getCurrentFrame() / videoConfig.fps
23087
- });
23088
- }
23089
- };
23090
- emitter.addEventListener("timeupdate", onTimeUpdate);
23091
- return () => {
23092
- emitter.removeEventListener("timeupdate", onTimeUpdate);
23093
- };
23094
- }, [
23095
- browserMediaControlsBehavior.mode,
23096
- emitter,
23097
- getCurrentFrame,
23098
- playbackRate,
23099
- videoConfig
23100
- ]);
23101
- useEffect33(() => {
23102
- if (!navigator.mediaSession) {
23103
- return;
23104
- }
23105
- if (browserMediaControlsBehavior.mode === "do-nothing") {
23106
- return;
23107
- }
23108
- navigator.mediaSession.setActionHandler("play", () => {
23109
- if (browserMediaControlsBehavior.mode === "register-media-session") {
23110
- play();
23111
- }
23112
- });
23113
- navigator.mediaSession.setActionHandler("pause", () => {
23114
- if (browserMediaControlsBehavior.mode === "register-media-session") {
23115
- pause();
23116
- }
23117
- });
23118
- navigator.mediaSession.setActionHandler("seekto", (event) => {
23119
- if (browserMediaControlsBehavior.mode === "register-media-session" && event.seekTime !== undefined && videoConfig) {
23120
- seek(Math.round(event.seekTime * videoConfig.fps));
23121
- }
23122
- });
23123
- navigator.mediaSession.setActionHandler("seekbackward", () => {
23124
- if (browserMediaControlsBehavior.mode === "register-media-session" && videoConfig) {
23125
- seek(Math.max(0, Math.round(getCurrentFrame() - 10 * videoConfig.fps)));
23126
- }
23127
- });
23128
- navigator.mediaSession.setActionHandler("seekforward", () => {
23129
- if (browserMediaControlsBehavior.mode === "register-media-session" && videoConfig) {
23130
- seek(Math.min(videoConfig.durationInFrames - 1, Math.round(getCurrentFrame() + 10 * videoConfig.fps)));
23131
- }
23132
- });
23133
- navigator.mediaSession.setActionHandler("previoustrack", () => {
23134
- if (browserMediaControlsBehavior.mode === "register-media-session") {
23135
- seek(0);
23136
- }
23137
- });
23138
- return () => {
23139
- navigator.mediaSession.metadata = null;
23140
- navigator.mediaSession.setActionHandler("play", null);
23141
- navigator.mediaSession.setActionHandler("pause", null);
23142
- navigator.mediaSession.setActionHandler("seekto", null);
23143
- navigator.mediaSession.setActionHandler("seekbackward", null);
23144
- navigator.mediaSession.setActionHandler("seekforward", null);
23145
- navigator.mediaSession.setActionHandler("previoustrack", null);
23146
- };
23147
- }, [
23148
- browserMediaControlsBehavior.mode,
23149
- getCurrentFrame,
23150
- pause,
23151
- play,
23152
- seek,
23153
- videoConfig
23154
- ]);
23155
- };
23156
- var calculateNextFrame = ({
23157
- time,
23158
- currentFrame: startFrame,
23159
- playbackSpeed,
23160
- fps,
23161
- actualLastFrame,
23162
- actualFirstFrame,
23163
- framesAdvanced,
23164
- shouldLoop
23165
- }) => {
23166
- const op = playbackSpeed < 0 ? Math.ceil : Math.floor;
23167
- const framesToAdvance = op(time * playbackSpeed / (1000 / fps)) - framesAdvanced;
23168
- const nextFrame = framesToAdvance + startFrame;
23169
- const isCurrentFrameOutside = startFrame > actualLastFrame || startFrame < actualFirstFrame;
23170
- const isNextFrameOutside = nextFrame > actualLastFrame || nextFrame < actualFirstFrame;
23171
- const hasEnded = !shouldLoop && isNextFrameOutside && !isCurrentFrameOutside;
23172
- if (playbackSpeed > 0) {
23173
- if (isNextFrameOutside) {
23174
- return {
23175
- nextFrame: actualFirstFrame,
23176
- framesToAdvance,
23177
- hasEnded
23178
- };
23179
- }
23180
- return { nextFrame, framesToAdvance, hasEnded };
23181
- }
23182
- if (isNextFrameOutside) {
23183
- return { nextFrame: actualLastFrame, framesToAdvance, hasEnded };
23184
- }
23185
- return { nextFrame, framesToAdvance, hasEnded };
23186
- };
23187
- var getIsBackgrounded = () => {
23188
- if (typeof document === "undefined") {
23189
- return false;
23190
- }
23191
- return document.visibilityState === "hidden";
23192
- };
23193
- var useIsBackgrounded = () => {
23194
- const isBackgrounded = useRef35(getIsBackgrounded());
23195
- useEffect42(() => {
23196
- const onVisibilityChange = () => {
23197
- isBackgrounded.current = getIsBackgrounded();
23198
- };
23199
- document.addEventListener("visibilitychange", onVisibilityChange);
23200
- return () => {
23201
- document.removeEventListener("visibilitychange", onVisibilityChange);
23202
- };
23203
- }, []);
23204
- return isBackgrounded;
23205
- };
23206
- var setGlobalTimeAnchor = ({
23207
- audioContext,
23208
- audioSyncAnchor,
23209
- absoluteTimeInSeconds,
23210
- globalPlaybackRate,
23211
- logLevel,
23212
- force
23213
- }) => {
23214
- const newAnchor = audioContext.currentTime - absoluteTimeInSeconds / globalPlaybackRate;
23215
- const shift = newAnchor - audioSyncAnchor.value;
23216
- const tolerance = Internals.getAudioSyncAnchorTolerance(audioContext);
23217
- if (Math.abs(shift) < tolerance && !force) {
23218
- return false;
23219
- }
23220
- if (Math.abs(shift) < Number.EPSILON) {
23221
- return false;
23222
- }
23223
- Internals.Log.verbose({ logLevel, tag: "audio-scheduling" }, "Anchor " + (force ? "forcibly " : "") + "changed from %s to %s with shift %s", audioSyncAnchor.value, newAnchor, shift);
23224
- audioSyncAnchor.value = newAnchor;
23225
- return true;
23226
- };
23227
- var shouldForceAnchorChange = (newState) => {
23228
- if (newState === "suspended" || newState === "running-to-suspended") {
23229
- return true;
23230
- }
23231
- if (newState === "closed" || newState === "interrupted" || newState === "running" || newState === "suspended-to-running") {
23232
- return false;
23233
- }
23234
- throw new Error(`Unexpected audio context state: ${newState}`);
23235
- };
23236
- var usePlayback = ({
23237
- loop,
23238
- playbackRate,
23239
- moveToBeginningWhenEnded,
23240
- inFrame,
23241
- outFrame,
23242
- browserMediaControlsBehavior,
23243
- getCurrentFrame,
23244
- muted
23245
- }) => {
23246
- const config = Internals.useUnsafeVideoConfig();
23247
- const fps = config?.fps ?? null;
23248
- const durationInFrames = config?.durationInFrames ?? null;
23249
- const compositionId = config?.id ?? null;
23250
- const frame = Internals.Timeline.useTimelinePosition();
23251
- const playing = Internals.usePlaying();
23252
- const { pause, emitter, isPlaying } = usePlayerMethods();
23253
- const setFrameFromPlayback = Internals.Timeline.useTimelineSetFrameWithoutSeek();
23254
- const sharedAudioContext = useContext310(Internals.SharedAudioContext);
23255
- const { setPlayerMuted } = useContext310(Internals.SetMediaVolumeContext);
23256
- const { isBuffering, subscribeBuffering, seek } = useContext310(Internals.SetTimelineContext);
23257
- const logLevel = Internals.useLogLevel();
23258
- const isBackgroundedRef = useIsBackgrounded();
23259
- const lastTimeUpdateTimestamp = useRef43(0);
23260
- const playbackClockRef = useRef43(null);
23261
- const previousMutedRef = useRef43(muted);
23262
- const anchoredAudioContextRef = useRef43(null);
23263
- useBrowserMediaSession({
23264
- browserMediaControlsBehavior,
23265
- playbackRate,
23266
- videoConfig: config
23267
- });
23268
- useLayoutEffect26(() => {
23269
- if (!sharedAudioContext) {
23270
- return;
23271
- }
23272
- if (!sharedAudioContext.audioContext) {
23273
- return;
23274
- }
23275
- if (fps === null) {
23276
- return;
23277
- }
23278
- if (muted) {
23279
- return;
23280
- }
23281
- const changed = setGlobalTimeAnchor({
23282
- audioContext: sharedAudioContext.audioContext,
23283
- audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
23284
- absoluteTimeInSeconds: frame / fps,
23285
- globalPlaybackRate: playbackRate,
23286
- logLevel,
23287
- force: false
23288
- });
23289
- if (changed) {
23290
- sharedAudioContext.audioSyncAnchorEmitter.dispatch("changed");
23291
- }
23292
- }, [fps, frame, logLevel, playbackRate, sharedAudioContext, muted]);
23293
- useLayoutEffect26(() => {
23294
- const audioContext = sharedAudioContext?.audioContext;
23295
- if (!audioContext) {
23296
- return;
23297
- }
23298
- if (fps === null) {
23299
- return;
23300
- }
23301
- if (muted) {
23302
- return;
23303
- }
23304
- const callback = () => {
23305
- const newState = sharedAudioContext?.getAudioContextState();
23306
- if (newState && shouldForceAnchorChange(newState)) {
23307
- const changed = setGlobalTimeAnchor({
23308
- audioContext,
23309
- audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
23310
- absoluteTimeInSeconds: getCurrentFrame() / fps,
23311
- globalPlaybackRate: playbackRate,
23312
- logLevel,
23313
- force: true
23314
- });
23315
- if (changed) {
23316
- sharedAudioContext.audioSyncAnchorEmitter.dispatch("changed");
23317
- }
23318
- }
23319
- };
23320
- audioContext?.addEventListener("statechange", callback);
23321
- return () => {
23322
- audioContext?.removeEventListener("statechange", callback);
23323
- };
23324
- }, [fps, getCurrentFrame, logLevel, muted, playbackRate, sharedAudioContext]);
23325
- useEffect53(() => {
23326
- const wasMuted = previousMutedRef.current;
23327
- previousMutedRef.current = muted;
23328
- if (fps === null || durationInFrames === null || compositionId === null) {
23329
- playbackClockRef.current = null;
23330
- return;
23331
- }
23332
- if (!playing) {
23333
- playbackClockRef.current = null;
23334
- sharedAudioContext?.suspend?.();
23335
- return;
23336
- }
23337
- if (muted) {
23338
- sharedAudioContext?.suspend?.();
23339
- }
23340
- const previousClock = playbackClockRef.current;
23341
- const shouldRestartClock = previousClock === null || previousClock.compositionId !== compositionId || previousClock.fps !== fps || previousClock.playbackRate !== playbackRate;
23342
- const clock = shouldRestartClock ? {
23343
- compositionId,
23344
- startedTime: performance.now(),
23345
- framesAdvanced: 0,
23346
- fps,
23347
- playbackRate
23348
- } : previousClock;
23349
- playbackClockRef.current = clock;
23350
- if (sharedAudioContext?._experimentalKeepAudioContextAlive && sharedAudioContext.audioContext && !muted) {
23351
- const didUnmute = wasMuted && !muted;
23352
- const didReplaceAudioContext = anchoredAudioContextRef.current !== sharedAudioContext.audioContext;
23353
- const shouldRescheduleAudio = shouldRestartClock || didUnmute || didReplaceAudioContext;
23354
- const changed = setGlobalTimeAnchor({
23355
- audioContext: sharedAudioContext.audioContext,
23356
- audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
23357
- absoluteTimeInSeconds: getCurrentFrame() / fps,
23358
- globalPlaybackRate: playbackRate,
23359
- logLevel,
23360
- force: shouldRescheduleAudio
23361
- });
23362
- anchoredAudioContextRef.current = sharedAudioContext.audioContext;
23363
- if (changed || shouldRescheduleAudio) {
23364
- sharedAudioContext.audioSyncAnchorEmitter.dispatch("changed");
23365
- }
23366
- }
23367
- let hasBeenStopped = false;
23368
- let audioContextFailed = false;
23369
- let reqAnimFrameCall = null;
23370
- let playbackFrame = getCurrentFrame();
23371
- let lastSeekRevision = seek?.revision.current ?? null;
23372
- const cancelQueuedFrame = () => {
23373
- if (reqAnimFrameCall !== null) {
23374
- if (reqAnimFrameCall.type === "raf") {
23375
- cancelAnimationFrame(reqAnimFrameCall.id);
23376
- } else {
23377
- clearTimeout(reqAnimFrameCall.id);
23378
- }
23379
- }
23380
- };
23381
- const stop = () => {
23382
- hasBeenStopped = true;
23383
- cancelQueuedFrame();
23384
- };
23385
- const callback = () => {
23386
- if (hasBeenStopped) {
23387
- return;
23388
- }
23389
- if (!isPlaying()) {
23390
- sharedAudioContext?.suspend?.();
23391
- return;
23392
- }
23393
- if (!muted && !audioContextFailed && !isBuffering()) {
23394
- sharedAudioContext?.resume?.();
23395
- }
23396
- const time = performance.now() - clock.startedTime;
23397
- const actualLastFrame = outFrame ?? durationInFrames - 1;
23398
- const actualFirstFrame = inFrame ?? 0;
23399
- const seekRevision = seek?.revision.current ?? null;
23400
- if (seekRevision !== lastSeekRevision) {
23401
- playbackFrame = getCurrentFrame();
23402
- lastSeekRevision = seekRevision;
23403
- }
23404
- const currentFrame = playbackFrame;
23405
- const { nextFrame, framesToAdvance, hasEnded } = calculateNextFrame({
23406
- time,
23407
- currentFrame,
23408
- playbackSpeed: playbackRate,
23409
- fps,
23410
- actualFirstFrame,
23411
- actualLastFrame,
23412
- framesAdvanced: clock.framesAdvanced,
23413
- shouldLoop: loop
23414
- });
23415
- clock.framesAdvanced += framesToAdvance;
23416
- const frameToDisplay = hasEnded && !moveToBeginningWhenEnded ? playbackRate > 0 ? actualLastFrame : actualFirstFrame : nextFrame;
23417
- if (frameToDisplay !== currentFrame && !isBuffering()) {
23418
- playbackFrame = frameToDisplay;
23419
- setFrameFromPlayback((c) => ({ ...c, [compositionId]: frameToDisplay }));
23420
- }
23421
- if (hasEnded) {
23422
- stop();
23423
- pause();
23424
- emitter.dispatchEnded();
23425
- return;
23426
- }
23427
- queueNextFrame();
23428
- };
23429
- const queueNextFrame = () => {
23430
- if (hasBeenStopped) {
23431
- return;
23432
- }
23433
- const getIsResumingAudioContext = audioContextFailed ? null : sharedAudioContext?.getIsResumingAudioContext?.() ?? null;
23434
- if (getIsResumingAudioContext !== null && !muted) {
23435
- getIsResumingAudioContext.then((result) => {
23436
- if (hasBeenStopped) {
23437
- return;
23438
- }
23439
- if (result === "failed") {
23440
- audioContextFailed = true;
23441
- sharedAudioContext?.suspend();
23442
- setPlayerMuted(true);
23443
- }
23444
- clock.startedTime = performance.now();
23445
- clock.framesAdvanced = 0;
23446
- queueNextFrame();
23447
- });
23448
- return;
23449
- }
23450
- if (isBuffering()) {
23451
- if (!muted && !audioContextFailed) {
23452
- sharedAudioContext?.suspend?.();
23453
- }
23454
- const unsubscribe = subscribeBuffering((state) => {
23455
- if (state.buffering) {
23456
- return;
23457
- }
23458
- unsubscribe();
23459
- if (!muted && !audioContextFailed && sharedAudioContext?._experimentalKeepAudioContextAlive) {
23460
- sharedAudioContext.resume();
23461
- }
23462
- clock.startedTime = performance.now();
23463
- clock.framesAdvanced = 0;
23464
- queueNextFrame();
23465
- });
23466
- return;
23467
- }
23468
- if (isBackgroundedRef.current) {
23469
- reqAnimFrameCall = {
23470
- type: "timeout",
23471
- id: setTimeout(callback, 1000 / fps)
23472
- };
23473
- return;
23474
- }
23475
- reqAnimFrameCall = { type: "raf", id: requestAnimationFrame(callback) };
23476
- };
23477
- queueNextFrame();
23478
- const onVisibilityChange = () => {
23479
- if (document.visibilityState === "visible") {
23480
- return;
23481
- }
23482
- cancelQueuedFrame();
23483
- callback();
23484
- };
23485
- window.addEventListener("visibilitychange", onVisibilityChange);
23486
- return () => {
23487
- window.removeEventListener("visibilitychange", onVisibilityChange);
23488
- stop();
23489
- };
23490
- }, [
23491
- compositionId,
23492
- durationInFrames,
23493
- fps,
23494
- loop,
23495
- pause,
23496
- playing,
23497
- setFrameFromPlayback,
23498
- emitter,
23499
- playbackRate,
23500
- inFrame,
23501
- outFrame,
23502
- moveToBeginningWhenEnded,
23503
- isBackgroundedRef,
23504
- getCurrentFrame,
23505
- isBuffering,
23506
- isPlaying,
23507
- sharedAudioContext,
23508
- setPlayerMuted,
23509
- subscribeBuffering,
23510
- seek,
23511
- logLevel,
23512
- muted
23513
- ]);
23514
- useEffect53(() => {
23515
- const now = performance.now();
23516
- const timeSinceLastUpdate = now - lastTimeUpdateTimestamp.current;
23517
- if (timeSinceLastUpdate >= 250) {
23518
- emitter.dispatchTimeUpdate({ frame });
23519
- lastTimeUpdateTimestamp.current = now;
23520
- return;
23521
- }
23522
- const timeoutId = setTimeout(() => {
23523
- emitter.dispatchTimeUpdate({ frame });
23524
- lastTimeUpdateTimestamp.current = performance.now();
23525
- }, 250 - timeSinceLastUpdate);
23526
- return () => clearTimeout(timeoutId);
23527
- }, [emitter, frame]);
23528
- useEffect53(() => {
23529
- emitter.dispatchFrameUpdate({ frame });
23530
- }, [emitter, frame]);
23531
- };
23532
23508
  var elementSizeHooks = [];
23533
23509
  var getElement = (source) => {
23534
23510
  if (!source) {
@@ -23540,7 +23516,7 @@ var getElement = (source) => {
23540
23516
  return source;
23541
23517
  };
23542
23518
  var useElementSize = (source, options) => {
23543
- const [size, setSize] = useState33(() => {
23519
+ const [size, setSize] = useState72(() => {
23544
23520
  const element = getElement(source);
23545
23521
  if (!element) {
23546
23522
  return null;
@@ -23560,7 +23536,7 @@ var useElementSize = (source, options) => {
23560
23536
  }
23561
23537
  };
23562
23538
  });
23563
- const observer = useMemo210(() => {
23539
+ const observer = useMemo55(() => {
23564
23540
  if (typeof ResizeObserver === "undefined") {
23565
23541
  return null;
23566
23542
  }
@@ -23593,7 +23569,7 @@ var useElementSize = (source, options) => {
23593
23569
  });
23594
23570
  });
23595
23571
  }, [options.shouldApplyCssTransforms]);
23596
- const updateSize = useCallback28(() => {
23572
+ const updateSize = useCallback52(() => {
23597
23573
  const element = getElement(source);
23598
23574
  if (!element) {
23599
23575
  return;
@@ -23620,10 +23596,10 @@ var useElementSize = (source, options) => {
23620
23596
  };
23621
23597
  });
23622
23598
  }, [source]);
23623
- useEffect62(() => {
23599
+ useEffect53(() => {
23624
23600
  updateSize();
23625
23601
  }, [updateSize]);
23626
- useEffect62(() => {
23602
+ useEffect53(() => {
23627
23603
  if (!observer) {
23628
23604
  return;
23629
23605
  }
@@ -23637,7 +23613,7 @@ var useElementSize = (source, options) => {
23637
23613
  }
23638
23614
  };
23639
23615
  }, [observer, source]);
23640
- useEffect62(() => {
23616
+ useEffect53(() => {
23641
23617
  if (!options.triggerOnWindowResize) {
23642
23618
  return;
23643
23619
  }
@@ -23646,573 +23622,26 @@ var useElementSize = (source, options) => {
23646
23622
  window.removeEventListener("resize", updateSize);
23647
23623
  };
23648
23624
  }, [options.triggerOnWindowResize, updateSize]);
23649
- useEffect62(() => {
23625
+ useEffect53(() => {
23650
23626
  elementSizeHooks.push(updateSize);
23651
23627
  return () => {
23652
23628
  elementSizeHooks = elementSizeHooks.filter((e) => e !== updateSize);
23653
23629
  };
23654
23630
  }, [updateSize]);
23655
- return useMemo210(() => {
23631
+ return useMemo55(() => {
23656
23632
  if (!size) {
23657
23633
  return null;
23658
23634
  }
23659
23635
  return { ...size, refresh: updateSize };
23660
23636
  }, [size, updateSize]);
23661
23637
  };
23662
- var playerCssClassname = (override) => {
23663
- return override ?? "__remotion-player";
23664
- };
23665
- var errorStyle = {
23666
- display: "flex",
23667
- justifyContent: "center",
23668
- alignItems: "center",
23669
- flex: 1,
23670
- height: "100%",
23671
- width: "100%"
23672
- };
23673
-
23674
- class ErrorBoundary extends React42.Component {
23675
- state = { hasError: null };
23676
- static getDerivedStateFromError(error) {
23677
- return { hasError: error };
23678
- }
23679
- componentDidCatch(error) {
23680
- this.props.onError(error);
23681
- }
23682
- render() {
23683
- if (this.state.hasError) {
23684
- return /* @__PURE__ */ jsx410("div", {
23685
- style: errorStyle,
23686
- children: this.props.errorFallback({
23687
- error: this.state.hasError
23688
- })
23689
- });
23690
- }
23691
- return this.props.children;
23692
- }
23693
- }
23694
- var getHashOfDomain = async () => {
23695
- if (typeof window === "undefined") {
23696
- return null;
23697
- }
23698
- if (typeof window.crypto === "undefined") {
23699
- return null;
23700
- }
23701
- if (typeof window.crypto.subtle === "undefined") {
23702
- return null;
23703
- }
23704
- try {
23705
- const hashBuffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(window.location.hostname));
23706
- return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
23707
- } catch {
23708
- return null;
23709
- }
23710
- };
23711
- var style = {
23712
- backgroundColor: "red",
23713
- position: "absolute",
23714
- padding: 12,
23715
- fontFamily: "Arial"
23716
- };
23717
- var DOMAIN_BLACKLIST = [
23718
- "28d262b44cc61fa750f1686b16ad0604dabfe193fbc263eec05c89b7ad4c2cd6",
23719
- "4db1b0a94be33165dfefcb3ba03d04c7a2666dd27c496d3dc9fa41858e94925e",
23720
- "fbc48530bbf245da790f63675e84e06bab38c3b114fab07eb350025119922bdc",
23721
- "7baf10a8932757b1b3a22b3fce10a048747ac2f8eaf638603487e3705b07eb83",
23722
- "8a6c21a598d8c667272b5207c051b85997bf5b45d5fb712378be3f27cd72c6a6",
23723
- "a2f7aaac9c50a9255e7fc376110c4e0bfe153722dc66ed3c5d3bf2a135f65518"
23724
- ];
23725
- var ran = false;
23726
- var RenderWarningIfBlacklist = () => {
23727
- const [unlicensed, setUnlicensed] = React53.useState(false);
23728
- useEffect72(() => {
23729
- if (ran) {
23730
- return;
23731
- }
23732
- ran = true;
23733
- getHashOfDomain().then((hash) => {
23734
- if (hash && DOMAIN_BLACKLIST.includes(hash)) {
23735
- setUnlicensed(true);
23736
- }
23737
- }).catch(() => {});
23738
- }, []);
23739
- useEffect72(() => {
23740
- if (!unlicensed) {
23741
- return;
23742
- }
23743
- const ensureBanner = () => {
23744
- const banner = document.querySelector(".warning-banner");
23745
- if (!banner) {
23746
- const div = document.createElement("div");
23747
- div.className = "warning-banner";
23748
- Object.assign(div.style, style, {
23749
- zIndex: "9999",
23750
- cssText: `${style.cssText} !important;`
23751
- });
23752
- div.innerHTML = `
23753
- <a href="https://github.com/remotion-dev/remotion/pull/4589" style="color: white;">
23754
- Remotion Unlicensed – Contact hi@remotion.dev
23755
- </a>
23756
- `;
23757
- document.body.appendChild(div);
23758
- }
23759
- };
23760
- const observer = new MutationObserver(() => ensureBanner());
23761
- observer.observe(document.body, { childList: true, subtree: true });
23762
- return () => {
23763
- observer.disconnect();
23764
- };
23765
- }, [unlicensed]);
23766
- if (!unlicensed) {
23767
- return null;
23768
- }
23769
- return /* @__PURE__ */ jsx53("div", {
23770
- style,
23771
- className: "warning-banner",
23772
- children: /* @__PURE__ */ jsx53("a", {
23773
- style: { color: "white" },
23774
- href: "https://github.com/remotion-dev/remotion/pull/4589",
23775
- children: "Remotion Unlicensed – Contact hi@remotion.dev"
23776
- })
23777
- });
23778
- };
23779
- var DefaultPlayPauseButton = ({ playing, buffering }) => {
23780
- if (playing && buffering) {
23781
- return /* @__PURE__ */ jsx63(BufferingIndicator, {
23782
- type: "player"
23783
- });
23784
- }
23785
- if (playing) {
23786
- return /* @__PURE__ */ jsx63(PauseIcon, {});
23787
- }
23788
- return /* @__PURE__ */ jsx63(PlayIcon, {});
23789
- };
23790
- var KNOB_SIZE = 12;
23791
- var BAR_HEIGHT = 5;
23792
- var DefaultVolumeSlider = ({
23793
- volume,
23794
- isVertical,
23795
- onBlur,
23796
- inputRef,
23797
- setVolume
23798
- }) => {
23799
- const sliderContainer = useMemo310(() => {
23800
- const paddingLeft = 5;
23801
- const common = {
23802
- paddingLeft,
23803
- height: ICON_SIZE2,
23804
- width: VOLUME_SLIDER_WIDTH,
23805
- display: "inline-flex",
23806
- alignItems: "center"
23807
- };
23808
- if (isVertical) {
23809
- return {
23810
- ...common,
23811
- position: "absolute",
23812
- transform: `rotate(-90deg) translateX(${VOLUME_SLIDER_WIDTH / 2 + ICON_SIZE2 / 2}px)`
23813
- };
23814
- }
23815
- return {
23816
- ...common
23817
- };
23818
- }, [isVertical]);
23819
- const randomId = typeof React62.useId === "undefined" ? "volume-slider" : React62.useId();
23820
- const [randomClass] = useState43(() => `__remotion-volume-slider-${random(randomId)}`.replace(".", ""));
23821
- const onVolumeChange = useCallback32((e) => {
23822
- setVolume(parseFloat(e.target.value));
23823
- }, [setVolume]);
23824
- const inputStyle = useMemo310(() => {
23825
- const commonStyle = {
23826
- WebkitAppearance: "none",
23827
- backgroundColor: "rgba(255, 255, 255, 0.5)",
23828
- borderRadius: BAR_HEIGHT / 2,
23829
- cursor: "pointer",
23830
- height: BAR_HEIGHT,
23831
- width: VOLUME_SLIDER_WIDTH,
23832
- backgroundImage: `linear-gradient(
23833
- to right,
23834
- white ${volume * 100}%, rgba(255, 255, 255, 0) ${volume * 100}%
23835
- )`
23836
- };
23837
- if (isVertical) {
23838
- return {
23839
- ...commonStyle,
23840
- bottom: ICON_SIZE2 + VOLUME_SLIDER_WIDTH / 2
23841
- };
23842
- }
23843
- return commonStyle;
23844
- }, [isVertical, volume]);
23845
- const sliderStyle = `
23846
- .${randomClass}::-webkit-slider-thumb {
23847
- -webkit-appearance: none;
23848
- background-color: white;
23849
- border-radius: ${KNOB_SIZE / 2}px;
23850
- box-shadow: 0 0 2px black;
23851
- height: ${KNOB_SIZE}px;
23852
- width: ${KNOB_SIZE}px;
23853
- }
23854
-
23855
- .${randomClass}::-moz-range-thumb {
23856
- -webkit-appearance: none;
23857
- background-color: white;
23858
- border-radius: ${KNOB_SIZE / 2}px;
23859
- box-shadow: 0 0 2px black;
23860
- height: ${KNOB_SIZE}px;
23861
- width: ${KNOB_SIZE}px;
23862
- }
23863
- `;
23864
- return /* @__PURE__ */ jsxs33("div", {
23865
- style: sliderContainer,
23866
- children: [
23867
- /* @__PURE__ */ jsx73("style", {
23868
- dangerouslySetInnerHTML: {
23869
- __html: sliderStyle
23870
- }
23871
- }),
23872
- /* @__PURE__ */ jsx73("input", {
23873
- ref: inputRef,
23874
- "aria-label": "Change volume",
23875
- className: randomClass,
23876
- max: 1,
23877
- min: 0,
23878
- onBlur,
23879
- onChange: onVolumeChange,
23880
- step: 0.01,
23881
- type: "range",
23882
- value: volume,
23883
- style: inputStyle
23884
- })
23885
- ]
23886
- });
23887
- };
23888
- var renderDefaultVolumeSlider = (props) => {
23889
- return /* @__PURE__ */ jsx73(DefaultVolumeSlider, {
23890
- ...props
23891
- });
23892
- };
23893
- var VOLUME_SLIDER_WIDTH = 100;
23894
- var MediaVolumeSlider = ({ displayVerticalVolumeSlider, renderMuteButton, renderVolumeSlider }) => {
23895
- const [playerMuted, setPlayerMuted] = Internals.usePlayerMutedState();
23896
- const [mediaVolume, setMediaVolume] = Internals.useMediaVolumeState();
23897
- const [focused, setFocused] = useState52(false);
23898
- const parentDivRef = useRef52(null);
23899
- const inputRef = useRef52(null);
23900
- const hover = useHoverState(parentDivRef, false);
23901
- const onBlur = useCallback42(() => {
23902
- setTimeout(() => {
23903
- if (inputRef.current && document.activeElement !== inputRef.current) {
23904
- setFocused(false);
23905
- }
23906
- }, 10);
23907
- }, []);
23908
- const isVolume0 = mediaVolume === 0;
23909
- const onClick = useCallback42(() => {
23910
- if (isVolume0) {
23911
- setMediaVolume(1);
23912
- setPlayerMuted(false);
23913
- return;
23914
- }
23915
- setPlayerMuted((mute) => !mute);
23916
- }, [isVolume0, setPlayerMuted, setMediaVolume]);
23917
- const parentDivStyle = useMemo410(() => {
23918
- return {
23919
- display: "inline-flex",
23920
- background: "none",
23921
- border: "none",
23922
- justifyContent: "center",
23923
- alignItems: "center",
23924
- touchAction: "none",
23925
- ...displayVerticalVolumeSlider && { position: "relative" }
23926
- };
23927
- }, [displayVerticalVolumeSlider]);
23928
- const volumeContainer = useMemo410(() => {
23929
- return {
23930
- display: "inline",
23931
- width: ICON_SIZE2,
23932
- height: ICON_SIZE2,
23933
- cursor: "pointer",
23934
- appearance: "none",
23935
- background: "none",
23936
- border: "none",
23937
- padding: 0
23938
- };
23939
- }, []);
23940
- const renderDefaultMuteButton = useCallback42(({ muted, volume }) => {
23941
- const isMutedOrZero = muted || volume === 0;
23942
- return /* @__PURE__ */ jsx82("button", {
23943
- "aria-label": isMutedOrZero ? "Unmute sound" : "Mute sound",
23944
- title: isMutedOrZero ? "Unmute sound" : "Mute sound",
23945
- onClick,
23946
- onBlur,
23947
- onFocus: () => setFocused(true),
23948
- style: volumeContainer,
23949
- type: "button",
23950
- children: isMutedOrZero ? /* @__PURE__ */ jsx82(VolumeOffIcon, {}) : /* @__PURE__ */ jsx82(VolumeOnIcon, {})
23951
- });
23952
- }, [onBlur, onClick, volumeContainer]);
23953
- const muteButton = useMemo410(() => {
23954
- return renderMuteButton ? renderMuteButton({ muted: playerMuted, volume: mediaVolume }) : renderDefaultMuteButton({ muted: playerMuted, volume: mediaVolume });
23955
- }, [playerMuted, mediaVolume, renderDefaultMuteButton, renderMuteButton]);
23956
- const volumeSlider = useMemo410(() => {
23957
- return (focused || hover) && !playerMuted && !Internals.isIosSafari() ? (renderVolumeSlider ?? renderDefaultVolumeSlider)({
23958
- isVertical: displayVerticalVolumeSlider,
23959
- volume: mediaVolume,
23960
- onBlur: () => setFocused(false),
23961
- inputRef,
23962
- setVolume: setMediaVolume
23963
- }) : null;
23964
- }, [
23965
- displayVerticalVolumeSlider,
23966
- focused,
23967
- hover,
23968
- playerMuted,
23969
- mediaVolume,
23970
- renderVolumeSlider,
23971
- setMediaVolume
23972
- ]);
23973
- return /* @__PURE__ */ jsxs42("div", {
23974
- ref: parentDivRef,
23975
- style: parentDivStyle,
23976
- children: [
23977
- muteButton,
23978
- volumeSlider
23979
- ]
23980
- });
23981
- };
23982
- function useComponentVisible(initialIsVisible) {
23983
- const [isComponentVisible, setIsComponentVisible] = useState62(initialIsVisible);
23984
- const ref = useRef62(null);
23985
- useEffect82(() => {
23986
- const handleClickOutside = (event) => {
23987
- if (ref.current && !ref.current.contains(event.target)) {
23988
- setIsComponentVisible(false);
23989
- }
23990
- };
23991
- document.addEventListener("pointerup", handleClickOutside, true);
23992
- return () => {
23993
- document.removeEventListener("pointerup", handleClickOutside, true);
23994
- };
23995
- }, []);
23996
- return { ref, isComponentVisible, setIsComponentVisible };
23997
- }
23998
- var BOTTOM = 35;
23999
- var THRESHOLD = 70;
24000
- var rateDiv = {
24001
- height: 30,
24002
- paddingRight: 15,
24003
- paddingLeft: 12,
24004
- display: "flex",
24005
- flexDirection: "row",
24006
- alignItems: "center"
24007
- };
24008
- var checkmarkContainer = {
24009
- width: 22,
24010
- display: "flex",
24011
- alignItems: "center"
24012
- };
24013
- var checkmarkStyle = {
24014
- width: 14,
24015
- height: 14,
24016
- color: "black"
24017
- };
24018
- var Checkmark = () => /* @__PURE__ */ jsx92("svg", {
24019
- viewBox: "0 0 512 512",
24020
- style: checkmarkStyle,
24021
- children: /* @__PURE__ */ jsx92("path", {
24022
- fill: "currentColor",
24023
- d: "M435.848 83.466L172.804 346.51l-96.652-96.652c-4.686-4.686-12.284-4.686-16.971 0l-28.284 28.284c-4.686 4.686-4.686 12.284 0 16.971l133.421 133.421c4.686 4.686 12.284 4.686 16.971 0l299.813-299.813c4.686-4.686 4.686-12.284 0-16.971l-28.284-28.284c-4.686-4.686-12.284-4.686-16.97 0z"
24024
- })
24025
- });
24026
- var formatPlaybackRate = (rate) => {
24027
- const str = rate.toString();
24028
- return str.includes(".") ? str : str + ".0";
24029
- };
24030
- var PlaybackrateOption = ({ rate, onSelect, selectedRate, keyboardSelectedRate }) => {
24031
- const onClick = useCallback52((e) => {
24032
- e.stopPropagation();
24033
- e.preventDefault();
24034
- onSelect(rate);
24035
- }, [onSelect, rate]);
24036
- const [hovered, setHovered] = useState72(false);
24037
- const onMouseEnter = useCallback52(() => {
24038
- setHovered(true);
24039
- }, []);
24040
- const onMouseLeave = useCallback52(() => {
24041
- setHovered(false);
24042
- }, []);
24043
- const isFocused = keyboardSelectedRate === rate;
24044
- const actualStyle = useMemo55(() => {
24045
- return {
24046
- ...rateDiv,
24047
- backgroundColor: hovered || isFocused ? "#eee" : "transparent"
24048
- };
24049
- }, [hovered, isFocused]);
24050
- return /* @__PURE__ */ jsxs52("div", {
24051
- onPointerEnter: onMouseEnter,
24052
- onPointerLeave: onMouseLeave,
24053
- tabIndex: 0,
24054
- style: actualStyle,
24055
- onClick,
24056
- children: [
24057
- /* @__PURE__ */ jsx92("div", {
24058
- style: checkmarkContainer,
24059
- children: rate === selectedRate ? /* @__PURE__ */ jsx92(Checkmark, {}) : null
24060
- }),
24061
- formatPlaybackRate(rate),
24062
- "x"
24063
- ]
24064
- }, rate);
24065
- };
24066
- var PlaybackPopup = ({ setIsComponentVisible, playbackRates, canvasSize }) => {
24067
- const { setPlaybackRate, playbackRate } = Internals.usePlaybackRate();
24068
- const [keyboardSelectedRate, setKeyboardSelectedRate] = useState72(playbackRate);
24069
- useEffect92(() => {
24070
- const listener = (e) => {
24071
- if (e.ctrlKey || e.metaKey || e.altKey) {
24072
- return;
24073
- }
24074
- if (e.key === "ArrowUp") {
24075
- e.preventDefault();
24076
- const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
24077
- if (currentIndex === 0) {
24078
- return;
24079
- }
24080
- if (currentIndex === -1) {
24081
- setKeyboardSelectedRate(playbackRates[0]);
24082
- } else {
24083
- setKeyboardSelectedRate(playbackRates[currentIndex - 1]);
24084
- }
24085
- } else if (e.key === "ArrowDown") {
24086
- e.preventDefault();
24087
- const currentIndex = playbackRates.findIndex((rate) => rate === keyboardSelectedRate);
24088
- if (currentIndex === playbackRates.length - 1) {
24089
- return;
24090
- }
24091
- if (currentIndex === -1) {
24092
- setKeyboardSelectedRate(playbackRates[playbackRates.length - 1]);
24093
- } else {
24094
- setKeyboardSelectedRate(playbackRates[currentIndex + 1]);
24095
- }
24096
- } else if (e.key === "Enter") {
24097
- e.preventDefault();
24098
- setPlaybackRate(keyboardSelectedRate);
24099
- setIsComponentVisible(false);
24100
- } else if (e.key === "Escape") {
24101
- e.preventDefault();
24102
- setIsComponentVisible(false);
24103
- } else if (e.key === "Tab") {
24104
- setIsComponentVisible(false);
24105
- }
24106
- };
24107
- window.addEventListener("keydown", listener);
24108
- return () => {
24109
- window.removeEventListener("keydown", listener);
24110
- };
24111
- }, [
24112
- playbackRates,
24113
- keyboardSelectedRate,
24114
- setPlaybackRate,
24115
- setIsComponentVisible
24116
- ]);
24117
- const onSelect = useCallback52((rate) => {
24118
- setPlaybackRate(rate);
24119
- setIsComponentVisible(false);
24120
- }, [setIsComponentVisible, setPlaybackRate]);
24121
- const playbackPopup = useMemo55(() => {
24122
- return {
24123
- position: "absolute",
24124
- right: 0,
24125
- width: 125,
24126
- maxHeight: canvasSize.height - THRESHOLD - BOTTOM,
24127
- bottom: 35,
24128
- background: "#fff",
24129
- borderRadius: 4,
24130
- overflow: "auto",
24131
- color: "black",
24132
- textAlign: "left"
24133
- };
24134
- }, [canvasSize.height]);
24135
- return /* @__PURE__ */ jsx92("div", {
24136
- style: playbackPopup,
24137
- children: playbackRates.map((rate) => {
24138
- return /* @__PURE__ */ jsx92(PlaybackrateOption, {
24139
- selectedRate: playbackRate,
24140
- onSelect,
24141
- rate,
24142
- keyboardSelectedRate
24143
- }, rate);
24144
- })
24145
- });
24146
- };
24147
- var label2 = {
24148
- fontSize: 13,
24149
- fontWeight: "bold",
24150
- color: "white",
24151
- border: "2px solid white",
24152
- borderRadius: 20,
24153
- paddingLeft: 8,
24154
- paddingRight: 8,
24155
- paddingTop: 2,
24156
- paddingBottom: 2
24157
- };
24158
- var playerButtonStyle = {
24159
- appearance: "none",
24160
- backgroundColor: "transparent",
24161
- border: "none",
24162
- cursor: "pointer",
24163
- paddingLeft: 0,
24164
- paddingRight: 0,
24165
- paddingTop: 6,
24166
- paddingBottom: 6,
24167
- height: 37,
24168
- display: "inline-flex",
24169
- marginBottom: 0,
24170
- marginTop: 0,
24171
- alignItems: "center"
24172
- };
24173
- var button = {
24174
- ...playerButtonStyle,
24175
- position: "relative"
24176
- };
24177
- var PlaybackrateControl = ({ playbackRates, canvasSize }) => {
24178
- const { ref, isComponentVisible, setIsComponentVisible } = useComponentVisible(false);
24179
- const { playbackRate } = Internals.usePlaybackRate();
24180
- const onClick = useCallback52((e) => {
24181
- e.stopPropagation();
24182
- e.preventDefault();
24183
- setIsComponentVisible((prevIsComponentVisible) => !prevIsComponentVisible);
24184
- }, [setIsComponentVisible]);
24185
- return /* @__PURE__ */ jsx92("div", {
24186
- ref,
24187
- children: /* @__PURE__ */ jsxs52("button", {
24188
- type: "button",
24189
- "aria-label": "Change playback rate",
24190
- style: button,
24191
- onClick,
24192
- children: [
24193
- /* @__PURE__ */ jsxs52("div", {
24194
- style: label2,
24195
- children: [
24196
- playbackRate,
24197
- "x"
24198
- ]
24199
- }),
24200
- isComponentVisible && /* @__PURE__ */ jsx92(PlaybackPopup, {
24201
- canvasSize,
24202
- playbackRates,
24203
- setIsComponentVisible
24204
- })
24205
- ]
24206
- })
24207
- });
24208
- };
24209
- var getFrameFromX = (clientX, durationInFrames, width) => {
24210
- const pos = clientX;
24211
- const frame = Math.round(interpolate(pos, [0, width], [0, durationInFrames - 1], {
24212
- extrapolateLeft: "clamp",
24213
- extrapolateRight: "clamp"
24214
- }));
24215
- return frame;
23638
+ var getFrameFromX = (clientX, durationInFrames, width) => {
23639
+ const pos = clientX;
23640
+ const frame = Math.round(interpolate(pos, [0, width], [0, durationInFrames - 1], {
23641
+ extrapolateLeft: "clamp",
23642
+ extrapolateRight: "clamp"
23643
+ }));
23644
+ return frame;
24216
23645
  };
24217
23646
  var BAR_HEIGHT2 = 5;
24218
23647
  var KNOB_SIZE2 = 12;
@@ -24241,7 +23670,7 @@ var findBodyInWhichDivIsLocated = (div) => {
24241
23670
  return current;
24242
23671
  };
24243
23672
  var PlayerSeekBar = ({ durationInFrames, onSeekEnd, onSeekStart, inFrame, outFrame }) => {
24244
- const containerRef = useRef72(null);
23673
+ const containerRef = useRef43(null);
24245
23674
  const barHovered = useHoverState(containerRef, false);
24246
23675
  const size = useElementSize(containerRef, {
24247
23676
  triggerOnWindowResize: true,
@@ -24293,7 +23722,7 @@ var PlayerSeekBar = ({ durationInFrames, onSeekEnd, onSeekStart, inFrame, outFra
24293
23722
  }
24294
23723
  onSeekEnd();
24295
23724
  }, [dragging, onSeekEnd, pause, play]);
24296
- useEffect102(() => {
23725
+ useEffect62(() => {
24297
23726
  if (!dragging.dragging) {
24298
23727
  return;
24299
23728
  }
@@ -24345,15 +23774,15 @@ var PlayerSeekBar = ({ durationInFrames, onSeekEnd, onSeekStart, inFrame, outFra
24345
23774
  /* @__PURE__ */ jsxs62("div", {
24346
23775
  style: barBackground,
24347
23776
  children: [
24348
- /* @__PURE__ */ jsx102("div", {
23777
+ /* @__PURE__ */ jsx82("div", {
24349
23778
  style: active
24350
23779
  }),
24351
- /* @__PURE__ */ jsx102("div", {
23780
+ /* @__PURE__ */ jsx82("div", {
24352
23781
  style: fillStyle
24353
23782
  })
24354
23783
  ]
24355
23784
  }),
24356
- /* @__PURE__ */ jsx102("div", {
23785
+ /* @__PURE__ */ jsx82("div", {
24357
23786
  style: knobStyle
24358
23787
  })
24359
23788
  ]
@@ -24375,333 +23804,936 @@ var PlayerTimeLabel = ({ durationInFrames, maxTimeLabelWidth, fps }) => {
24375
23804
  overflow: "hidden",
24376
23805
  textOverflow: "ellipsis"
24377
23806
  };
24378
- }, [maxTimeLabelWidth]);
24379
- const isLastFrame = frame === durationInFrames - 1;
24380
- const frameToDisplay = isLastFrame ? frame + 1 : frame;
24381
- return /* @__PURE__ */ jsxs72("div", {
24382
- style: timeLabel,
24383
- children: [
24384
- formatTime(frameToDisplay / fps),
24385
- " / ",
24386
- formatTime(durationInFrames / fps)
24387
- ]
24388
- });
24389
- };
24390
- var X_SPACER = 10;
24391
- var X_PADDING = 12;
24392
- var useVideoControlsResize = ({
24393
- allowFullscreen: allowFullScreen,
24394
- playerWidth
24395
- }) => {
24396
- const resizeInfo = useMemo82(() => {
24397
- const playPauseIconSize = ICON_SIZE2;
24398
- const volumeIconSize = ICON_SIZE2;
24399
- const _fullscreenIconSize = allowFullScreen ? fullscreenIconSize : 0;
24400
- const elementsSize = volumeIconSize + playPauseIconSize + _fullscreenIconSize + X_PADDING * 2 + X_SPACER * 2;
24401
- const maxTimeLabelWidth = playerWidth - elementsSize;
24402
- const maxTimeLabelWidthWithoutNegativeValue = Math.max(maxTimeLabelWidth, 0);
24403
- const availableTimeLabelWidthIfVolumeOpen = maxTimeLabelWidthWithoutNegativeValue - VOLUME_SLIDER_WIDTH;
24404
- const computedLabelWidth = availableTimeLabelWidthIfVolumeOpen < VOLUME_SLIDER_WIDTH ? maxTimeLabelWidthWithoutNegativeValue : availableTimeLabelWidthIfVolumeOpen;
24405
- const minWidthForHorizontalDisplay = computedLabelWidth + elementsSize + VOLUME_SLIDER_WIDTH;
24406
- const displayVerticalVolumeSlider = playerWidth < minWidthForHorizontalDisplay;
24407
- return {
24408
- maxTimeLabelWidth: maxTimeLabelWidthWithoutNegativeValue === 0 ? null : maxTimeLabelWidthWithoutNegativeValue,
24409
- displayVerticalVolumeSlider
23807
+ }, [maxTimeLabelWidth]);
23808
+ const isLastFrame = frame === durationInFrames - 1;
23809
+ const frameToDisplay = isLastFrame ? frame + 1 : frame;
23810
+ return /* @__PURE__ */ jsxs72("div", {
23811
+ style: timeLabel,
23812
+ children: [
23813
+ formatTime(frameToDisplay / fps),
23814
+ " / ",
23815
+ formatTime(durationInFrames / fps)
23816
+ ]
23817
+ });
23818
+ };
23819
+ var X_SPACER = 10;
23820
+ var X_PADDING = 12;
23821
+ var useVideoControlsResize = ({
23822
+ allowFullscreen: allowFullScreen,
23823
+ playerWidth
23824
+ }) => {
23825
+ const resizeInfo = useMemo82(() => {
23826
+ const playPauseIconSize = ICON_SIZE2;
23827
+ const volumeIconSize = ICON_SIZE2;
23828
+ const _fullscreenIconSize = allowFullScreen ? fullscreenIconSize : 0;
23829
+ const elementsSize = volumeIconSize + playPauseIconSize + _fullscreenIconSize + X_PADDING * 2 + X_SPACER * 2;
23830
+ const maxTimeLabelWidth = playerWidth - elementsSize;
23831
+ const maxTimeLabelWidthWithoutNegativeValue = Math.max(maxTimeLabelWidth, 0);
23832
+ const availableTimeLabelWidthIfVolumeOpen = maxTimeLabelWidthWithoutNegativeValue - VOLUME_SLIDER_WIDTH;
23833
+ const computedLabelWidth = availableTimeLabelWidthIfVolumeOpen < VOLUME_SLIDER_WIDTH ? maxTimeLabelWidthWithoutNegativeValue : availableTimeLabelWidthIfVolumeOpen;
23834
+ const minWidthForHorizontalDisplay = computedLabelWidth + elementsSize + VOLUME_SLIDER_WIDTH;
23835
+ const displayVerticalVolumeSlider = playerWidth < minWidthForHorizontalDisplay;
23836
+ return {
23837
+ maxTimeLabelWidth: maxTimeLabelWidthWithoutNegativeValue === 0 ? null : maxTimeLabelWidthWithoutNegativeValue,
23838
+ displayVerticalVolumeSlider
23839
+ };
23840
+ }, [allowFullScreen, playerWidth]);
23841
+ return resizeInfo;
23842
+ };
23843
+ var gradientSteps = [
23844
+ 0,
23845
+ 0.013,
23846
+ 0.049,
23847
+ 0.104,
23848
+ 0.175,
23849
+ 0.259,
23850
+ 0.352,
23851
+ 0.45,
23852
+ 0.55,
23853
+ 0.648,
23854
+ 0.741,
23855
+ 0.825,
23856
+ 0.896,
23857
+ 0.951,
23858
+ 0.987
23859
+ ];
23860
+ var gradientOpacities = [
23861
+ 0,
23862
+ 8.1,
23863
+ 15.5,
23864
+ 22.5,
23865
+ 29,
23866
+ 35.3,
23867
+ 41.2,
23868
+ 47.1,
23869
+ 52.9,
23870
+ 58.8,
23871
+ 64.7,
23872
+ 71,
23873
+ 77.5,
23874
+ 84.5,
23875
+ 91.9
23876
+ ];
23877
+ var globalGradientOpacity = 1 / 0.7;
23878
+ var containerStyle2 = {
23879
+ boxSizing: "border-box",
23880
+ position: "absolute",
23881
+ bottom: 0,
23882
+ width: "100%",
23883
+ paddingTop: 40,
23884
+ paddingBottom: 10,
23885
+ backgroundImage: `linear-gradient(to bottom,${gradientSteps.map((g, i) => {
23886
+ return `hsla(0, 0%, 0%, ${g}) ${gradientOpacities[i] * globalGradientOpacity}%`;
23887
+ }).join(", ")}, hsl(0, 0%, 0%) 100%)`,
23888
+ backgroundSize: "auto 145px",
23889
+ display: "flex",
23890
+ paddingRight: X_PADDING,
23891
+ paddingLeft: X_PADDING,
23892
+ flexDirection: "column",
23893
+ transition: "opacity 0.3s"
23894
+ };
23895
+ var controlsRow = {
23896
+ display: "flex",
23897
+ flexDirection: "row",
23898
+ width: "100%",
23899
+ alignItems: "center",
23900
+ justifyContent: "center",
23901
+ userSelect: "none",
23902
+ WebkitUserSelect: "none"
23903
+ };
23904
+ var leftPartStyle = {
23905
+ display: "flex",
23906
+ flexDirection: "row",
23907
+ userSelect: "none",
23908
+ WebkitUserSelect: "none",
23909
+ alignItems: "center"
23910
+ };
23911
+ var xSpacer = {
23912
+ width: 12
23913
+ };
23914
+ var ySpacer = {
23915
+ height: 8
23916
+ };
23917
+ var flex1 = {
23918
+ flex: 1
23919
+ };
23920
+ var fullscreen = {};
23921
+ var Controls = ({
23922
+ durationInFrames,
23923
+ isFullscreen,
23924
+ fps,
23925
+ showVolumeControls,
23926
+ onFullscreenButtonClick,
23927
+ allowFullscreen,
23928
+ onExitFullscreenButtonClick,
23929
+ spaceKeyToPlayOrPause,
23930
+ onSeekEnd,
23931
+ onSeekStart,
23932
+ inFrame,
23933
+ outFrame,
23934
+ initiallyShowControls,
23935
+ canvasSize,
23936
+ renderPlayPauseButton,
23937
+ renderFullscreenButton,
23938
+ alwaysShowControls,
23939
+ showPlaybackRateControl,
23940
+ containerRef,
23941
+ buffering,
23942
+ hideControlsWhenPointerDoesntMove,
23943
+ onPointerDown,
23944
+ onDoubleClick,
23945
+ renderMuteButton,
23946
+ renderVolumeSlider,
23947
+ playing,
23948
+ toggle,
23949
+ renderCustomControls
23950
+ }) => {
23951
+ const playButtonRef = useRef52(null);
23952
+ const [supportsFullscreen, setSupportsFullscreen] = useState92(false);
23953
+ const hovered = useHoverState(containerRef, hideControlsWhenPointerDoesntMove);
23954
+ const { maxTimeLabelWidth, displayVerticalVolumeSlider } = useVideoControlsResize({
23955
+ allowFullscreen,
23956
+ playerWidth: canvasSize?.width ?? 0
23957
+ });
23958
+ const [shouldShowInitially, setInitiallyShowControls] = useState92(() => {
23959
+ if (typeof initiallyShowControls === "boolean") {
23960
+ return initiallyShowControls;
23961
+ }
23962
+ if (typeof initiallyShowControls === "number") {
23963
+ if (initiallyShowControls % 1 !== 0) {
23964
+ throw new Error("initiallyShowControls must be an integer or a boolean");
23965
+ }
23966
+ if (Number.isNaN(initiallyShowControls)) {
23967
+ throw new Error("initiallyShowControls must not be NaN");
23968
+ }
23969
+ if (!Number.isFinite(initiallyShowControls)) {
23970
+ throw new Error("initiallyShowControls must be finite");
23971
+ }
23972
+ if (initiallyShowControls <= 0) {
23973
+ throw new Error("initiallyShowControls must be a positive integer");
23974
+ }
23975
+ return initiallyShowControls;
23976
+ }
23977
+ throw new TypeError("initiallyShowControls must be a number or a boolean");
23978
+ });
23979
+ const containerCss = useMemo92(() => {
23980
+ const shouldShow = hovered || !playing || shouldShowInitially || alwaysShowControls;
23981
+ return {
23982
+ ...containerStyle2,
23983
+ opacity: Number(shouldShow)
23984
+ };
23985
+ }, [hovered, shouldShowInitially, playing, alwaysShowControls]);
23986
+ useEffect72(() => {
23987
+ if (playButtonRef.current && spaceKeyToPlayOrPause) {
23988
+ playButtonRef.current.focus({
23989
+ preventScroll: true
23990
+ });
23991
+ }
23992
+ }, [playing, spaceKeyToPlayOrPause]);
23993
+ useEffect72(() => {
23994
+ setSupportsFullscreen((typeof document !== "undefined" && (document.fullscreenEnabled || document.webkitFullscreenEnabled)) ?? false);
23995
+ }, []);
23996
+ useEffect72(() => {
23997
+ if (shouldShowInitially === false) {
23998
+ return;
23999
+ }
24000
+ const time = shouldShowInitially === true ? 2000 : shouldShowInitially;
24001
+ const timeout = setTimeout(() => {
24002
+ setInitiallyShowControls(false);
24003
+ }, time);
24004
+ return () => {
24005
+ clearInterval(timeout);
24006
+ };
24007
+ }, [shouldShowInitially]);
24008
+ const playbackRates = useMemo92(() => {
24009
+ if (showPlaybackRateControl === true) {
24010
+ return [0.5, 0.8, 1, 1.2, 1.5, 1.8, 2, 2.5, 3];
24011
+ }
24012
+ if (Array.isArray(showPlaybackRateControl)) {
24013
+ for (const rate of showPlaybackRateControl) {
24014
+ if (typeof rate !== "number") {
24015
+ throw new Error("Every item in showPlaybackRateControl must be a number");
24016
+ }
24017
+ if (rate <= 0) {
24018
+ throw new Error("Every item in showPlaybackRateControl must be positive");
24019
+ }
24020
+ }
24021
+ return showPlaybackRateControl;
24022
+ }
24023
+ return null;
24024
+ }, [showPlaybackRateControl]);
24025
+ const customControlsElement = renderCustomControls ? renderCustomControls() : null;
24026
+ const ref = useRef52(null);
24027
+ const flexRef = useRef52(null);
24028
+ const onPointerDownIfContainer = useCallback72((e) => {
24029
+ if (e.target === ref.current || e.target === flexRef.current) {
24030
+ onPointerDown?.(e);
24031
+ }
24032
+ }, [onPointerDown]);
24033
+ const onDoubleClickIfContainer = useCallback72((e) => {
24034
+ if (e.target === ref.current || e.target === flexRef.current) {
24035
+ onDoubleClick?.(e);
24036
+ }
24037
+ }, [onDoubleClick]);
24038
+ return /* @__PURE__ */ jsxs8("div", {
24039
+ ref,
24040
+ style: containerCss,
24041
+ onPointerDown: onPointerDownIfContainer,
24042
+ onDoubleClick: onDoubleClickIfContainer,
24043
+ children: [
24044
+ /* @__PURE__ */ jsxs8("div", {
24045
+ ref: flexRef,
24046
+ style: controlsRow,
24047
+ children: [
24048
+ /* @__PURE__ */ jsxs8("div", {
24049
+ style: leftPartStyle,
24050
+ children: [
24051
+ /* @__PURE__ */ jsx92("button", {
24052
+ ref: playButtonRef,
24053
+ type: "button",
24054
+ style: playerButtonStyle,
24055
+ onClick: toggle,
24056
+ "aria-label": playing ? "Pause video" : "Play video",
24057
+ title: playing ? "Pause video" : "Play video",
24058
+ children: renderPlayPauseButton === null ? /* @__PURE__ */ jsx92(DefaultPlayPauseButton, {
24059
+ buffering,
24060
+ playing
24061
+ }) : renderPlayPauseButton({
24062
+ playing,
24063
+ isBuffering: buffering
24064
+ }) ?? /* @__PURE__ */ jsx92(DefaultPlayPauseButton, {
24065
+ buffering,
24066
+ playing
24067
+ })
24068
+ }),
24069
+ showVolumeControls ? /* @__PURE__ */ jsxs8(Fragment22, {
24070
+ children: [
24071
+ /* @__PURE__ */ jsx92("div", {
24072
+ style: xSpacer
24073
+ }),
24074
+ /* @__PURE__ */ jsx92(MediaVolumeSlider, {
24075
+ renderMuteButton,
24076
+ renderVolumeSlider,
24077
+ displayVerticalVolumeSlider
24078
+ })
24079
+ ]
24080
+ }) : null,
24081
+ /* @__PURE__ */ jsx92("div", {
24082
+ style: xSpacer
24083
+ }),
24084
+ /* @__PURE__ */ jsx92(PlayerTimeLabel, {
24085
+ durationInFrames,
24086
+ fps,
24087
+ maxTimeLabelWidth
24088
+ }),
24089
+ /* @__PURE__ */ jsx92("div", {
24090
+ style: xSpacer
24091
+ })
24092
+ ]
24093
+ }),
24094
+ /* @__PURE__ */ jsx92("div", {
24095
+ style: flex1
24096
+ }),
24097
+ customControlsElement,
24098
+ customControlsElement && playbackRates && canvasSize ? /* @__PURE__ */ jsx92("div", {
24099
+ style: xSpacer
24100
+ }) : null,
24101
+ playbackRates && canvasSize && /* @__PURE__ */ jsx92(PlaybackrateControl, {
24102
+ canvasSize,
24103
+ playbackRates
24104
+ }),
24105
+ playbackRates && supportsFullscreen && allowFullscreen ? /* @__PURE__ */ jsx92("div", {
24106
+ style: xSpacer
24107
+ }) : null,
24108
+ /* @__PURE__ */ jsx92("div", {
24109
+ style: fullscreen,
24110
+ children: supportsFullscreen && allowFullscreen ? /* @__PURE__ */ jsx92("button", {
24111
+ type: "button",
24112
+ "aria-label": isFullscreen ? "Exit fullscreen" : "Enter Fullscreen",
24113
+ title: isFullscreen ? "Exit fullscreen" : "Enter Fullscreen",
24114
+ style: playerButtonStyle,
24115
+ onClick: isFullscreen ? onExitFullscreenButtonClick : onFullscreenButtonClick,
24116
+ children: renderFullscreenButton === null ? /* @__PURE__ */ jsx92(FullscreenIcon, {
24117
+ isFullscreen
24118
+ }) : renderFullscreenButton({ isFullscreen })
24119
+ }) : null
24120
+ })
24121
+ ]
24122
+ }),
24123
+ /* @__PURE__ */ jsx92("div", {
24124
+ style: ySpacer
24125
+ }),
24126
+ /* @__PURE__ */ jsx92(PlayerSeekBar, {
24127
+ onSeekEnd,
24128
+ onSeekStart,
24129
+ durationInFrames,
24130
+ inFrame,
24131
+ outFrame
24132
+ })
24133
+ ]
24134
+ });
24135
+ };
24136
+ var TimelineSequenceObserverContext = React82.createContext(null);
24137
+ var useBrowserMediaSession = ({
24138
+ browserMediaControlsBehavior,
24139
+ videoConfig,
24140
+ playbackRate
24141
+ }) => {
24142
+ const playing = Internals.usePlaying();
24143
+ const { pause, play, emitter, getCurrentFrame, seek } = usePlayerMethods();
24144
+ const hasEverPlayed = useRef62(false);
24145
+ useEffect82(() => {
24146
+ if (playing) {
24147
+ hasEverPlayed.current = true;
24148
+ }
24149
+ if (!navigator.mediaSession) {
24150
+ return;
24151
+ }
24152
+ if (browserMediaControlsBehavior.mode === "do-nothing") {
24153
+ return;
24154
+ }
24155
+ if (playing) {
24156
+ navigator.mediaSession.playbackState = "playing";
24157
+ } else if (hasEverPlayed.current) {
24158
+ navigator.mediaSession.playbackState = "paused";
24159
+ }
24160
+ }, [browserMediaControlsBehavior.mode, playing]);
24161
+ useEffect82(() => {
24162
+ if (!navigator.mediaSession) {
24163
+ return;
24164
+ }
24165
+ if (browserMediaControlsBehavior.mode === "do-nothing") {
24166
+ return;
24167
+ }
24168
+ const onTimeUpdate = () => {
24169
+ if (!videoConfig) {
24170
+ return;
24171
+ }
24172
+ if (navigator.mediaSession) {
24173
+ navigator.mediaSession.setPositionState({
24174
+ duration: videoConfig.durationInFrames / videoConfig.fps,
24175
+ playbackRate,
24176
+ position: getCurrentFrame() / videoConfig.fps
24177
+ });
24178
+ }
24179
+ };
24180
+ emitter.addEventListener("timeupdate", onTimeUpdate);
24181
+ return () => {
24182
+ emitter.removeEventListener("timeupdate", onTimeUpdate);
24183
+ };
24184
+ }, [
24185
+ browserMediaControlsBehavior.mode,
24186
+ emitter,
24187
+ getCurrentFrame,
24188
+ playbackRate,
24189
+ videoConfig
24190
+ ]);
24191
+ useEffect82(() => {
24192
+ if (!navigator.mediaSession) {
24193
+ return;
24194
+ }
24195
+ if (browserMediaControlsBehavior.mode === "do-nothing") {
24196
+ return;
24197
+ }
24198
+ navigator.mediaSession.setActionHandler("play", () => {
24199
+ if (browserMediaControlsBehavior.mode === "register-media-session") {
24200
+ play();
24201
+ }
24202
+ });
24203
+ navigator.mediaSession.setActionHandler("pause", () => {
24204
+ if (browserMediaControlsBehavior.mode === "register-media-session") {
24205
+ pause();
24206
+ }
24207
+ });
24208
+ navigator.mediaSession.setActionHandler("seekto", (event) => {
24209
+ if (browserMediaControlsBehavior.mode === "register-media-session" && event.seekTime !== undefined && videoConfig) {
24210
+ seek(Math.round(event.seekTime * videoConfig.fps));
24211
+ }
24212
+ });
24213
+ navigator.mediaSession.setActionHandler("seekbackward", () => {
24214
+ if (browserMediaControlsBehavior.mode === "register-media-session" && videoConfig) {
24215
+ seek(Math.max(0, Math.round(getCurrentFrame() - 10 * videoConfig.fps)));
24216
+ }
24217
+ });
24218
+ navigator.mediaSession.setActionHandler("seekforward", () => {
24219
+ if (browserMediaControlsBehavior.mode === "register-media-session" && videoConfig) {
24220
+ seek(Math.min(videoConfig.durationInFrames - 1, Math.round(getCurrentFrame() + 10 * videoConfig.fps)));
24221
+ }
24222
+ });
24223
+ navigator.mediaSession.setActionHandler("previoustrack", () => {
24224
+ if (browserMediaControlsBehavior.mode === "register-media-session") {
24225
+ seek(0);
24226
+ }
24227
+ });
24228
+ return () => {
24229
+ navigator.mediaSession.metadata = null;
24230
+ navigator.mediaSession.setActionHandler("play", null);
24231
+ navigator.mediaSession.setActionHandler("pause", null);
24232
+ navigator.mediaSession.setActionHandler("seekto", null);
24233
+ navigator.mediaSession.setActionHandler("seekbackward", null);
24234
+ navigator.mediaSession.setActionHandler("seekforward", null);
24235
+ navigator.mediaSession.setActionHandler("previoustrack", null);
24236
+ };
24237
+ }, [
24238
+ browserMediaControlsBehavior.mode,
24239
+ getCurrentFrame,
24240
+ pause,
24241
+ play,
24242
+ seek,
24243
+ videoConfig
24244
+ ]);
24245
+ };
24246
+ var calculateNextFrame = ({
24247
+ time,
24248
+ currentFrame: startFrame,
24249
+ playbackSpeed,
24250
+ fps,
24251
+ actualLastFrame,
24252
+ actualFirstFrame,
24253
+ framesAdvanced,
24254
+ shouldLoop
24255
+ }) => {
24256
+ const op = playbackSpeed < 0 ? Math.ceil : Math.floor;
24257
+ const framesToAdvance = op(time * playbackSpeed / (1000 / fps)) - framesAdvanced;
24258
+ const nextFrame = framesToAdvance + startFrame;
24259
+ const isCurrentFrameOutside = startFrame > actualLastFrame || startFrame < actualFirstFrame;
24260
+ const isNextFrameOutside = nextFrame > actualLastFrame || nextFrame < actualFirstFrame;
24261
+ const hasEnded = !shouldLoop && isNextFrameOutside && !isCurrentFrameOutside;
24262
+ if (playbackSpeed > 0) {
24263
+ if (isNextFrameOutside) {
24264
+ return {
24265
+ nextFrame: actualFirstFrame,
24266
+ framesToAdvance,
24267
+ hasEnded
24268
+ };
24269
+ }
24270
+ return { nextFrame, framesToAdvance, hasEnded };
24271
+ }
24272
+ if (isNextFrameOutside) {
24273
+ return { nextFrame: actualLastFrame, framesToAdvance, hasEnded };
24274
+ }
24275
+ return { nextFrame, framesToAdvance, hasEnded };
24276
+ };
24277
+ var getIsBackgrounded = () => {
24278
+ if (typeof document === "undefined") {
24279
+ return false;
24280
+ }
24281
+ return document.visibilityState === "hidden";
24282
+ };
24283
+ var useIsBackgrounded = () => {
24284
+ const isBackgrounded = useRef72(getIsBackgrounded());
24285
+ useEffect92(() => {
24286
+ const onVisibilityChange = () => {
24287
+ isBackgrounded.current = getIsBackgrounded();
24288
+ };
24289
+ document.addEventListener("visibilitychange", onVisibilityChange);
24290
+ return () => {
24291
+ document.removeEventListener("visibilitychange", onVisibilityChange);
24292
+ };
24293
+ }, []);
24294
+ return isBackgrounded;
24295
+ };
24296
+ var setGlobalTimeAnchor = ({
24297
+ audioContext,
24298
+ audioSyncAnchor,
24299
+ absoluteTimeInSeconds,
24300
+ globalPlaybackRate,
24301
+ logLevel,
24302
+ force
24303
+ }) => {
24304
+ const newAnchor = audioContext.currentTime - absoluteTimeInSeconds / globalPlaybackRate;
24305
+ const shift = newAnchor - audioSyncAnchor.value;
24306
+ const tolerance = Internals.getAudioSyncAnchorTolerance(audioContext);
24307
+ if (Math.abs(shift) < tolerance && !force) {
24308
+ return false;
24309
+ }
24310
+ if (Math.abs(shift) < Number.EPSILON) {
24311
+ return false;
24312
+ }
24313
+ Internals.Log.verbose({ logLevel, tag: "audio-scheduling" }, "Anchor " + (force ? "forcibly " : "") + "changed from %s to %s with shift %s", audioSyncAnchor.value, newAnchor, shift);
24314
+ audioSyncAnchor.value = newAnchor;
24315
+ return true;
24316
+ };
24317
+ var shouldForceAnchorChange = (newState) => {
24318
+ if (newState === "suspended" || newState === "running-to-suspended") {
24319
+ return true;
24320
+ }
24321
+ if (newState === "closed" || newState === "interrupted" || newState === "running" || newState === "suspended-to-running") {
24322
+ return false;
24323
+ }
24324
+ throw new Error(`Unexpected audio context state: ${newState}`);
24325
+ };
24326
+ var usePlayback = ({
24327
+ loop,
24328
+ playbackRate,
24329
+ moveToBeginningWhenEnded,
24330
+ inFrame,
24331
+ outFrame,
24332
+ browserMediaControlsBehavior,
24333
+ getCurrentFrame,
24334
+ muted
24335
+ }) => {
24336
+ const config = Internals.useUnsafeVideoConfig();
24337
+ const fps = config?.fps ?? null;
24338
+ const durationInFrames = config?.durationInFrames ?? null;
24339
+ const compositionId = config?.id ?? null;
24340
+ const frame = Internals.Timeline.useTimelinePosition();
24341
+ const playing = Internals.usePlaying();
24342
+ const { pause, emitter, isPlaying } = usePlayerMethods();
24343
+ const setFrameFromPlayback = Internals.Timeline.useTimelineSetFrameWithoutSeek();
24344
+ const sharedAudioContext = useContext310(Internals.SharedAudioContext);
24345
+ const { setPlayerMuted } = useContext310(Internals.SetMediaVolumeContext);
24346
+ const { isBuffering, subscribeBuffering, seek } = useContext310(Internals.SetTimelineContext);
24347
+ const logLevel = Internals.useLogLevel();
24348
+ const isBackgroundedRef = useIsBackgrounded();
24349
+ const lastTimeUpdateTimestamp = useRef82(0);
24350
+ const playbackClockRef = useRef82(null);
24351
+ const previousMutedRef = useRef82(muted);
24352
+ const anchoredAudioContextRef = useRef82(null);
24353
+ useBrowserMediaSession({
24354
+ browserMediaControlsBehavior,
24355
+ playbackRate,
24356
+ videoConfig: config
24357
+ });
24358
+ useLayoutEffect26(() => {
24359
+ if (!sharedAudioContext) {
24360
+ return;
24361
+ }
24362
+ if (!sharedAudioContext.audioContext) {
24363
+ return;
24364
+ }
24365
+ if (fps === null) {
24366
+ return;
24367
+ }
24368
+ if (muted) {
24369
+ return;
24370
+ }
24371
+ const changed = setGlobalTimeAnchor({
24372
+ audioContext: sharedAudioContext.audioContext,
24373
+ audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
24374
+ absoluteTimeInSeconds: frame / fps,
24375
+ globalPlaybackRate: playbackRate,
24376
+ logLevel,
24377
+ force: false
24378
+ });
24379
+ if (changed) {
24380
+ sharedAudioContext.audioSyncAnchorEmitter.dispatch("changed");
24381
+ }
24382
+ }, [fps, frame, logLevel, playbackRate, sharedAudioContext, muted]);
24383
+ useLayoutEffect26(() => {
24384
+ const audioContext = sharedAudioContext?.audioContext;
24385
+ if (!audioContext) {
24386
+ return;
24387
+ }
24388
+ if (fps === null) {
24389
+ return;
24390
+ }
24391
+ if (muted) {
24392
+ return;
24393
+ }
24394
+ const callback = () => {
24395
+ const newState = sharedAudioContext?.getAudioContextState();
24396
+ if (newState && shouldForceAnchorChange(newState)) {
24397
+ const changed = setGlobalTimeAnchor({
24398
+ audioContext,
24399
+ audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
24400
+ absoluteTimeInSeconds: getCurrentFrame() / fps,
24401
+ globalPlaybackRate: playbackRate,
24402
+ logLevel,
24403
+ force: true
24404
+ });
24405
+ if (changed) {
24406
+ sharedAudioContext.audioSyncAnchorEmitter.dispatch("changed");
24407
+ }
24408
+ }
24409
+ };
24410
+ audioContext?.addEventListener("statechange", callback);
24411
+ return () => {
24412
+ audioContext?.removeEventListener("statechange", callback);
24413
+ };
24414
+ }, [fps, getCurrentFrame, logLevel, muted, playbackRate, sharedAudioContext]);
24415
+ useEffect102(() => {
24416
+ const wasMuted = previousMutedRef.current;
24417
+ previousMutedRef.current = muted;
24418
+ if (fps === null || durationInFrames === null || compositionId === null) {
24419
+ playbackClockRef.current = null;
24420
+ return;
24421
+ }
24422
+ if (!playing) {
24423
+ playbackClockRef.current = null;
24424
+ sharedAudioContext?.suspend?.();
24425
+ return;
24426
+ }
24427
+ if (muted) {
24428
+ sharedAudioContext?.suspend?.();
24429
+ }
24430
+ const previousClock = playbackClockRef.current;
24431
+ const shouldRestartClock = previousClock === null || previousClock.compositionId !== compositionId || previousClock.fps !== fps || previousClock.playbackRate !== playbackRate;
24432
+ const clock = shouldRestartClock ? {
24433
+ compositionId,
24434
+ startedTime: performance.now(),
24435
+ framesAdvanced: 0,
24436
+ fps,
24437
+ playbackRate
24438
+ } : previousClock;
24439
+ playbackClockRef.current = clock;
24440
+ if (sharedAudioContext?._experimentalKeepAudioContextAlive && sharedAudioContext.audioContext && !muted) {
24441
+ const didUnmute = wasMuted && !muted;
24442
+ const didReplaceAudioContext = anchoredAudioContextRef.current !== sharedAudioContext.audioContext;
24443
+ const shouldRescheduleAudio = shouldRestartClock || didUnmute || didReplaceAudioContext;
24444
+ const changed = setGlobalTimeAnchor({
24445
+ audioContext: sharedAudioContext.audioContext,
24446
+ audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
24447
+ absoluteTimeInSeconds: getCurrentFrame() / fps,
24448
+ globalPlaybackRate: playbackRate,
24449
+ logLevel,
24450
+ force: shouldRescheduleAudio
24451
+ });
24452
+ anchoredAudioContextRef.current = sharedAudioContext.audioContext;
24453
+ if (changed || shouldRescheduleAudio) {
24454
+ sharedAudioContext.audioSyncAnchorEmitter.dispatch("changed");
24455
+ }
24456
+ }
24457
+ let hasBeenStopped = false;
24458
+ let audioContextFailed = false;
24459
+ let reqAnimFrameCall = null;
24460
+ let playbackFrame = getCurrentFrame();
24461
+ let lastSeekRevision = seek?.revision.current ?? null;
24462
+ const cancelQueuedFrame = () => {
24463
+ if (reqAnimFrameCall !== null) {
24464
+ if (reqAnimFrameCall.type === "raf") {
24465
+ cancelAnimationFrame(reqAnimFrameCall.id);
24466
+ } else {
24467
+ clearTimeout(reqAnimFrameCall.id);
24468
+ }
24469
+ }
24470
+ };
24471
+ const stop = () => {
24472
+ hasBeenStopped = true;
24473
+ cancelQueuedFrame();
24474
+ };
24475
+ const callback = () => {
24476
+ if (hasBeenStopped) {
24477
+ return;
24478
+ }
24479
+ if (!isPlaying()) {
24480
+ sharedAudioContext?.suspend?.();
24481
+ return;
24482
+ }
24483
+ if (!muted && !audioContextFailed && !isBuffering()) {
24484
+ sharedAudioContext?.resume?.();
24485
+ }
24486
+ const time = performance.now() - clock.startedTime;
24487
+ const actualLastFrame = outFrame ?? durationInFrames - 1;
24488
+ const actualFirstFrame = inFrame ?? 0;
24489
+ const seekRevision = seek?.revision.current ?? null;
24490
+ if (seekRevision !== lastSeekRevision) {
24491
+ playbackFrame = getCurrentFrame();
24492
+ lastSeekRevision = seekRevision;
24493
+ }
24494
+ const currentFrame = playbackFrame;
24495
+ const { nextFrame, framesToAdvance, hasEnded } = calculateNextFrame({
24496
+ time,
24497
+ currentFrame,
24498
+ playbackSpeed: playbackRate,
24499
+ fps,
24500
+ actualFirstFrame,
24501
+ actualLastFrame,
24502
+ framesAdvanced: clock.framesAdvanced,
24503
+ shouldLoop: loop
24504
+ });
24505
+ clock.framesAdvanced += framesToAdvance;
24506
+ const frameToDisplay = hasEnded && !moveToBeginningWhenEnded ? playbackRate > 0 ? actualLastFrame : actualFirstFrame : nextFrame;
24507
+ if (frameToDisplay !== currentFrame && !isBuffering()) {
24508
+ playbackFrame = frameToDisplay;
24509
+ setFrameFromPlayback((c) => ({ ...c, [compositionId]: frameToDisplay }));
24510
+ }
24511
+ if (hasEnded) {
24512
+ stop();
24513
+ pause();
24514
+ emitter.dispatchEnded();
24515
+ return;
24516
+ }
24517
+ queueNextFrame();
24518
+ };
24519
+ const queueNextFrame = () => {
24520
+ if (hasBeenStopped) {
24521
+ return;
24522
+ }
24523
+ const getIsResumingAudioContext = audioContextFailed ? null : sharedAudioContext?.getIsResumingAudioContext?.() ?? null;
24524
+ if (getIsResumingAudioContext !== null && !muted) {
24525
+ getIsResumingAudioContext.then((result) => {
24526
+ if (hasBeenStopped) {
24527
+ return;
24528
+ }
24529
+ if (result === "failed") {
24530
+ audioContextFailed = true;
24531
+ sharedAudioContext?.suspend();
24532
+ setPlayerMuted(true);
24533
+ }
24534
+ clock.startedTime = performance.now();
24535
+ clock.framesAdvanced = 0;
24536
+ queueNextFrame();
24537
+ });
24538
+ return;
24539
+ }
24540
+ if (isBuffering()) {
24541
+ if (!muted && !audioContextFailed) {
24542
+ sharedAudioContext?.suspend?.();
24543
+ }
24544
+ const unsubscribe = subscribeBuffering((state) => {
24545
+ if (state.buffering) {
24546
+ return;
24547
+ }
24548
+ unsubscribe();
24549
+ if (!muted && !audioContextFailed && sharedAudioContext?._experimentalKeepAudioContextAlive) {
24550
+ sharedAudioContext.resume();
24551
+ }
24552
+ clock.startedTime = performance.now();
24553
+ clock.framesAdvanced = 0;
24554
+ queueNextFrame();
24555
+ });
24556
+ return;
24557
+ }
24558
+ if (isBackgroundedRef.current) {
24559
+ reqAnimFrameCall = {
24560
+ type: "timeout",
24561
+ id: setTimeout(callback, 1000 / fps)
24562
+ };
24563
+ return;
24564
+ }
24565
+ reqAnimFrameCall = { type: "raf", id: requestAnimationFrame(callback) };
24566
+ };
24567
+ queueNextFrame();
24568
+ const onVisibilityChange = () => {
24569
+ if (document.visibilityState === "visible") {
24570
+ return;
24571
+ }
24572
+ cancelQueuedFrame();
24573
+ callback();
24410
24574
  };
24411
- }, [allowFullScreen, playerWidth]);
24412
- return resizeInfo;
24575
+ window.addEventListener("visibilitychange", onVisibilityChange);
24576
+ return () => {
24577
+ window.removeEventListener("visibilitychange", onVisibilityChange);
24578
+ stop();
24579
+ };
24580
+ }, [
24581
+ compositionId,
24582
+ durationInFrames,
24583
+ fps,
24584
+ loop,
24585
+ pause,
24586
+ playing,
24587
+ setFrameFromPlayback,
24588
+ emitter,
24589
+ playbackRate,
24590
+ inFrame,
24591
+ outFrame,
24592
+ moveToBeginningWhenEnded,
24593
+ isBackgroundedRef,
24594
+ getCurrentFrame,
24595
+ isBuffering,
24596
+ isPlaying,
24597
+ sharedAudioContext,
24598
+ setPlayerMuted,
24599
+ subscribeBuffering,
24600
+ seek,
24601
+ logLevel,
24602
+ muted
24603
+ ]);
24604
+ useEffect102(() => {
24605
+ const now = performance.now();
24606
+ const timeSinceLastUpdate = now - lastTimeUpdateTimestamp.current;
24607
+ if (timeSinceLastUpdate >= 250) {
24608
+ emitter.dispatchTimeUpdate({ frame });
24609
+ lastTimeUpdateTimestamp.current = now;
24610
+ return;
24611
+ }
24612
+ const timeoutId = setTimeout(() => {
24613
+ emitter.dispatchTimeUpdate({ frame });
24614
+ lastTimeUpdateTimestamp.current = performance.now();
24615
+ }, 250 - timeSinceLastUpdate);
24616
+ return () => clearTimeout(timeoutId);
24617
+ }, [emitter, frame]);
24618
+ useEffect102(() => {
24619
+ emitter.dispatchFrameUpdate({ frame });
24620
+ }, [emitter, frame]);
24413
24621
  };
24414
- var gradientSteps = [
24415
- 0,
24416
- 0.013,
24417
- 0.049,
24418
- 0.104,
24419
- 0.175,
24420
- 0.259,
24421
- 0.352,
24422
- 0.45,
24423
- 0.55,
24424
- 0.648,
24425
- 0.741,
24426
- 0.825,
24427
- 0.896,
24428
- 0.951,
24429
- 0.987
24430
- ];
24431
- var gradientOpacities = [
24432
- 0,
24433
- 8.1,
24434
- 15.5,
24435
- 22.5,
24436
- 29,
24437
- 35.3,
24438
- 41.2,
24439
- 47.1,
24440
- 52.9,
24441
- 58.8,
24442
- 64.7,
24443
- 71,
24444
- 77.5,
24445
- 84.5,
24446
- 91.9
24447
- ];
24448
- var globalGradientOpacity = 1 / 0.7;
24449
- var containerStyle2 = {
24450
- boxSizing: "border-box",
24451
- position: "absolute",
24452
- bottom: 0,
24453
- width: "100%",
24454
- paddingTop: 40,
24455
- paddingBottom: 10,
24456
- backgroundImage: `linear-gradient(to bottom,${gradientSteps.map((g, i) => {
24457
- return `hsla(0, 0%, 0%, ${g}) ${gradientOpacities[i] * globalGradientOpacity}%`;
24458
- }).join(", ")}, hsl(0, 0%, 0%) 100%)`,
24459
- backgroundSize: "auto 145px",
24460
- display: "flex",
24461
- paddingRight: X_PADDING,
24462
- paddingLeft: X_PADDING,
24463
- flexDirection: "column",
24464
- transition: "opacity 0.3s"
24622
+ var playerCssClassname = (override) => {
24623
+ return override ?? "__remotion-player";
24465
24624
  };
24466
- var controlsRow = {
24625
+ var errorStyle = {
24467
24626
  display: "flex",
24468
- flexDirection: "row",
24469
- width: "100%",
24470
- alignItems: "center",
24471
24627
  justifyContent: "center",
24472
- userSelect: "none",
24473
- WebkitUserSelect: "none"
24474
- };
24475
- var leftPartStyle = {
24476
- display: "flex",
24477
- flexDirection: "row",
24478
- userSelect: "none",
24479
- WebkitUserSelect: "none",
24480
- alignItems: "center"
24481
- };
24482
- var xSpacer = {
24483
- width: 12
24628
+ alignItems: "center",
24629
+ flex: 1,
24630
+ height: "100%",
24631
+ width: "100%"
24484
24632
  };
24485
- var ySpacer = {
24486
- height: 8
24633
+
24634
+ class ErrorBoundary extends React92.Component {
24635
+ state = { hasError: null };
24636
+ static getDerivedStateFromError(error) {
24637
+ return { hasError: error };
24638
+ }
24639
+ componentDidCatch(error) {
24640
+ this.props.onError(error);
24641
+ }
24642
+ render() {
24643
+ if (this.state.hasError) {
24644
+ return /* @__PURE__ */ jsx102("div", {
24645
+ style: errorStyle,
24646
+ children: this.props.errorFallback({
24647
+ error: this.state.hasError
24648
+ })
24649
+ });
24650
+ }
24651
+ return this.props.children;
24652
+ }
24653
+ }
24654
+ var getHashOfDomain = async () => {
24655
+ if (typeof window === "undefined") {
24656
+ return null;
24657
+ }
24658
+ if (typeof window.crypto === "undefined") {
24659
+ return null;
24660
+ }
24661
+ if (typeof window.crypto.subtle === "undefined") {
24662
+ return null;
24663
+ }
24664
+ try {
24665
+ const hashBuffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(window.location.hostname));
24666
+ return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
24667
+ } catch {
24668
+ return null;
24669
+ }
24487
24670
  };
24488
- var flex1 = {
24489
- flex: 1
24671
+ var style = {
24672
+ backgroundColor: "red",
24673
+ position: "absolute",
24674
+ padding: 12,
24675
+ fontFamily: "Arial"
24490
24676
  };
24491
- var fullscreen = {};
24492
- var Controls = ({
24493
- durationInFrames,
24494
- isFullscreen,
24495
- fps,
24496
- showVolumeControls,
24497
- onFullscreenButtonClick,
24498
- allowFullscreen,
24499
- onExitFullscreenButtonClick,
24500
- spaceKeyToPlayOrPause,
24501
- onSeekEnd,
24502
- onSeekStart,
24503
- inFrame,
24504
- outFrame,
24505
- initiallyShowControls,
24506
- canvasSize,
24507
- renderPlayPauseButton,
24508
- renderFullscreenButton,
24509
- alwaysShowControls,
24510
- showPlaybackRateControl,
24511
- containerRef,
24512
- buffering,
24513
- hideControlsWhenPointerDoesntMove,
24514
- onPointerDown,
24515
- onDoubleClick,
24516
- renderMuteButton,
24517
- renderVolumeSlider,
24518
- playing,
24519
- toggle,
24520
- renderCustomControls
24521
- }) => {
24522
- const playButtonRef = useRef82(null);
24523
- const [supportsFullscreen, setSupportsFullscreen] = useState92(false);
24524
- const hovered = useHoverState(containerRef, hideControlsWhenPointerDoesntMove);
24525
- const { maxTimeLabelWidth, displayVerticalVolumeSlider } = useVideoControlsResize({
24526
- allowFullscreen,
24527
- playerWidth: canvasSize?.width ?? 0
24528
- });
24529
- const [shouldShowInitially, setInitiallyShowControls] = useState92(() => {
24530
- if (typeof initiallyShowControls === "boolean") {
24531
- return initiallyShowControls;
24532
- }
24533
- if (typeof initiallyShowControls === "number") {
24534
- if (initiallyShowControls % 1 !== 0) {
24535
- throw new Error("initiallyShowControls must be an integer or a boolean");
24536
- }
24537
- if (Number.isNaN(initiallyShowControls)) {
24538
- throw new Error("initiallyShowControls must not be NaN");
24539
- }
24540
- if (!Number.isFinite(initiallyShowControls)) {
24541
- throw new Error("initiallyShowControls must be finite");
24542
- }
24543
- if (initiallyShowControls <= 0) {
24544
- throw new Error("initiallyShowControls must be a positive integer");
24545
- }
24546
- return initiallyShowControls;
24547
- }
24548
- throw new TypeError("initiallyShowControls must be a number or a boolean");
24549
- });
24550
- const containerCss = useMemo92(() => {
24551
- const shouldShow = hovered || !playing || shouldShowInitially || alwaysShowControls;
24552
- return {
24553
- ...containerStyle2,
24554
- opacity: Number(shouldShow)
24555
- };
24556
- }, [hovered, shouldShowInitially, playing, alwaysShowControls]);
24677
+ var DOMAIN_BLACKLIST = [
24678
+ "28d262b44cc61fa750f1686b16ad0604dabfe193fbc263eec05c89b7ad4c2cd6",
24679
+ "4db1b0a94be33165dfefcb3ba03d04c7a2666dd27c496d3dc9fa41858e94925e",
24680
+ "fbc48530bbf245da790f63675e84e06bab38c3b114fab07eb350025119922bdc",
24681
+ "7baf10a8932757b1b3a22b3fce10a048747ac2f8eaf638603487e3705b07eb83",
24682
+ "8a6c21a598d8c667272b5207c051b85997bf5b45d5fb712378be3f27cd72c6a6",
24683
+ "a2f7aaac9c50a9255e7fc376110c4e0bfe153722dc66ed3c5d3bf2a135f65518"
24684
+ ];
24685
+ var ran = false;
24686
+ var RenderWarningIfBlacklist = () => {
24687
+ const [unlicensed, setUnlicensed] = React102.useState(false);
24557
24688
  useEffect112(() => {
24558
- if (playButtonRef.current && spaceKeyToPlayOrPause) {
24559
- playButtonRef.current.focus({
24560
- preventScroll: true
24561
- });
24689
+ if (ran) {
24690
+ return;
24562
24691
  }
24563
- }, [playing, spaceKeyToPlayOrPause]);
24564
- useEffect112(() => {
24565
- setSupportsFullscreen((typeof document !== "undefined" && (document.fullscreenEnabled || document.webkitFullscreenEnabled)) ?? false);
24692
+ ran = true;
24693
+ getHashOfDomain().then((hash) => {
24694
+ if (hash && DOMAIN_BLACKLIST.includes(hash)) {
24695
+ setUnlicensed(true);
24696
+ }
24697
+ }).catch(() => {});
24566
24698
  }, []);
24567
24699
  useEffect112(() => {
24568
- if (shouldShowInitially === false) {
24700
+ if (!unlicensed) {
24569
24701
  return;
24570
24702
  }
24571
- const time = shouldShowInitially === true ? 2000 : shouldShowInitially;
24572
- const timeout = setTimeout(() => {
24573
- setInitiallyShowControls(false);
24574
- }, time);
24703
+ const ensureBanner = () => {
24704
+ const banner = document.querySelector(".warning-banner");
24705
+ if (!banner) {
24706
+ const div = document.createElement("div");
24707
+ div.className = "warning-banner";
24708
+ Object.assign(div.style, style, {
24709
+ zIndex: "9999",
24710
+ cssText: `${style.cssText} !important;`
24711
+ });
24712
+ div.innerHTML = `
24713
+ <a href="https://github.com/remotion-dev/remotion/pull/4589" style="color: white;">
24714
+ Remotion Unlicensed – Contact hi@remotion.dev
24715
+ </a>
24716
+ `;
24717
+ document.body.appendChild(div);
24718
+ }
24719
+ };
24720
+ const observer = new MutationObserver(() => ensureBanner());
24721
+ observer.observe(document.body, { childList: true, subtree: true });
24575
24722
  return () => {
24576
- clearInterval(timeout);
24723
+ observer.disconnect();
24577
24724
  };
24578
- }, [shouldShowInitially]);
24579
- const playbackRates = useMemo92(() => {
24580
- if (showPlaybackRateControl === true) {
24581
- return [0.5, 0.8, 1, 1.2, 1.5, 1.8, 2, 2.5, 3];
24582
- }
24583
- if (Array.isArray(showPlaybackRateControl)) {
24584
- for (const rate of showPlaybackRateControl) {
24585
- if (typeof rate !== "number") {
24586
- throw new Error("Every item in showPlaybackRateControl must be a number");
24587
- }
24588
- if (rate <= 0) {
24589
- throw new Error("Every item in showPlaybackRateControl must be positive");
24590
- }
24591
- }
24592
- return showPlaybackRateControl;
24593
- }
24725
+ }, [unlicensed]);
24726
+ if (!unlicensed) {
24594
24727
  return null;
24595
- }, [showPlaybackRateControl]);
24596
- const customControlsElement = renderCustomControls ? renderCustomControls() : null;
24597
- const ref = useRef82(null);
24598
- const flexRef = useRef82(null);
24599
- const onPointerDownIfContainer = useCallback72((e) => {
24600
- if (e.target === ref.current || e.target === flexRef.current) {
24601
- onPointerDown?.(e);
24602
- }
24603
- }, [onPointerDown]);
24604
- const onDoubleClickIfContainer = useCallback72((e) => {
24605
- if (e.target === ref.current || e.target === flexRef.current) {
24606
- onDoubleClick?.(e);
24607
- }
24608
- }, [onDoubleClick]);
24609
- return /* @__PURE__ */ jsxs8("div", {
24610
- ref,
24611
- style: containerCss,
24612
- onPointerDown: onPointerDownIfContainer,
24613
- onDoubleClick: onDoubleClickIfContainer,
24614
- children: [
24615
- /* @__PURE__ */ jsxs8("div", {
24616
- ref: flexRef,
24617
- style: controlsRow,
24618
- children: [
24619
- /* @__PURE__ */ jsxs8("div", {
24620
- style: leftPartStyle,
24621
- children: [
24622
- /* @__PURE__ */ jsx112("button", {
24623
- ref: playButtonRef,
24624
- type: "button",
24625
- style: playerButtonStyle,
24626
- onClick: toggle,
24627
- "aria-label": playing ? "Pause video" : "Play video",
24628
- title: playing ? "Pause video" : "Play video",
24629
- children: renderPlayPauseButton === null ? /* @__PURE__ */ jsx112(DefaultPlayPauseButton, {
24630
- buffering,
24631
- playing
24632
- }) : renderPlayPauseButton({
24633
- playing,
24634
- isBuffering: buffering
24635
- }) ?? /* @__PURE__ */ jsx112(DefaultPlayPauseButton, {
24636
- buffering,
24637
- playing
24638
- })
24639
- }),
24640
- showVolumeControls ? /* @__PURE__ */ jsxs8(Fragment22, {
24641
- children: [
24642
- /* @__PURE__ */ jsx112("div", {
24643
- style: xSpacer
24644
- }),
24645
- /* @__PURE__ */ jsx112(MediaVolumeSlider, {
24646
- renderMuteButton,
24647
- renderVolumeSlider,
24648
- displayVerticalVolumeSlider
24649
- })
24650
- ]
24651
- }) : null,
24652
- /* @__PURE__ */ jsx112("div", {
24653
- style: xSpacer
24654
- }),
24655
- /* @__PURE__ */ jsx112(PlayerTimeLabel, {
24656
- durationInFrames,
24657
- fps,
24658
- maxTimeLabelWidth
24659
- }),
24660
- /* @__PURE__ */ jsx112("div", {
24661
- style: xSpacer
24662
- })
24663
- ]
24664
- }),
24665
- /* @__PURE__ */ jsx112("div", {
24666
- style: flex1
24667
- }),
24668
- customControlsElement,
24669
- customControlsElement && playbackRates && canvasSize ? /* @__PURE__ */ jsx112("div", {
24670
- style: xSpacer
24671
- }) : null,
24672
- playbackRates && canvasSize && /* @__PURE__ */ jsx112(PlaybackrateControl, {
24673
- canvasSize,
24674
- playbackRates
24675
- }),
24676
- playbackRates && supportsFullscreen && allowFullscreen ? /* @__PURE__ */ jsx112("div", {
24677
- style: xSpacer
24678
- }) : null,
24679
- /* @__PURE__ */ jsx112("div", {
24680
- style: fullscreen,
24681
- children: supportsFullscreen && allowFullscreen ? /* @__PURE__ */ jsx112("button", {
24682
- type: "button",
24683
- "aria-label": isFullscreen ? "Exit fullscreen" : "Enter Fullscreen",
24684
- title: isFullscreen ? "Exit fullscreen" : "Enter Fullscreen",
24685
- style: playerButtonStyle,
24686
- onClick: isFullscreen ? onExitFullscreenButtonClick : onFullscreenButtonClick,
24687
- children: renderFullscreenButton === null ? /* @__PURE__ */ jsx112(FullscreenIcon, {
24688
- isFullscreen
24689
- }) : renderFullscreenButton({ isFullscreen })
24690
- }) : null
24691
- })
24692
- ]
24693
- }),
24694
- /* @__PURE__ */ jsx112("div", {
24695
- style: ySpacer
24696
- }),
24697
- /* @__PURE__ */ jsx112(PlayerSeekBar, {
24698
- onSeekEnd,
24699
- onSeekStart,
24700
- durationInFrames,
24701
- inFrame,
24702
- outFrame
24703
- })
24704
- ]
24728
+ }
24729
+ return /* @__PURE__ */ jsx112("div", {
24730
+ style,
24731
+ className: "warning-banner",
24732
+ children: /* @__PURE__ */ jsx112("a", {
24733
+ style: { color: "white" },
24734
+ href: "https://github.com/remotion-dev/remotion/pull/4589",
24735
+ children: "Remotion Unlicensed – Contact hi@remotion.dev"
24736
+ })
24705
24737
  });
24706
24738
  };
24707
24739
  var IS_NODE = typeof document === "undefined";
@@ -28441,16 +28473,27 @@ var videoIteratorManager = async ({
28441
28473
  let framesRendered = 0;
28442
28474
  let currentDelayHandle = null;
28443
28475
  let lastDrawnFrame = null;
28476
+ let lastDrawnMediaTime = null;
28477
+ let lastPlainFrameTime;
28444
28478
  let currentSeek = null;
28479
+ let lastPaintedEffects = [];
28480
+ let lastPaintedEffectChainState = null;
28481
+ let lastCompletedEffectPaint = null;
28445
28482
  let destroyed = false;
28446
28483
  let pendingEffectRun = null;
28447
28484
  const clearLastDrawnFrame = () => {
28448
28485
  lastDrawnFrame = null;
28486
+ lastDrawnMediaTime = null;
28487
+ if (lastPlainFrameTime !== undefined) {
28488
+ lastPlainFrameTime = null;
28489
+ }
28490
+ lastCompletedEffectPaint = null;
28449
28491
  };
28450
28492
  const displayWidth = await videoTrack.getDisplayWidth();
28451
28493
  const displayHeight = await videoTrack.getDisplayHeight();
28452
28494
  if (canvas && !getIsDisposed()) {
28453
28495
  if (canvas.width !== displayWidth || canvas.height !== displayHeight) {
28496
+ lastPlainFrameTime = null;
28454
28497
  canvas.width = displayWidth;
28455
28498
  canvas.height = displayHeight;
28456
28499
  }
@@ -28460,14 +28503,21 @@ var videoIteratorManager = async ({
28460
28503
  const frameSize = maxWidth / displayWidth < Math.min(1, maxHeight / displayHeight) ? { width: maxWidth, fit: "fill" } : maxHeight < displayHeight ? { height: maxHeight, fit: "fill" } : {};
28461
28504
  const videoSink = new VideoSampleSink(videoTrack);
28462
28505
  const prewarmedVideoIteratorCache = makePrewarmedVideoIteratorCache(videoSink, await videoTrack.getTimeResolution(), Object.keys(frameSize).length === 0 ? null : frameSize);
28463
- const paintFrame = async (frame) => {
28506
+ const paintFrame = async (frame, mediaTime) => {
28464
28507
  if (destroyed) {
28465
28508
  return;
28466
28509
  }
28467
28510
  if (context && canvas) {
28511
+ lastPlainFrameTime = null;
28468
28512
  const effects = getEffects();
28513
+ lastPaintedEffects = effects;
28469
28514
  const chainState = getEffectChainState(canvas.width, canvas.height);
28515
+ lastPaintedEffectChainState = chainState;
28470
28516
  if (effects.length > 0 && chainState && canvas instanceof HTMLCanvasElement) {
28517
+ if (lastCompletedEffectPaint?.frame === frame && lastCompletedEffectPaint.effects === effects && lastCompletedEffectPaint.chainState === chainState) {
28518
+ return;
28519
+ }
28520
+ lastCompletedEffectPaint = null;
28471
28521
  const firstEnabledEffect = effects.find((effect) => !effect.params.disabled);
28472
28522
  const source = getStableEffectSource(frame, {
28473
28523
  width: canvas.width,
@@ -28477,7 +28527,7 @@ var videoIteratorManager = async ({
28477
28527
  const run = { state: chainState, runId: chainState.currentRunId + 1 };
28478
28528
  pendingEffectRun = run;
28479
28529
  try {
28480
- await runEffectChain2({
28530
+ const completed = await runEffectChain2({
28481
28531
  state: chainState,
28482
28532
  source,
28483
28533
  effects,
@@ -28485,23 +28535,31 @@ var videoIteratorManager = async ({
28485
28535
  width: canvas.width,
28486
28536
  height: canvas.height
28487
28537
  });
28538
+ if (completed && pendingEffectRun === run) {
28539
+ lastCompletedEffectPaint = { frame, effects, chainState };
28540
+ }
28488
28541
  } finally {
28489
28542
  if (pendingEffectRun === run) {
28490
28543
  pendingEffectRun = null;
28491
28544
  }
28492
28545
  }
28493
28546
  } else {
28547
+ lastCompletedEffectPaint = null;
28494
28548
  context.clearRect(0, 0, canvas.width, canvas.height);
28495
28549
  drawStableFrame(context, frame, canvas.width, canvas.height);
28550
+ if (effects.length === 0) {
28551
+ lastPlainFrameTime = mediaTime;
28552
+ }
28496
28553
  }
28497
28554
  }
28498
28555
  };
28499
- const drawFrame = async (frame) => {
28500
- await paintFrame(frame);
28556
+ const drawFrame = async (frame, mediaTime) => {
28557
+ await paintFrame(frame, mediaTime);
28501
28558
  if (destroyed) {
28502
28559
  return;
28503
28560
  }
28504
28561
  lastDrawnFrame = frame;
28562
+ lastDrawnMediaTime = mediaTime;
28505
28563
  framesRendered++;
28506
28564
  drawDebugOverlay();
28507
28565
  const callback = getOnVideoFrameCallback();
@@ -28514,7 +28572,7 @@ var videoIteratorManager = async ({
28514
28572
  if (!lastDrawnFrame) {
28515
28573
  return;
28516
28574
  }
28517
- await paintFrame(lastDrawnFrame);
28575
+ await paintFrame(lastDrawnFrame, lastDrawnMediaTime);
28518
28576
  if (destroyed) {
28519
28577
  return;
28520
28578
  }
@@ -28560,7 +28618,7 @@ var videoIteratorManager = async ({
28560
28618
  }
28561
28619
  if (nonce.isStale()) {
28562
28620
  if (!videoFrameIterator.isDestroyed() && iterator.initialFrame) {
28563
- await drawFrame(iterator.initialFrame);
28621
+ await drawFrame(iterator.initialFrame, timeToSeek);
28564
28622
  }
28565
28623
  return;
28566
28624
  }
@@ -28570,7 +28628,7 @@ var videoIteratorManager = async ({
28570
28628
  if (!iterator.initialFrame) {
28571
28629
  return;
28572
28630
  }
28573
- await drawFrame(iterator.initialFrame);
28631
+ await drawFrame(iterator.initialFrame, timeToSeek);
28574
28632
  } catch (_catch) {
28575
28633
  var _err = _catch, _hasErr = 1;
28576
28634
  } finally {
@@ -28592,6 +28650,11 @@ var videoIteratorManager = async ({
28592
28650
  return;
28593
28651
  }
28594
28652
  if (currentSeek !== null && roundTo4Digits(currentSeek) === roundTo4Digits(newTime)) {
28653
+ const effects = getEffects();
28654
+ const chainState = canvas ? getEffectChainState(canvas.width, canvas.height) : null;
28655
+ if ((effects !== lastPaintedEffects || chainState !== lastPaintedEffectChainState) && (effects.length > 0 || lastPaintedEffects.length > 0)) {
28656
+ await redrawCurrentFrame();
28657
+ }
28595
28658
  return;
28596
28659
  }
28597
28660
  const previousTime = currentSeek;
@@ -28647,7 +28710,7 @@ var videoIteratorManager = async ({
28647
28710
  return;
28648
28711
  }
28649
28712
  if (result.type === "satisfied") {
28650
- await drawFrame(result.frame);
28713
+ await drawFrame(result.frame, newTime);
28651
28714
  currentSeek = newTime;
28652
28715
  return;
28653
28716
  }
@@ -28688,6 +28751,12 @@ var videoIteratorManager = async ({
28688
28751
  videoFrameIterator = null;
28689
28752
  },
28690
28753
  getVideoFrameIterator: () => videoFrameIterator,
28754
+ getPlainFrameTime: (copiedFrameTime) => {
28755
+ if (destroyed || pendingEffectRun || lastCompletedEffectPaint) {
28756
+ return null;
28757
+ }
28758
+ return lastPlainFrameTime === undefined ? copiedFrameTime : lastPlainFrameTime;
28759
+ },
28691
28760
  drawFrame,
28692
28761
  redrawCurrentFrame,
28693
28762
  getFramesRendered: () => framesRendered
@@ -29323,7 +29392,7 @@ var callOnErrorAndResolve = ({
29323
29392
  if (isClientSideRendering) {
29324
29393
  return ["fail", clientSideError];
29325
29394
  }
29326
- if (result) {
29395
+ if (result === "fail" || result === "fallback") {
29327
29396
  return [result, error];
29328
29397
  }
29329
29398
  if (disallowFallback) {
@@ -30697,6 +30766,9 @@ var makeKeyframeBank = async ({
30697
30766
  frames[frame.timestamp] = frame;
30698
30767
  frameTimestamps.push(frame.timestamp);
30699
30768
  allocationSize += getAllocationSize(frame);
30769
+ while (frameTimestamps.length > 2) {
30770
+ deleteFrameAtTimestamp(frameTimestamps[0]);
30771
+ }
30700
30772
  lastUsed = Date.now();
30701
30773
  Internals.Log.trace({ logLevel, tag: "@remotion/media" }, `Added frame at ${frame.timestamp}sec to bank`);
30702
30774
  };
@@ -32671,8 +32743,10 @@ var {
32671
32743
  useBuffering: useBuffering22,
32672
32744
  useMediaAudioState: useMediaAudioState22
32673
32745
  } = Internals;
32746
+ var studioVideoCanvases = new Map;
32674
32747
  var VideoForPreviewAssertedShowing = ({
32675
32748
  src: unpreloadedSrc,
32749
+ mediaTime,
32676
32750
  style,
32677
32751
  playbackRate,
32678
32752
  toneFrequency,
@@ -32706,6 +32780,7 @@ var VideoForPreviewAssertedShowing = ({
32706
32780
  }) => {
32707
32781
  const src = usePreload22(unpreloadedSrc);
32708
32782
  const canvasRef = useRef37(null);
32783
+ const { isStudio } = useRemotionEnvironment();
32709
32784
  const videoConfig = useUnsafeVideoConfig22();
32710
32785
  const frame = useCurrentFrame();
32711
32786
  const mediaPlayerRef = useRef37(null);
@@ -32790,6 +32865,56 @@ var VideoForPreviewAssertedShowing = ({
32790
32865
  const hasDrawnRealFrameRef = useRef37(false);
32791
32866
  const isPremountingRef = useRef37(isPremounting);
32792
32867
  isPremountingRef.current = isPremounting;
32868
+ const maxWidth = maxCanvasSinkFrameSize?.width;
32869
+ const maxHeight = maxCanvasSinkFrameSize?.height;
32870
+ const studioSourceKey = useMemo411(() => isStudio ? JSON.stringify([
32871
+ getSharedInputCacheKey({
32872
+ src: preloadedSrc,
32873
+ credentials,
32874
+ requestInit: initialRequestInit
32875
+ }),
32876
+ maxWidth,
32877
+ maxHeight
32878
+ ]) : null, [
32879
+ credentials,
32880
+ initialRequestInit,
32881
+ isStudio,
32882
+ maxHeight,
32883
+ maxWidth,
32884
+ preloadedSrc
32885
+ ]);
32886
+ const copiedFrameRef = useRef37(null);
32887
+ const canSharePausedFrame = !shouldFallbackToNativeVideo && terminalError === null && !playing && !loop && !debugOverlay && !onVideoFrame && effects.length === 0 && !_experimentalInitiallyDrawCachedFrame;
32888
+ const canSharePausedFrameRef = useRef37(canSharePausedFrame);
32889
+ canSharePausedFrameRef.current = canSharePausedFrame;
32890
+ const mediaTimeRef = useRef37(mediaTime);
32891
+ mediaTimeRef.current = mediaTime;
32892
+ const canReceivePausedFrame = canSharePausedFrame && !isPremounting && !isPostmounting && !headless;
32893
+ useLayoutEffect33(() => {
32894
+ const canvas = canvasRef.current;
32895
+ if (!canvas || !studioSourceKey || !canReceivePausedFrame || mediaPlayerRef.current) {
32896
+ return;
32897
+ }
32898
+ for (const [source, previous] of studioVideoCanvases) {
32899
+ if (source !== canvas && previous.sourceKey === studioSourceKey && previous.getPlainFrameTime() === mediaTimeRef.current) {
32900
+ const context = canvas.getContext("2d");
32901
+ if (!context) {
32902
+ return;
32903
+ }
32904
+ canvas.width = source.width;
32905
+ canvas.height = source.height;
32906
+ context.drawImage(source, 0, 0);
32907
+ copiedFrameRef.current = {
32908
+ canvas,
32909
+ sourceKey: studioSourceKey,
32910
+ mediaTime: mediaTimeRef.current,
32911
+ width: canvas.width,
32912
+ height: canvas.height
32913
+ };
32914
+ break;
32915
+ }
32916
+ }
32917
+ }, [canReceivePausedFrame, studioSourceKey]);
32793
32918
  useLayoutEffect33(() => {
32794
32919
  if (!_experimentalInitiallyDrawCachedFrame) {
32795
32920
  return;
@@ -32836,9 +32961,10 @@ var VideoForPreviewAssertedShowing = ({
32836
32961
  scheduleAudioNode: sharedAudioContext.scheduleAudioNode,
32837
32962
  unscheduleAudioNode: sharedAudioContext.unscheduleAudioNode
32838
32963
  } : null;
32964
+ const canvas = canvasRef.current;
32839
32965
  try {
32840
32966
  const player = new MediaPlayer({
32841
- canvas: canvasRef.current,
32967
+ canvas,
32842
32968
  src: preloadedSrc,
32843
32969
  logLevel,
32844
32970
  sharedAudioContext: sharedAudioContextForMediaPlayer,
@@ -32879,6 +33005,20 @@ var VideoForPreviewAssertedShowing = ({
32879
33005
  }
32880
33006
  }
32881
33007
  });
33008
+ if (canvas && studioSourceKey) {
33009
+ const copied = copiedFrameRef.current;
33010
+ copiedFrameRef.current = null;
33011
+ studioVideoCanvases.set(canvas, {
33012
+ sourceKey: studioSourceKey,
33013
+ getPlainFrameTime: () => {
33014
+ if (!canSharePausedFrameRef.current) {
33015
+ return null;
33016
+ }
33017
+ const copiedTime = copied?.canvas === canvas && copied.sourceKey === studioSourceKey && copied.mediaTime === mediaTimeRef.current && copied.width === canvas.width && copied.height === canvas.height ? copied.mediaTime : null;
33018
+ return player.videoIteratorManager ? player.videoIteratorManager.getPlainFrameTime(copiedTime) : copiedTime;
33019
+ }
33020
+ });
33021
+ }
32882
33022
  mediaPlayerRef.current = player;
32883
33023
  player.initialize(currentTimeRef.current, initialMuted.current, initialVolume.current).then((result) => {
32884
33024
  if (result.type === "disposed") {
@@ -32951,6 +33091,9 @@ var VideoForPreviewAssertedShowing = ({
32951
33091
  setShouldFallbackToNativeVideo(true);
32952
33092
  }
32953
33093
  return () => {
33094
+ if (canvas && studioSourceKey) {
33095
+ studioVideoCanvases.delete(canvas);
33096
+ }
32954
33097
  if (mediaPlayerRef.current) {
32955
33098
  Internals.Log.trace({ logLevel, tag: "@remotion/media" }, `[VideoForPreview] Disposing MediaPlayer`);
32956
33099
  mediaPlayerRef.current.dispose();
@@ -32973,6 +33116,7 @@ var VideoForPreviewAssertedShowing = ({
32973
33116
  credentials,
32974
33117
  initialRequestInit,
32975
33118
  setMediaDurationInSeconds,
33119
+ studioSourceKey,
32976
33120
  maxCanvasSinkFrameSize?.width,
32977
33121
  maxCanvasSinkFrameSize?.height
32978
33122
  ]);
@@ -33018,13 +33162,17 @@ var VideoForPreviewAssertedShowing = ({
33018
33162
  }
33019
33163
  mediaPlayer.setVideoFrameCallback(onVideoFrame ?? null);
33020
33164
  }, [onVideoFrame, mediaPlayerReady]);
33165
+ const lastEffectsTime = useRef37(currentTime);
33021
33166
  useLayoutEffect33(() => {
33167
+ const timeChanged = lastEffectsTime.current !== currentTime;
33168
+ lastEffectsTime.current = currentTime;
33022
33169
  const mediaPlayer = mediaPlayerRef.current;
33023
- if (!mediaPlayer || !mediaPlayerReady) {
33170
+ if (!mediaPlayer || !mediaPlayerReady || timeChanged) {
33024
33171
  return;
33025
33172
  }
33026
33173
  mediaPlayer.redrawVideoEffects().catch(() => {});
33027
33174
  }, [
33175
+ currentTime,
33028
33176
  effects,
33029
33177
  effectsOutputSize?.width,
33030
33178
  effectsOutputSize?.height,
@@ -33075,19 +33223,17 @@ var VideoForPreview2 = (props) => {
33075
33223
  const frame = useCurrentFrame();
33076
33224
  const videoConfig = useVideoConfig();
33077
33225
  const currentTime = frame / videoConfig.fps;
33078
- const showShow = useMemo411(() => {
33079
- return getTimeInSeconds({
33080
- unloopedTimeInSeconds: currentTime,
33081
- playbackRate: props.playbackRate,
33082
- loop: props.loop,
33083
- trimBefore: props.trimBefore,
33084
- trimAfter: props.trimAfter,
33085
- mediaDurationInSeconds: Infinity,
33086
- fps: videoConfig.fps,
33087
- ifNoMediaDuration: "infinity",
33088
- src: props.src
33089
- }) !== null;
33090
- }, [
33226
+ const mediaTime = useMemo411(() => getTimeInSeconds({
33227
+ unloopedTimeInSeconds: currentTime,
33228
+ playbackRate: props.playbackRate,
33229
+ loop: props.loop,
33230
+ trimBefore: props.trimBefore,
33231
+ trimAfter: props.trimAfter,
33232
+ mediaDurationInSeconds: Infinity,
33233
+ fps: videoConfig.fps,
33234
+ ifNoMediaDuration: "infinity",
33235
+ src: props.src
33236
+ }), [
33091
33237
  currentTime,
33092
33238
  props.loop,
33093
33239
  props.playbackRate,
@@ -33096,11 +33242,12 @@ var VideoForPreview2 = (props) => {
33096
33242
  props.trimBefore,
33097
33243
  props.trimAfter
33098
33244
  ]);
33099
- if (!showShow) {
33245
+ if (mediaTime === null) {
33100
33246
  return null;
33101
33247
  }
33102
33248
  return /* @__PURE__ */ jsx411(VideoForPreviewAssertedShowing, {
33103
- ...props
33249
+ ...props,
33250
+ mediaTime
33104
33251
  });
33105
33252
  };
33106
33253
  var VideoForRendering2 = ({
@@ -33215,16 +33362,12 @@ var VideoForRendering2 = ({
33215
33362
  return;
33216
33363
  }
33217
33364
  const handleError = (err, clientSideError, fallbackMessage, mediaDurationInSeconds) => {
33218
- if (environment.isClientSideRendering) {
33219
- cancelRender(clientSideError);
33220
- return;
33221
- }
33222
33365
  const [action, errorToUse] = callOnErrorAndResolve({
33223
33366
  onError,
33224
33367
  error: err,
33225
33368
  disallowFallback: disallowFallbackToOffthreadVideo,
33226
33369
  isClientSideRendering: environment.isClientSideRendering,
33227
- clientSideError: err
33370
+ clientSideError
33228
33371
  });
33229
33372
  if (action === "fail") {
33230
33373
  cancelRender(errorToUse);
@@ -35207,7 +35350,7 @@ import {
35207
35350
  } from "mediabunny";
35208
35351
 
35209
35352
  // ../core/dist/esm/version.mjs
35210
- var VERSION2 = "4.0.540";
35353
+ var VERSION2 = "4.0.541";
35211
35354
 
35212
35355
  // ../web-renderer/dist/esm/index.mjs
35213
35356
  import { AudioSample, VideoSample } from "mediabunny";
@@ -35602,6 +35745,17 @@ var addAudioSample = async (audio, audioSampleSource) => {
35602
35745
  sample.close();
35603
35746
  }
35604
35747
  };
35748
+ var decodeBinaryArtifact = (encoded) => {
35749
+ if ("fromBase64" in Uint8Array && typeof Uint8Array.fromBase64 === "function") {
35750
+ return Uint8Array.fromBase64(encoded);
35751
+ }
35752
+ const binary = atob(encoded);
35753
+ const bytes = new Uint8Array(binary.length);
35754
+ for (let index = 0;index < binary.length; index++) {
35755
+ bytes[index] = binary.charCodeAt(index);
35756
+ }
35757
+ return bytes;
35758
+ };
35605
35759
  var onlyArtifact = async ({
35606
35760
  assets,
35607
35761
  frameBuffer
@@ -35613,7 +35767,7 @@ var onlyArtifact = async ({
35613
35767
  if (artifact.contentType === "binary" || artifact.contentType === "text") {
35614
35768
  result.push({
35615
35769
  frame: artifact.frame,
35616
- content: artifact.content,
35770
+ content: artifact.contentType === "binary" ? decodeBinaryArtifact(artifact.content) : artifact.content,
35617
35771
  filename: artifact.filename,
35618
35772
  downloadBehavior: artifact.downloadBehavior
35619
35773
  });
@@ -41743,7 +41897,7 @@ var renderMediaOnWeb = (options) => {
41743
41897
  };
41744
41898
 
41745
41899
  // src/components/homepage/Demo/DemoRender.tsx
41746
- import React51, { useCallback as useCallback35 } from "react";
41900
+ import React49, { useCallback as useCallback35 } from "react";
41747
41901
  import { z } from "zod";
41748
41902
 
41749
41903
  // src/components/homepage/Demo/DemoErrorIcon.tsx
@@ -43664,8 +43818,9 @@ var cutPath = (d, length) => {
43664
43818
  if (summedUpLength + instructionAndInfo.length > length) {
43665
43819
  const remainingLength = length - summedUpLength;
43666
43820
  const progress = remainingLength / instructionAndInfo.length;
43821
+ const { instruction } = instructionAndInfo;
43667
43822
  const cut = cutInstruction({
43668
- instruction: instructionAndInfo.instruction,
43823
+ instruction: instruction.type === "Z" ? { type: "L", x: segment.startPoint.x, y: segment.startPoint.y } : instruction,
43669
43824
  lastPoint: instructionAndInfo.startPoint,
43670
43825
  progress
43671
43826
  });
@@ -43963,7 +44118,7 @@ var PathInternals = {
43963
44118
  };
43964
44119
 
43965
44120
  // ../shapes/dist/esm/index.mjs
43966
- import React46, { useMemo as useMemo64 } from "react";
44121
+ import React42, { useMemo as useMemo64 } from "react";
43967
44122
  import { version } from "react-dom";
43968
44123
  import { jsx as jsx77, jsxs as jsxs21 } from "react/jsx-runtime";
43969
44124
  import { jsx as jsx213 } from "react/jsx-runtime";
@@ -44185,7 +44340,7 @@ var RenderSvgWithTiming = ({
44185
44340
  _remotionInternalPostmountDisplay: effectivePostmountFor || null,
44186
44341
  _remotionInternalIsPremounting: premountingActive,
44187
44342
  _remotionInternalIsPostmounting: postmountingActive,
44188
- children: React46.cloneElement(content, { style: premountingStyle ?? undefined })
44343
+ children: React42.cloneElement(content, { style: premountingStyle ?? undefined })
44189
44344
  })
44190
44345
  });
44191
44346
  };
@@ -44259,7 +44414,7 @@ var RenderSvg = ({
44259
44414
  }
44260
44415
  const prevX = prevInstruction.x;
44261
44416
  const prevY = prevInstruction.y;
44262
- return /* @__PURE__ */ jsxs21(React46.Fragment, {
44417
+ return /* @__PURE__ */ jsxs21(React42.Fragment, {
44263
44418
  children: [
44264
44419
  /* @__PURE__ */ jsx77("path", {
44265
44420
  d: `M ${prevX} ${prevY} ${i.cp1x} ${i.cp1y}`,
@@ -46010,7 +46165,7 @@ var style2 = {
46010
46165
  justifyContent: "center"
46011
46166
  };
46012
46167
  var RenderButton = ({ renderData, onError, playerRef }) => {
46013
- const [state, setState] = React51.useState({
46168
+ const [state, setState] = React49.useState({
46014
46169
  type: "idle"
46015
46170
  });
46016
46171
  const triggerRender = useCallback35(async () => {
@@ -46530,7 +46685,7 @@ var PlayerVolume = ({ playerRef }) => {
46530
46685
  };
46531
46686
 
46532
46687
  // src/components/homepage/Demo/PlayPauseButton.tsx
46533
- import React60, { useCallback as useCallback39, useEffect as useEffect38 } from "react";
46688
+ import React58, { useCallback as useCallback39, useEffect as useEffect38 } from "react";
46534
46689
  import { jsx as jsx88 } from "react/jsx-runtime";
46535
46690
  var playerButtonStyle2 = {
46536
46691
  appearance: "none",
@@ -46547,7 +46702,7 @@ var playerButtonStyle2 = {
46547
46702
  color: PALETTE.TEXT_COLOR
46548
46703
  };
46549
46704
  var PlayPauseButton = ({ playerRef }) => {
46550
- const [playing, setPlaying] = React60.useState(true);
46705
+ const [playing, setPlaying] = React58.useState(true);
46551
46706
  useEffect38(() => {
46552
46707
  const { current } = playerRef;
46553
46708
  if (!current) {
@@ -46585,7 +46740,7 @@ var PlayPauseButton = ({ playerRef }) => {
46585
46740
  };
46586
46741
 
46587
46742
  // src/components/homepage/Demo/TimeDisplay.tsx
46588
- import React61, { useEffect as useEffect39 } from "react";
46743
+ import React59, { useEffect as useEffect39 } from "react";
46589
46744
  import { jsx as jsx89 } from "react/jsx-runtime";
46590
46745
  var formatTime2 = (timeInSeconds) => {
46591
46746
  const minutes = Math.floor(timeInSeconds / 60);
@@ -46593,7 +46748,7 @@ var formatTime2 = (timeInSeconds) => {
46593
46748
  return `${String(minutes)}:${String(seconds).padStart(2, "0")}`;
46594
46749
  };
46595
46750
  var TimeDisplay = ({ fps, playerRef }) => {
46596
- const [time, setTime] = React61.useState(0);
46751
+ const [time, setTime] = React59.useState(0);
46597
46752
  useEffect39(() => {
46598
46753
  const { current } = playerRef;
46599
46754
  if (!current) {
@@ -46672,7 +46827,7 @@ var PlayerControls = ({ playerRef, durationInFrames, fps, children }) => {
46672
46827
  };
46673
46828
 
46674
46829
  // src/components/homepage/Demo/ThemeNudge.tsx
46675
- import React63 from "react";
46830
+ import React60 from "react";
46676
46831
  import { jsx as jsx91, jsxs as jsxs30 } from "react/jsx-runtime";
46677
46832
  var origWidth3 = 37;
46678
46833
  var scale3 = 0.4;
@@ -46695,7 +46850,7 @@ var Icon3 = () => {
46695
46850
  };
46696
46851
  var ThemeNudge = () => {
46697
46852
  const { colorMode, setColorMode } = useColorMode();
46698
- const toggleTheme = React63.useCallback((e) => {
46853
+ const toggleTheme = React60.useCallback((e) => {
46699
46854
  e.preventDefault();
46700
46855
  setColorMode(colorMode === "dark" ? "light" : "dark");
46701
46856
  }, [colorMode, setColorMode]);
@@ -46885,7 +47040,7 @@ var Demo = ({ title, description }) => {
46885
47040
  };
46886
47041
 
46887
47042
  // src/components/homepage/MakeVideosLinks.tsx
46888
- import React65 from "react";
47043
+ import React62 from "react";
46889
47044
  import { jsx as jsx95, jsxs as jsxs34, Fragment as Fragment7 } from "react/jsx-runtime";
46890
47045
  var icon2 = {
46891
47046
  height: 16,
@@ -46926,7 +47081,7 @@ var MakeVideosLinks = ({ links }) => {
46926
47081
  /* @__PURE__ */ jsx95("div", {
46927
47082
  className: "leading-6",
46928
47083
  children: links.map((link) => {
46929
- return /* @__PURE__ */ jsxs34(React65.Fragment, {
47084
+ return /* @__PURE__ */ jsxs34(React62.Fragment, {
46930
47085
  children: [
46931
47086
  /* @__PURE__ */ jsx95(MakeVideosLinkItem, {
46932
47087
  ...link
@@ -47318,7 +47473,7 @@ import { useMemo as useMemo80 } from "react";
47318
47473
 
47319
47474
  // ../design/dist/esm/index.mjs
47320
47475
  import * as React210 from "react";
47321
- import * as React67 from "react";
47476
+ import * as React64 from "react";
47322
47477
  import { Fragment as Fragment23, jsx as jsx100 } from "react/jsx-runtime";
47323
47478
  import React510, { useCallback as useCallback210, useRef as useRef212, useState as useState212 } from "react";
47324
47479
 
@@ -48667,7 +48822,7 @@ import { jsx as jsx313, jsxs as jsxs39 } from "react/jsx-runtime";
48667
48822
  import { useEffect as useEffect210, useMemo as useMemo212, useRef as useRef49 } from "react";
48668
48823
  import { jsx as jsx413 } from "react/jsx-runtime";
48669
48824
  import { jsx as jsx511, jsxs as jsxs210 } from "react/jsx-runtime";
48670
- import React68 from "react";
48825
+ import React65 from "react";
48671
48826
  import { jsx as jsx611 } from "react/jsx-runtime";
48672
48827
  import { jsx as jsx710 } from "react/jsx-runtime";
48673
48828
  import { jsx as jsx810, jsxs as jsxs310 } from "react/jsx-runtime";
@@ -48679,10 +48834,10 @@ import { jsx as jsx124 } from "react/jsx-runtime";
48679
48834
  import * as React362 from "react";
48680
48835
  import * as ReactDOM4 from "react-dom";
48681
48836
  import React113 from "react";
48682
- import * as React82 from "react";
48837
+ import * as React83 from "react";
48683
48838
  import { jsx as jsx133 } from "react/jsx-runtime";
48684
- import * as React92 from "react";
48685
- import * as React102 from "react";
48839
+ import * as React93 from "react";
48840
+ import * as React103 from "react";
48686
48841
  import { Fragment as Fragment42, jsx as jsx143 } from "react/jsx-runtime";
48687
48842
  import { jsx as jsx153 } from "react/jsx-runtime";
48688
48843
  import * as React122 from "react";
@@ -48791,7 +48946,7 @@ function composeRefs(...refs) {
48791
48946
  };
48792
48947
  }
48793
48948
  function useComposedRefs(...refs) {
48794
- return React67.useCallback(composeRefs(...refs), refs);
48949
+ return React64.useCallback(composeRefs(...refs), refs);
48795
48950
  }
48796
48951
  var REACT_LAZY_TYPE = Symbol.for("react.lazy");
48797
48952
  var use = React210[" use ".trim().toString()];
@@ -48799,7 +48954,7 @@ var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
48799
48954
  function cn(...inputs) {
48800
48955
  return twMerge(clsx(inputs));
48801
48956
  }
48802
- var Card2 = React68.forwardRef(({ children, className, ...rest }, ref) => {
48957
+ var Card2 = React65.forwardRef(({ children, className, ...rest }, ref) => {
48803
48958
  return /* @__PURE__ */ jsx611("div", {
48804
48959
  ref,
48805
48960
  className: cn("rounded-lg border-2 border-black bg-card-bg text-text border-b-4", className),
@@ -48830,18 +48985,18 @@ function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForD
48830
48985
  function createContextScope(scopeName, createContextScopeDeps = []) {
48831
48986
  let defaultContexts = [];
48832
48987
  function createContext3(rootComponentName, defaultContext) {
48833
- const BaseContext = React82.createContext(defaultContext);
48988
+ const BaseContext = React83.createContext(defaultContext);
48834
48989
  const index = defaultContexts.length;
48835
48990
  defaultContexts = [...defaultContexts, defaultContext];
48836
48991
  function Provider(props) {
48837
48992
  const { scope, children, ...context } = props;
48838
48993
  const Context = scope?.[scopeName][index] || BaseContext;
48839
- const value = React82.useMemo(() => context, Object.values(context));
48994
+ const value = React83.useMemo(() => context, Object.values(context));
48840
48995
  return /* @__PURE__ */ jsx133(Context.Provider, { value, children });
48841
48996
  }
48842
48997
  function useContext2(consumerName, scope) {
48843
48998
  const Context = scope?.[scopeName][index] || BaseContext;
48844
- const context = React82.useContext(Context);
48999
+ const context = React83.useContext(Context);
48845
49000
  if (context)
48846
49001
  return context;
48847
49002
  if (defaultContext !== undefined)
@@ -48853,11 +49008,11 @@ function createContextScope(scopeName, createContextScopeDeps = []) {
48853
49008
  }
48854
49009
  const createScope = () => {
48855
49010
  const scopeContexts = defaultContexts.map((defaultContext) => {
48856
- return React82.createContext(defaultContext);
49011
+ return React83.createContext(defaultContext);
48857
49012
  });
48858
49013
  return function useScope(scope) {
48859
49014
  const contexts = scope?.[scopeName] || scopeContexts;
48860
- return React82.useMemo(() => ({ [`__scope${scopeName}`]: { ...scope, [scopeName]: contexts } }), [scope, contexts]);
49015
+ return React83.useMemo(() => ({ [`__scope${scopeName}`]: { ...scope, [scopeName]: contexts } }), [scope, contexts]);
48861
49016
  };
48862
49017
  };
48863
49018
  createScope.scopeName = scopeName;
@@ -48878,7 +49033,7 @@ function composeContextScopes(...scopes) {
48878
49033
  const currentScope = scopeProps[`__scope${scopeName}`];
48879
49034
  return { ...nextScopes2, ...currentScope };
48880
49035
  }, {});
48881
- return React82.useMemo(() => ({ [`__scope${baseScope.scopeName}`]: nextScopes }), [nextScopes]);
49036
+ return React83.useMemo(() => ({ [`__scope${baseScope.scopeName}`]: nextScopes }), [nextScopes]);
48882
49037
  };
48883
49038
  };
48884
49039
  createScope.scopeName = baseScope.scopeName;
@@ -48895,45 +49050,45 @@ function composeRefs2(...refs) {
48895
49050
  return (node) => refs.forEach((ref) => setRef22(ref, node));
48896
49051
  }
48897
49052
  function useComposedRefs2(...refs) {
48898
- return React92.useCallback(composeRefs2(...refs), refs);
49053
+ return React93.useCallback(composeRefs2(...refs), refs);
48899
49054
  }
48900
- var Slot2 = React102.forwardRef((props, forwardedRef) => {
49055
+ var Slot2 = React103.forwardRef((props, forwardedRef) => {
48901
49056
  const { children, ...slotProps } = props;
48902
- const childrenArray = React102.Children.toArray(children);
49057
+ const childrenArray = React103.Children.toArray(children);
48903
49058
  const slottable = childrenArray.find(isSlottable2);
48904
49059
  if (slottable) {
48905
49060
  const newElement = slottable.props.children;
48906
49061
  const newChildren = childrenArray.map((child) => {
48907
49062
  if (child === slottable) {
48908
- if (React102.Children.count(newElement) > 1)
48909
- return React102.Children.only(null);
48910
- return React102.isValidElement(newElement) ? newElement.props.children : null;
49063
+ if (React103.Children.count(newElement) > 1)
49064
+ return React103.Children.only(null);
49065
+ return React103.isValidElement(newElement) ? newElement.props.children : null;
48911
49066
  } else {
48912
49067
  return child;
48913
49068
  }
48914
49069
  });
48915
- return /* @__PURE__ */ jsx143(SlotClone, { ...slotProps, ref: forwardedRef, children: React102.isValidElement(newElement) ? React102.cloneElement(newElement, undefined, newChildren) : null });
49070
+ return /* @__PURE__ */ jsx143(SlotClone, { ...slotProps, ref: forwardedRef, children: React103.isValidElement(newElement) ? React103.cloneElement(newElement, undefined, newChildren) : null });
48916
49071
  }
48917
49072
  return /* @__PURE__ */ jsx143(SlotClone, { ...slotProps, ref: forwardedRef, children });
48918
49073
  });
48919
49074
  Slot2.displayName = "Slot";
48920
- var SlotClone = React102.forwardRef((props, forwardedRef) => {
49075
+ var SlotClone = React103.forwardRef((props, forwardedRef) => {
48921
49076
  const { children, ...slotProps } = props;
48922
- if (React102.isValidElement(children)) {
49077
+ if (React103.isValidElement(children)) {
48923
49078
  const childrenRef = getElementRef2(children);
48924
- return React102.cloneElement(children, {
49079
+ return React103.cloneElement(children, {
48925
49080
  ...mergeProps2(slotProps, children.props),
48926
49081
  ref: forwardedRef ? composeRefs2(forwardedRef, childrenRef) : childrenRef
48927
49082
  });
48928
49083
  }
48929
- return React102.Children.count(children) > 1 ? React102.Children.only(null) : null;
49084
+ return React103.Children.count(children) > 1 ? React103.Children.only(null) : null;
48930
49085
  });
48931
49086
  SlotClone.displayName = "SlotClone";
48932
49087
  var Slottable2 = ({ children }) => {
48933
49088
  return /* @__PURE__ */ jsx143(Fragment42, { children });
48934
49089
  };
48935
49090
  function isSlottable2(child) {
48936
- return React102.isValidElement(child) && child.type === Slottable2;
49091
+ return React103.isValidElement(child) && child.type === Slottable2;
48937
49092
  }
48938
49093
  function mergeProps2(slotProps, childProps) {
48939
49094
  const overrideProps = { ...childProps };
@@ -54437,7 +54592,7 @@ var Textarea = React522.forwardRef(({ className, style, ...props }, ref) => {
54437
54592
  Textarea.displayName = "Textarea";
54438
54593
 
54439
54594
  // src/components/homepage/FreePricing.tsx
54440
- import React69, { useCallback as useCallback53, useMemo as useMemo79 } from "react";
54595
+ import React66, { useCallback as useCallback53, useMemo as useMemo79 } from "react";
54441
54596
 
54442
54597
  // ../../node_modules/.bun/tailwind-merge@2.5.2/node_modules/tailwind-merge/dist/bundle-mjs.mjs
54443
54598
  var CLASS_PART_SEPARATOR2 = "-";
@@ -55905,6 +56060,8 @@ var FreePricing = ({ termsHref, faqHref }) => {
55905
56060
  children: [
55906
56061
  /* @__PURE__ */ jsx105("a", {
55907
56062
  href: termsHref,
56063
+ target: termsHref.startsWith("http") ? "_blank" : undefined,
56064
+ rel: "noopener noreferrer",
55908
56065
  className: "underline underline-offset-4 text-inherit font-brand",
55909
56066
  children: "Terms"
55910
56067
  }),
@@ -56075,10 +56232,10 @@ var CompanyPricing = ({
56075
56232
  purchaseHref
56076
56233
  }) => {
56077
56234
  const mobileLayout = useMobileLayout();
56078
- const [creatorsSelected, setCreatorsSelected] = React69.useState(false);
56079
- const [automatorsSelected, setAutomatorsSelected] = React69.useState(true);
56080
- const [devSeatCount, setDevSeatCount] = React69.useState(3);
56081
- const [cloudRenders, setCloudRenders] = React69.useState(1e4);
56235
+ const [creatorsSelected, setCreatorsSelected] = React66.useState(false);
56236
+ const [automatorsSelected, setAutomatorsSelected] = React66.useState(true);
56237
+ const [devSeatCount, setDevSeatCount] = React66.useState(3);
56238
+ const [cloudRenders, setCloudRenders] = React66.useState(1e4);
56082
56239
  const formatPrice = useCallback53((price) => {
56083
56240
  const formatter = new Intl.NumberFormat("en-US", {
56084
56241
  style: "currency",
@@ -56358,7 +56515,7 @@ var Pricing = ({
56358
56515
  faqHref = "/docs/license/faq",
56359
56516
  faqLabel = "License FAQ",
56360
56517
  licenseHref = "https://github.com/remotion-dev/remotion/blob/main/LICENSE.md",
56361
- termsHref = "/docs/terms",
56518
+ termsHref = "https://www.remotion.dev/docs/terms",
56362
56519
  purchaseHref = "https://remotion.pro/dashboard"
56363
56520
  }) => {
56364
56521
  const faqLinkTarget = useMemo80(() => {