UNPKG

remotion

Version:

Make videos programmatically

14,683 lines 449 kB
var __defProp = Object.defineProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {
      get: all[name],
      enumerable: true,
      configurable: true,
      set: (newValue) => all[name] = () => newValue
    });
};

// src/_check-rsc.ts
import { createContext } from "react";
if (typeof createContext !== "function") {
  const err = [
    'Remotion requires React.createContext, but it is "undefined".',
    'If you are in a React Server Component, turn it into a client component by adding "use client" at the top of the file.',
    "",
    "Before:",
    '  import {useCurrentFrame} from "remotion";',
    "",
    "After:",
    '  "use client";',
    '  import {useCurrentFrame} from "remotion";'
  ];
  throw new Error(err.join(`
`));
}

// src/Clipper.tsx
var Clipper = () => {
  throw new Error("<Clipper> has been removed as of Remotion v4.0.228. The native clipping APIs were experimental and subject to removal at any time. We removed them because they were sparingly used and made rendering often slower rather than faster.");
};

// src/Composition.tsx
import { Suspense, useCallback as useCallback3, useContext as useContext9, useEffect as useEffect2 } from "react";
import { createPortal } from "react-dom";

// src/CanUseRemotionHooks.tsx
import { createContext as createContext2 } from "react";
import { jsx } from "react/jsx-runtime";
var CanUseRemotionHooks = createContext2(false);
var CanUseRemotionHooksProvider = ({ children }) => {
  return /* @__PURE__ */ jsx(CanUseRemotionHooks.Provider, {
    value: true,
    children
  });
};

// src/composition-render-error-context.ts
import { createContext as createContext3 } from "react";
var CompositionRenderErrorContext = createContext3({
  setError: () => {},
  clearError: () => {}
});

// src/CompositionErrorBoundary.tsx
import React2 from "react";
var getHot = () => {
  try {
    if (typeof __webpack_module__ === "undefined") {
      return null;
    }
    return __webpack_module__.hot ?? null;
  } catch {
    return null;
  }
};

class CompositionErrorBoundary extends React2.Component {
  state = { hasError: false };
  hmrStatusHandler = null;
  static getDerivedStateFromError() {
    return { hasError: true };
  }
  componentDidCatch(error) {
    this.props.onError(error);
    this.subscribeToHmrReset();
  }
  componentDidMount() {
    if (!this.state.hasError) {
      this.props.onClear();
    }
  }
  componentDidUpdate(_prevProps, prevState) {
    if (prevState.hasError && !this.state.hasError) {
      this.props.onClear();
    }
  }
  componentWillUnmount() {
    this.unsubscribeFromHmrReset();
  }
  subscribeToHmrReset() {
    if (this.hmrStatusHandler) {
      return;
    }
    const hot = getHot();
    if (!hot) {
      return;
    }
    const handler = (status) => {
      if (status !== "idle") {
        return;
      }
      this.unsubscribeFromHmrReset();
      this.setState({ hasError: false });
    };
    this.hmrStatusHandler = handler;
    hot.addStatusHandler(handler);
  }
  unsubscribeFromHmrReset() {
    const handler = this.hmrStatusHandler;
    if (!handler) {
      return;
    }
    this.hmrStatusHandler = null;
    const hot = getHot();
    if (!hot) {
      return;
    }
    hot.removeStatusHandler(handler);
  }
  render() {
    if (this.state.hasError) {
      return null;
    }
    return this.props.children;
  }
}

// src/CompositionManagerContext.tsx
import { createContext as createContext4 } from "react";
var getAssetPreviewCompositionId = (asset) => `asset:${asset}`;
var CompositionManager = createContext4({
  compositions: [],
  folders: [],
  currentCompositionMetadata: null,
  currentAssetMetadata: null,
  canvasContent: null
});
var CompositionSetters = createContext4({
  registerComposition: () => {
    return;
  },
  unregisterComposition: () => {
    return;
  },
  registerFolder: () => {
    return;
  },
  unregisterFolder: () => {
    return;
  },
  setCanvasContent: () => {
    return;
  },
  setCurrentAssetMetadata: () => {
    return;
  },
  onlyRenderComposition: null
});

// src/enable-sequence-stack-traces.ts
import React3 from "react";
var componentsToAddStacksTo = [];
var sequenceComponent = null;
var stacksByControls = new WeakMap;
var componentIdentityResolver = null;
var REMOTION_INTERNAL_STACK_PROP = "_remotionInternalStack";
var getComponentsToAddStacksTo = () => componentsToAddStacksTo;
var addSequenceStackTraces = (component) => {
  componentsToAddStacksTo.push(component);
};
var setSequenceComponent = (component) => {
  sequenceComponent = component;
};
var getSequenceComponent = () => sequenceComponent;
var setComponentIdentityResolver = (resolver) => {
  componentIdentityResolver = resolver;
};
var resolveComponentIdentity = (component) => {
  return componentIdentityResolver?.(component) ?? component;
};
var setStackForControls = (controls, stack) => {
  if (stack === undefined) {
    stacksByControls.delete(controls);
    return;
  }
  stacksByControls.set(controls, stack);
};
var getStackForControls = (controls) => {
  return stacksByControls.get(controls) ?? null;
};
var getSingleChildComponent = (children) => {
  const mountedChildren = React3.Children.toArray(children);
  if (mountedChildren.length !== 1) {
    return null;
  }
  const child = mountedChildren[0];
  if (!React3.isValidElement(child)) {
    return null;
  }
  if (typeof child.type !== "function" && typeof child.type !== "object") {
    return null;
  }
  return resolveComponentIdentity(child.type);
};

// src/Folder.tsx
import { createContext as createContext5, useContext as useContext2, useEffect, useMemo } from "react";

// src/sequence-order-marker.tsx
var SEQUENCE_ORDER_MARKER = Symbol.for("remotion.sequence-order-marker");
var SEQUENCE_MANAGER_ORDER_MARKER = Symbol.for("remotion.sequence-manager-order-marker");
var COMPOSITION_ORDER_MARKER = Symbol.for("remotion.composition-order-marker");
var FOLDER_ORDER_MARKER = Symbol.for("remotion.folder-order-marker");
var COMPOSITION_MANAGER_ORDER_MARKER = Symbol.for("remotion.composition-manager-order-marker");
var COMMIT_ORDER_EVENT = "remotion:commit-order";
var getCompositionAndFolderOrderKey = (item) => `${item.type}:${item.id}`;
var getFolderOrderId = ({
  name,
  parent
}) => [parent, name].filter(Boolean).join("/");
var SequenceOrderMarker = ({ children }) => children;
Object.defineProperty(SequenceOrderMarker, SEQUENCE_ORDER_MARKER, {
  value: true
});
var SequenceManagerOrderMarker = ({ children }) => children;
Object.defineProperty(SequenceManagerOrderMarker, SEQUENCE_MANAGER_ORDER_MARKER, {
  value: true
});
var CompositionOrderMarker = ({ children }) => children;
Object.defineProperty(CompositionOrderMarker, COMPOSITION_ORDER_MARKER, {
  value: true
});
var FolderOrderMarker = ({ children }) => children;
Object.defineProperty(FolderOrderMarker, FOLDER_ORDER_MARKER, {
  value: true
});
var CompositionManagerOrderMarker = ({ children }) => children;
Object.defineProperty(CompositionManagerOrderMarker, COMPOSITION_MANAGER_ORDER_MARKER, { value: true });
var CommitOrderInternals = {
  compositionManagerMarker: COMPOSITION_MANAGER_ORDER_MARKER,
  compositionMarker: COMPOSITION_ORDER_MARKER,
  folderMarker: FOLDER_ORDER_MARKER,
  sequenceManagerMarker: SEQUENCE_MANAGER_ORDER_MARKER,
  sequenceMarker: SEQUENCE_ORDER_MARKER,
  eventName: COMMIT_ORDER_EVENT
};

// src/truthy.ts
function truthy(value) {
  return Boolean(value);
}

// src/use-remotion-environment.ts
import { useContext, useState } from "react";

// src/get-remotion-environment.ts
function getNodeEnvString() {
  return ["NOD", "E_EN", "V"].join("");
}
var getEnvString = () => {
  return ["e", "nv"].join("");
};
var getRemotionEnvironment = () => {
  const isPlayer = typeof window !== "undefined" && window.remotion_isPlayer;
  const isRendering = typeof window !== "undefined" && typeof window.process !== "undefined" && typeof window.process.env !== "undefined" && (window.process[getEnvString()][getNodeEnvString()] === "test" || window.process[getEnvString()][getNodeEnvString()] === "production" && typeof window !== "undefined" && typeof window.remotion_puppeteerTimeout !== "undefined");
  const isStudio = typeof window !== "undefined" && window.remotion_isStudio;
  const isReadOnlyStudio = typeof window !== "undefined" && window.remotion_isReadOnlyStudio;
  return {
    isStudio,
    isRendering,
    isPlayer,
    isReadOnlyStudio,
    isClientSideRendering: false
  };
};

// src/remotion-environment-context.ts
import React4 from "react";
var RemotionEnvironmentContext = React4.createContext(null);

// src/use-remotion-environment.ts
var useRemotionEnvironment = () => {
  const context = useContext(RemotionEnvironmentContext);
  const [env] = useState(() => getRemotionEnvironment());
  return context ?? env;
};

// src/validation/validate-folder-name.ts
var getRegex = () => /^([a-zA-Z0-9-\u4E00-\u9FFF])+$/g;
var isFolderNameValid = (name) => name.match(getRegex());
var validateFolderName = (name) => {
  if (name === undefined || name === null) {
    throw new TypeError("You must pass a name to a <Folder />.");
  }
  if (typeof name !== "string") {
    throw new TypeError(`The "name" you pass into <Folder /> must be a string. Got: ${typeof name}`);
  }
  if (!isFolderNameValid(name)) {
    throw new Error(`Folder name can only contain a-z, A-Z, 0-9 and -. You passed ${name}`);
  }
};
var invalidFolderNameErrorMessage = `Folder name must match ${String(getRegex())}`;

// src/Folder.tsx
import { jsx as jsx2 } from "react/jsx-runtime";
var FolderContext = createContext5({
  folderName: null,
  parentName: null
});
var Folder = (props) => {
  const { name, children } = props;
  const parent = useContext2(FolderContext);
  const { registerFolder, unregisterFolder } = useContext2(CompositionSetters);
  const environment = useRemotionEnvironment();
  const stack = props._remotionInternalStack ?? null;
  validateFolderName(name);
  const parentNameArr = [parent.parentName, parent.folderName].filter(truthy);
  const parentName = parentNameArr.length === 0 ? null : parentNameArr.join("/");
  const value = useMemo(() => {
    return {
      folderName: name,
      parentName
    };
  }, [name, parentName]);
  useEffect(() => {
    registerFolder(name, parentName, stack);
    return () => {
      unregisterFolder(name, parentName);
    };
  }, [
    name,
    parent.folderName,
    parentName,
    registerFolder,
    unregisterFolder,
    stack
  ]);
  const folder = /* @__PURE__ */ jsx2(FolderContext.Provider, {
    value,
    children
  });
  return environment.isStudio ? /* @__PURE__ */ jsx2(FolderOrderMarker, {
    folderId: getFolderOrderId({ name, parent: parentName }),
    children: folder
  }) : folder;
};

// src/input-props-serialization.ts
var DATE_TOKEN = "remotion-date:";
var FILE_TOKEN = "remotion-file:";
var serializeJSONWithSpecialTypes = ({
  data,
  indent,
  staticBase
}) => {
  let customDateUsed = false;
  let customFileUsed = false;
  let mapUsed = false;
  let setUsed = false;
  try {
    const serializedString = JSON.stringify(data, function(key, value) {
      const item = this[key];
      if (item instanceof Date) {
        customDateUsed = true;
        return `${DATE_TOKEN}${item.toISOString()}`;
      }
      if (item instanceof Map) {
        mapUsed = true;
        return value;
      }
      if (item instanceof Set) {
        setUsed = true;
        return value;
      }
      if (typeof item === "string" && staticBase !== null && staticBase !== "" && item.startsWith(staticBase)) {
        customFileUsed = true;
        return `${FILE_TOKEN}${item.replace(staticBase + "/", "")}`;
      }
      return value;
    }, indent);
    return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
  } catch (err) {
    throw new Error("Could not serialize the passed input props to JSON: " + err.message);
  }
};
var resolveFileTokenToUrl = (value) => {
  const encodedName = value.replace(FILE_TOKEN, "");
  let name = encodedName;
  try {
    name = encodedName.split("/").map(decodeURIComponent).join("/");
  } catch {}
  const matchingStaticFile = window.remotion_staticFiles?.find((file) => file.name === name);
  if (matchingStaticFile) {
    return matchingStaticFile.src;
  }
  return `${window.remotion_staticBase}/${encodedName}`;
};
var deserializeJSONWithSpecialTypes = (data) => {
  return JSON.parse(data, (_, value) => {
    if (typeof value === "string" && value.startsWith(DATE_TOKEN)) {
      return new Date(value.replace(DATE_TOKEN, ""));
    }
    if (typeof value === "string" && value.startsWith(FILE_TOKEN)) {
      return resolveFileTokenToUrl(value);
    }
    return value;
  });
};
var serializeThenDeserialize = (props) => {
  return deserializeJSONWithSpecialTypes(serializeJSONWithSpecialTypes({
    data: props,
    indent: 2,
    staticBase: window.remotion_staticBase
  }).serializedString);
};
var serializeThenDeserializeInStudio = (props) => {
  if (getRemotionEnvironment().isStudio) {
    return serializeThenDeserialize(props);
  }
  return props;
};

// src/is-player.tsx
import { createContext as createContext6, useContext as useContext3 } from "react";
import { jsx as jsx3 } from "react/jsx-runtime";
var IsPlayerContext = createContext6(false);
var IsPlayerContextProvider = ({
  children
}) => {
  return /* @__PURE__ */ jsx3(IsPlayerContext.Provider, {
    value: true,
    children
  });
};
var useIsPlayer = () => {
  return useContext3(IsPlayerContext);
};

// src/AbsoluteFillElement.tsx
import { forwardRef, useMemo as useMemo2 } from "react";
import { jsx as jsx4 } from "react/jsx-runtime";
var hasTailwindClassName = ({
  className,
  classPrefix,
  type
}) => {
  if (!className) {
    return false;
  }
  if (type === "exact") {
    const split = className.split(" ");
    return classPrefix.some((token) => {
      return split.some((part) => {
        return part.trim() === token || part.trim().endsWith(`:${token}`) || part.trim().endsWith(`!${token}`);
      });
    });
  }
  return classPrefix.some((prefix) => {
    return className.startsWith(prefix) || className.includes(` ${prefix}`) || className.includes(`!${prefix}`) || className.includes(`:${prefix}`);
  });
};
var AbsoluteFillElementRefForwarding = (props, ref) => {
  const { style, ...other } = props;
  const actualStyle = useMemo2(() => {
    return {
      position: "absolute",
      top: hasTailwindClassName({
        className: other.className,
        classPrefix: ["top-", "inset-"],
        type: "prefix"
      }) ? undefined : 0,
      left: hasTailwindClassName({
        className: other.className,
        classPrefix: ["left-", "inset-"],
        type: "prefix"
      }) ? undefined : 0,
      right: hasTailwindClassName({
        className: other.className,
        classPrefix: ["right-", "inset-"],
        type: "prefix"
      }) ? undefined : 0,
      bottom: hasTailwindClassName({
        className: other.className,
        classPrefix: ["bottom-", "inset-"],
        type: "prefix"
      }) ? undefined : 0,
      width: hasTailwindClassName({
        className: other.className,
        classPrefix: ["w-"],
        type: "prefix"
      }) ? undefined : "100%",
      height: hasTailwindClassName({
        className: other.className,
        classPrefix: ["h-"],
        type: "prefix"
      }) ? undefined : "100%",
      display: hasTailwindClassName({
        className: other.className,
        classPrefix: [
          "block",
          "inline-block",
          "inline",
          "flex",
          "inline-flex",
          "flow-root",
          "grid",
          "inline-grid",
          "contents",
          "list-item",
          "hidden"
        ],
        type: "exact"
      }) ? undefined : "flex",
      flexDirection: hasTailwindClassName({
        className: other.className,
        classPrefix: [
          "flex-row",
          "flex-col",
          "flex-row-reverse",
          "flex-col-reverse"
        ],
        type: "exact"
      }) ? undefined : "column",
      ...style
    };
  }, [other.className, style]);
  return /* @__PURE__ */ jsx4("div", {
    ref,
    style: actualStyle,
    ...other
  });
};
var AbsoluteFillElement = forwardRef(AbsoluteFillElementRefForwarding);

// src/use-current-scale.ts
import React7, { createContext as createContext10 } from "react";

// src/portal-node.ts
var _portalNode = null;
var portalNodeCurrentScale = 1;
var portalNodeCurrentScaleListeners = [];
var getPortalNodeCurrentScale = () => portalNodeCurrentScale;
var subscribeToPortalNodeCurrentScale = (listener) => {
  portalNodeCurrentScaleListeners.push(listener);
  return () => {
    portalNodeCurrentScaleListeners = portalNodeCurrentScaleListeners.filter((currentListener) => currentListener !== listener);
  };
};
var setPortalNodeCurrentScale = (scale) => {
  if (portalNodeCurrentScale === scale) {
    return;
  }
  portalNodeCurrentScale = scale;
  for (const listener of portalNodeCurrentScaleListeners) {
    listener();
  }
};
var portalNode = () => {
  if (!_portalNode) {
    if (typeof document === "undefined") {
      throw new Error("Tried to call an API that only works in the browser from outside the browser");
    }
    _portalNode = document.createElement("div");
    _portalNode.style.position = "absolute";
    _portalNode.style.top = "0px";
    _portalNode.style.left = "0px";
    _portalNode.style.right = "0px";
    _portalNode.style.bottom = "0px";
    _portalNode.style.width = "100%";
    _portalNode.style.height = "100%";
    _portalNode.style.display = "flex";
    _portalNode.style.flexDirection = "column";
    const containerNode = document.createElement("div");
    containerNode.style.position = "fixed";
    containerNode.style.top = -999999 + "px";
    containerNode.appendChild(_portalNode);
    document.body.appendChild(containerNode);
  }
  return _portalNode;
};

// src/use-unsafe-video-config.ts
import { useContext as useContext6, useMemo as useMemo6 } from "react";

// src/SequenceContext.tsx
import { createContext as createContext7 } from "react";
var SequenceContext = createContext7(null);

// src/use-video.ts
import { useContext as useContext5, useMemo as useMemo5 } from "react";

// src/ResolveCompositionConfig.tsx
import { createContext as createContext9, createRef, useContext as useContext4, useMemo as useMemo4 } from "react";

// src/input-props-override.ts
var getKey = () => {
  return `remotion_inputPropsOverride` + window.location.origin;
};
var getInputPropsOverride = () => {
  if (typeof localStorage === "undefined")
    return null;
  const override = localStorage.getItem(getKey());
  if (!override)
    return null;
  return JSON.parse(override);
};
var setInputPropsOverride = (override) => {
  if (typeof localStorage === "undefined")
    return;
  if (override === null) {
    localStorage.removeItem(getKey());
    return;
  }
  localStorage.setItem(getKey(), JSON.stringify(override));
};

// src/config/input-props.ts
var didWarnSSRImport = false;
var warnOnceSSRImport = () => {
  if (didWarnSSRImport) {
    return;
  }
  didWarnSSRImport = true;
  console.warn("Called `getInputProps()` on the server. This function is not available server-side and has returned an empty object.");
  console.warn("To hide this warning, don't call this function on the server:");
  console.warn("  typeof window === 'undefined' ? {} : getInputProps()");
};
var getInputProps = () => {
  if (typeof window === "undefined") {
    warnOnceSSRImport();
    return {};
  }
  if (getRemotionEnvironment().isPlayer) {
    throw new Error("You cannot call `getInputProps()` from a <Player>. Instead, the props are available as React props from component that you passed as `component` prop.");
  }
  const override = getInputPropsOverride();
  if (override) {
    return override;
  }
  if (typeof window === "undefined" || typeof window.remotion_inputProps === "undefined") {
    throw new Error("Cannot call `getInputProps()` - window.remotion_inputProps is not set. This API is only available if you are in the Studio, or while you are rendering server-side.");
  }
  const param = window.remotion_inputProps;
  if (!param) {
    return {};
  }
  const parsed = deserializeJSONWithSpecialTypes(param);
  return parsed;
};

// src/EditorProps.tsx
import React6, { createContext as createContext8, useCallback, useMemo as useMemo3 } from "react";
import { jsx as jsx5 } from "react/jsx-runtime";
var EditorPropsContext = createContext8({
  props: {},
  updateProps: () => {
    throw new Error("Not implemented");
  }
});
var timeValueRef = React6.createRef();
var EditorPropsProvider = ({ children }) => {
  const [props, setProps] = React6.useState({});
  const updateProps = useCallback(({
    defaultProps,
    id,
    newProps
  }) => {
    setProps((prev) => {
      return {
        ...prev,
        [id]: typeof newProps === "function" ? newProps(prev[id] ?? defaultProps) : newProps
      };
    });
  }, []);
  const ctx = useMemo3(() => {
    return { props, updateProps };
  }, [props, updateProps]);
  return /* @__PURE__ */ jsx5(EditorPropsContext.Provider, {
    value: ctx,
    children
  });
};

// src/validation/validate-dimensions.ts
function validateDimension(amount, nameOfProp, location) {
  if (typeof amount !== "number") {
    throw new Error(`The "${nameOfProp}" prop ${location} must be a number, but you passed a value of type ${typeof amount}`);
  }
  if (isNaN(amount)) {
    throw new TypeError(`The "${nameOfProp}" prop ${location} must not be NaN, but is NaN.`);
  }
  if (!Number.isFinite(amount)) {
    throw new TypeError(`The "${nameOfProp}" prop ${location} must be finite, but is ${amount}.`);
  }
  if (amount % 1 !== 0) {
    throw new TypeError(`The "${nameOfProp}" prop ${location} must be an integer, but is ${amount}.`);
  }
  if (amount <= 0) {
    throw new TypeError(`The "${nameOfProp}" prop ${location} must be positive, but got ${amount}.`);
  }
}

// src/validation/validate-duration-in-frames.ts
function validateDurationInFrames(durationInFrames, options) {
  const { allowFloats, component } = options;
  if (typeof durationInFrames === "undefined") {
    throw new Error(`The "durationInFrames" prop ${component} is missing.`);
  }
  if (typeof durationInFrames !== "number") {
    throw new Error(`The "durationInFrames" prop ${component} must be a number, but you passed a value of type ${typeof durationInFrames}`);
  }
  if (durationInFrames <= 0) {
    throw new TypeError(`The "durationInFrames" prop ${component} must be positive, but got ${durationInFrames}.`);
  }
  if (!allowFloats && durationInFrames % 1 !== 0) {
    throw new TypeError(`The "durationInFrames" prop ${component} must be an integer, but got ${durationInFrames}.`);
  }
  if (!Number.isFinite(durationInFrames)) {
    throw new TypeError(`The "durationInFrames" prop ${component} must be finite, but got ${durationInFrames}.`);
  }
}

// src/validation/validate-fps.ts
function validateFps(fps, location, isGif) {
  if (typeof fps !== "number") {
    throw new Error(`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`);
  }
  if (!Number.isFinite(fps)) {
    throw new Error(`"fps" must be a finite, but you passed ${fps} ${location}`);
  }
  if (isNaN(fps)) {
    throw new Error(`"fps" must not be NaN, but got ${fps} ${location}`);
  }
  if (fps <= 0) {
    throw new TypeError(`"fps" must be positive, but got ${fps} ${location}`);
  }
  if (isGif && fps > 50) {
    throw new TypeError(`The FPS for a GIF cannot be higher than 50. Use the --every-nth-frame option to lower the FPS: https://remotion.dev/docs/render-as-gif`);
  }
}

// src/ResolveCompositionConfig.tsx
var ResolveCompositionContext = createContext9(null);
var resolveCompositionsRef = createRef();
var needsResolution = (composition) => {
  return Boolean(composition.calculateMetadata);
};
var useResolvedVideoConfig = (preferredCompositionId) => {
  const context = useContext4(ResolveCompositionContext);
  const { props: allEditorProps } = useContext4(EditorPropsContext);
  const {
    compositions,
    canvasContent,
    currentCompositionMetadata,
    currentAssetMetadata
  } = useContext4(CompositionManager);
  const currentComposition = canvasContent?.type === "composition" ? canvasContent.compositionId : null;
  const compositionId = preferredCompositionId ?? currentComposition;
  const composition = compositions.find((c) => c.id === compositionId);
  const selectedEditorProps = useMemo4(() => {
    return composition ? allEditorProps[composition.id] ?? {} : {};
  }, [allEditorProps, composition]);
  const env = useRemotionEnvironment();
  return useMemo4(() => {
    if (preferredCompositionId === null && canvasContent?.type === "asset" && currentAssetMetadata?.asset === canvasContent.asset) {
      return {
        type: "success",
        metadataSource: null,
        result: {
          ...currentAssetMetadata,
          id: getAssetPreviewCompositionId(canvasContent.asset),
          defaultProps: {}
        }
      };
    }
    if (!composition) {
      return null;
    }
    if (currentCompositionMetadata) {
      return {
        type: "success",
        metadataSource: null,
        result: {
          ...currentCompositionMetadata,
          id: composition.id,
          defaultProps: composition.defaultProps ?? {}
        }
      };
    }
    if (!needsResolution(composition)) {
      validateDurationInFrames(composition.durationInFrames, {
        allowFloats: false,
        component: `in <Composition id="${composition.id}">`
      });
      validateFps(composition.fps, `in <Composition id="${composition.id}">`, false);
      validateDimension(composition.width, "width", `in <Composition id="${composition.id}">`);
      validateDimension(composition.height, "height", `in <Composition id="${composition.id}">`);
      return {
        type: "success",
        metadataSource: null,
        result: {
          width: composition.width,
          height: composition.height,
          fps: composition.fps,
          id: composition.id,
          durationInFrames: composition.durationInFrames,
          defaultProps: composition.defaultProps ?? {},
          props: {
            ...composition.defaultProps ?? {},
            ...selectedEditorProps ?? {},
            ...typeof window === "undefined" || env.isPlayer || !window.remotion_inputProps ? {} : getInputProps() ?? {}
          },
          defaultCodec: null,
          defaultOutName: null,
          defaultVideoImageFormat: null,
          defaultPixelFormat: null,
          defaultProResProfile: null,
          defaultSampleRate: null
        }
      };
    }
    if (!context) {
      return null;
    }
    if (!context[composition.id]) {
      return null;
    }
    return context[composition.id];
  }, [
    composition,
    canvasContent,
    context,
    currentAssetMetadata,
    currentCompositionMetadata,
    preferredCompositionId,
    selectedEditorProps,
    env.isPlayer
  ]);
};

// src/use-video.ts
var AssetPreviewComposition = () => null;
var useVideo = () => {
  const {
    canvasContent,
    compositions,
    currentCompositionMetadata,
    currentAssetMetadata
  } = useContext5(CompositionManager);
  const selected = compositions.find((c) => {
    return canvasContent?.type === "composition" && c.id === canvasContent.compositionId;
  });
  const resolved = useResolvedVideoConfig(selected?.id ?? null);
  return useMemo5(() => {
    if (canvasContent?.type === "asset" && currentAssetMetadata?.asset === canvasContent.asset) {
      return {
        ...currentAssetMetadata,
        id: getAssetPreviewCompositionId(canvasContent.asset),
        defaultProps: {},
        component: AssetPreviewComposition
      };
    }
    if (!resolved) {
      return null;
    }
    if (resolved.type === "error") {
      return null;
    }
    if (resolved.type === "loading") {
      return null;
    }
    if (!selected) {
      return null;
    }
    return {
      ...resolved.result,
      defaultProps: selected.defaultProps ?? {},
      id: selected.id,
      ...currentCompositionMetadata ?? {},
      component: selected.component
    };
  }, [
    canvasContent,
    currentAssetMetadata,
    currentCompositionMetadata,
    resolved,
    selected
  ]);
};

// src/use-unsafe-video-config.ts
var useUnsafeVideoConfig = () => {
  const context = useContext6(SequenceContext);
  const ctxWidth = context?.width ?? null;
  const ctxHeight = context?.height ?? null;
  const ctxDuration = context?.durationInFrames ?? null;
  const video = useVideo();
  return useMemo6(() => {
    if (!video) {
      return null;
    }
    const {
      id,
      durationInFrames,
      fps,
      height,
      width,
      defaultProps,
      props,
      defaultCodec,
      defaultOutName,
      defaultVideoImageFormat,
      defaultPixelFormat,
      defaultProResProfile,
      defaultSampleRate
    } = video;
    return {
      id,
      width: ctxWidth ?? width,
      height: ctxHeight ?? height,
      fps,
      durationInFrames: ctxDuration ?? durationInFrames,
      defaultProps,
      props,
      defaultCodec,
      defaultOutName,
      defaultVideoImageFormat,
      defaultPixelFormat,
      defaultProResProfile,
      defaultSampleRate
    };
  }, [ctxDuration, ctxHeight, ctxWidth, video]);
};

// src/use-current-scale.ts
var CurrentScaleContext = React7.createContext(null);
var PreviewSizeContext = createContext10({
  setSize: () => {
    return;
  },
  size: { size: "auto", translation: { x: 0, y: 0 } }
});
var calculateScale = ({
  canvasSize,
  compositionHeight,
  compositionWidth,
  previewSize
}) => {
  const heightRatio = canvasSize.height / compositionHeight;
  const widthRatio = canvasSize.width / compositionWidth;
  const ratio = Math.min(heightRatio, widthRatio);
  if (previewSize === "auto") {
    if (ratio === 0) {
      return 1;
    }
    return ratio;
  }
  return Number(previewSize);
};
var useCurrentScale = (options) => {
  const hasContext = React7.useContext(CurrentScaleContext);
  const zoomContext = React7.useContext(PreviewSizeContext);
  const config = useUnsafeVideoConfig();
  const env = useRemotionEnvironment();
  const [portalScale, setPortalScale] = React7.useState(getPortalNodeCurrentScale);
  React7.useEffect(() => {
    const update = () => setPortalScale(getPortalNodeCurrentScale());
    update();
    return subscribeToPortalNodeCurrentScale(update);
  }, []);
  if (hasContext === null || config === null || zoomContext === null) {
    if (options?.dontThrowIfOutsideOfRemotion) {
      return 1;
    }
    if (env.isRendering) {
      return 1;
    }
    throw new Error([
      "useCurrentScale() was called outside of a Remotion context.",
      "This hook can only be called in a component that is being rendered by Remotion.",
      "If you want to this hook to return 1 outside of Remotion, pass {dontThrowIfOutsideOfRemotion: true} as an option.",
      "If you think you called this hook in a Remotion component, make sure all versions of Remotion are aligned."
    ].join(`
`));
  }
  if (hasContext.type === "scale") {
    return hasContext.scale;
  }
  return portalScale;
};

// src/loading-indicator.tsx
import { jsx as jsx6, jsxs } from "react/jsx-runtime";
var rotate = {
  transform: `rotate(90deg)`
};
var ICON_SIZE = 40;
var LABEL_SIZE = 14;
var label = {
  color: "rgba(255, 255, 255, 0.8)",
  fontFamily: "sans-serif"
};
var container = {
  justifyContent: "center",
  alignItems: "center",
  backgroundColor: "#1f2428"
};
var content = {
  display: "flex",
  flexDirection: "column",
  alignItems: "center",
  animation: "anim 2s",
  animationFillMode: "forwards"
};
var Loading = () => {
  const scale = useCurrentScale({ dontThrowIfOutsideOfRemotion: true });
  return /* @__PURE__ */ jsxs(AbsoluteFillElement, {
    style: container,
    id: "remotion-comp-loading",
    children: [
      /* @__PURE__ */ jsx6("style", {
        type: "text/css",
        children: `
				@keyframes anim {
					from {
						opacity: 0
					}
					to {
						opacity: 1
					}
				}
			`
      }),
      /* @__PURE__ */ jsxs("div", {
        id: "remotion-comp-loading-content",
        style: content,
        children: [
          /* @__PURE__ */ jsx6("svg", {
            width: ICON_SIZE / scale,
            height: ICON_SIZE / scale,
            viewBox: "-100 -100 400 400",
            style: rotate,
            children: /* @__PURE__ */ jsx6("path", {
              fill: "#555",
              stroke: "#555",
              strokeWidth: "100",
              strokeLinejoin: "round",
              d: "M 2 172 a 196 100 0 0 0 195 5 A 196 240 0 0 0 100 2.259 A 196 240 0 0 0 2 172 z"
            })
          }),
          /* @__PURE__ */ jsxs("p", {
            style: { ...label, fontSize: LABEL_SIZE / scale },
            children: [
              "Resolving ",
              "<Suspense>",
              "..."
            ]
          })
        ]
      })
    ]
  });
};

// src/use-delay-render.tsx
import { createContext as createContext12, useCallback as useCallback2, useContext as useContext8 } from "react";

// src/cancel-render.ts
var getErrorStackWithMessage = (error) => {
  const stack = error.stack ?? "";
  return stack.startsWith("Error:") ? stack : `${error.message}
${stack}`;
};
var isErrorLike = (err) => {
  if (err instanceof Error) {
    return true;
  }
  if (err === null) {
    return false;
  }
  if (typeof err !== "object") {
    return false;
  }
  if (!("stack" in err)) {
    return false;
  }
  if (typeof err.stack !== "string") {
    return false;
  }
  if (!("message" in err)) {
    return false;
  }
  if (typeof err.message !== "string") {
    return false;
  }
  return true;
};
function cancelRenderInternal(scope, err) {
  let error;
  if (isErrorLike(err)) {
    error = err;
    if (!error.stack) {
      error.stack = new Error(error.message).stack;
    }
  } else if (typeof err === "string") {
    error = Error(err);
  } else {
    error = Error("Rendering was cancelled");
  }
  if (scope) {
    scope.remotion_cancelledError = getErrorStackWithMessage(error);
  }
  throw error;
}
function cancelRender(err) {
  return cancelRenderInternal(typeof window !== "undefined" ? window : undefined, err);
}

// src/delay-render-constants.ts
var DELAY_RENDER_CALLSTACK_TOKEN = "The delayRender was called:";
var DELAY_RENDER_RETRIES_LEFT = "Retries left: ";
var DELAY_RENDER_RETRY_TOKEN = "- Rendering the frame will be retried.";
var DELAY_RENDER_CLEAR_TOKEN = "handle was cleared after";

// src/log.ts
var logLevels = ["trace", "verbose", "info", "warn", "error"];
var getNumberForLogLevel = (level) => {
  return logLevels.indexOf(level);
};
var isEqualOrBelowLogLevel = (currentLevel, level) => {
  return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level);
};
var transformArgs = ({
  args,
  logLevel,
  tag
}) => {
  const arr = [...args];
  if (getRemotionEnvironment().isRendering && !getRemotionEnvironment().isClientSideRendering) {
    arr.unshift(Symbol.for(`__remotion_level_${logLevel}`));
  }
  if (tag && getRemotionEnvironment().isRendering && !getRemotionEnvironment().isClientSideRendering) {
    arr.unshift(Symbol.for(`__remotion_tag_${tag}`));
  }
  return arr;
};
var verbose = (options, ...args) => {
  if (isEqualOrBelowLogLevel(options.logLevel, "verbose")) {
    return console.debug(...transformArgs({ args, logLevel: "verbose", tag: options.tag }));
  }
};
var trace = (options, ...args) => {
  if (isEqualOrBelowLogLevel(options.logLevel, "trace")) {
    return console.debug(...transformArgs({ args, logLevel: "trace", tag: options.tag }));
  }
};
var info = (options, ...args) => {
  if (isEqualOrBelowLogLevel(options.logLevel, "info")) {
    return console.log(...transformArgs({ args, logLevel: "info", tag: options.tag }));
  }
};
var warn = (options, ...args) => {
  if (isEqualOrBelowLogLevel(options.logLevel, "warn")) {
    return console.warn(...transformArgs({ args, logLevel: "warn", tag: options.tag }));
  }
};
var error = (options, ...args) => {
  return console.error(...transformArgs({ args, logLevel: "error", tag: options.tag }));
};
var Log = {
  trace,
  verbose,
  info,
  warn,
  error
};

// src/delay-render.ts
if (typeof window !== "undefined") {
  window.remotion_renderReady = false;
  if (!window.remotion_delayRenderTimeouts) {
    window.remotion_delayRenderTimeouts = {};
  }
  window.remotion_delayRenderHandles = [];
}
var defaultTimeout = 30000;
var delayRenderInternal = ({
  scope,
  environment,
  label: label2,
  options
}) => {
  if (typeof label2 !== "string" && label2 !== null) {
    throw new Error("The label parameter of delayRender() must be a string or undefined, got: " + JSON.stringify(label2));
  }
  const handle = Math.random();
  scope.remotion_delayRenderHandles.push(handle);
  const called = Error().stack?.replace(/^Error/g, "") ?? "";
  if (environment.isRendering) {
    const timeoutToUse = (options?.timeoutInMilliseconds ?? scope.remotion_puppeteerTimeout ?? defaultTimeout) - 2000;
    const retriesLeft = (options?.retries ?? 0) - (scope.remotion_attempt - 1);
    scope.remotion_delayRenderTimeouts[handle] = {
      label: label2 ?? null,
      startTime: Date.now(),
      timeout: setTimeout(() => {
        const message = [
          `A delayRender()`,
          label2 ? `"${label2}"` : null,
          `was called but not cleared after ${timeoutToUse}ms. See https://remotion.dev/docs/timeout for help.`,
          retriesLeft > 0 ? DELAY_RENDER_RETRIES_LEFT + retriesLeft : null,
          retriesLeft > 0 ? DELAY_RENDER_RETRY_TOKEN : null,
          DELAY_RENDER_CALLSTACK_TOKEN,
          called
        ].filter(truthy).join(" ");
        if (environment.isClientSideRendering) {
          scope.remotion_cancelledError = getErrorStackWithMessage(Error(message));
        } else {
          cancelRenderInternal(scope, Error(message));
        }
      }, timeoutToUse)
    };
  }
  scope.remotion_renderReady = false;
  return handle;
};
var delayRender = (label2, options) => {
  if (typeof window === "undefined") {
    return Math.random();
  }
  return delayRenderInternal({
    scope: window,
    environment: getRemotionEnvironment(),
    label: label2 ?? null,
    options: options ?? {}
  });
};
var continueRenderInternal = ({
  scope,
  handle,
  environment,
  logLevel
}) => {
  if (typeof handle === "undefined") {
    throw new TypeError("The continueRender() method must be called with a parameter that is the return value of delayRender(). No value was passed.");
  }
  if (typeof handle !== "number") {
    throw new TypeError("The parameter passed into continueRender() must be the return value of delayRender() which is a number. Got: " + JSON.stringify(handle));
  }
  const handleExists = scope.remotion_delayRenderHandles.includes(handle);
  const timeoutEntry = scope.remotion_delayRenderTimeouts[handle];
  if (handleExists && environment.isRendering && timeoutEntry) {
    const { label: label2, startTime, timeout } = timeoutEntry;
    clearTimeout(timeout);
    const message = [
      label2 ? `"${label2}"` : "A handle",
      DELAY_RENDER_CLEAR_TOKEN,
      `${Date.now() - startTime}ms`
    ].filter(truthy).join(" ");
    Log.verbose({ logLevel, tag: "delayRender()" }, message);
    delete scope.remotion_delayRenderTimeouts[handle];
  }
  scope.remotion_delayRenderHandles = scope.remotion_delayRenderHandles.filter((h) => h !== handle);
  if (scope.remotion_delayRenderHandles.length === 0) {
    scope.remotion_renderReady = true;
  }
};
var continueRender = (handle) => {
  if (typeof window === "undefined") {
    return;
  }
  continueRenderInternal({
    scope: window,
    handle,
    environment: getRemotionEnvironment(),
    logLevel: window.remotion_logLevel ?? "info"
  });
};

// src/log-level-context.tsx
import { createContext as createContext11 } from "react";
import * as React8 from "react";
var LogLevelContext = createContext11({
  logLevel: "info",
  mountTime: 0
});
var useLogLevel = () => {
  const { logLevel } = React8.useContext(LogLevelContext);
  if (logLevel === null) {
    throw new Error("useLogLevel must be used within a LogLevelProvider");
  }
  return logLevel;
};
var useMountTime = () => {
  const { mountTime } = React8.useContext(LogLevelContext);
  if (mountTime === null) {
    throw new Error("useMountTime must be used within a LogLevelProvider");
  }
  return mountTime;
};

// src/use-delay-render.tsx
var DelayRenderContextType = createContext12(null);
var useDelayRender = () => {
  const environment = useRemotionEnvironment();
  const scope = useContext8(DelayRenderContextType) ?? (typeof window !== "undefined" ? window : undefined);
  const logLevel = useLogLevel();
  const delayRender2 = useCallback2((label2, options) => {
    if (!scope) {
      return Math.random();
    }
    return delayRenderInternal({
      scope,
      environment,
      label: label2 ?? null,
      options: options ?? {}
    });
  }, [environment, scope]);
  const continueRender2 = useCallback2((handle) => {
    if (!scope) {
      return;
    }
    continueRenderInternal({
      scope,
      handle,
      environment,
      logLevel
    });
  }, [environment, logLevel, scope]);
  const cancelRender2 = useCallback2((err) => {
    return cancelRenderInternal(scope ?? (typeof window !== "undefined" ? window : undefined), err);
  }, [scope]);
  return { delayRender: delayRender2, continueRender: continueRender2, cancelRender: cancelRender2 };
};

// src/use-lazy-component.ts
import React9, { useMemo as useMemo7, useRef } from "react";
var useLazyComponent = ({
  compProps,
  componentName,
  noSuspense
}) => {
  const componentRef = useRef(null);
  if ("component" in compProps) {
    componentRef.current = compProps.component;
  }
  const lazy = useMemo7(() => {
    if ("component" in compProps) {
      if (typeof document === "undefined" || noSuspense) {
        return compProps.component;
      }
      if (typeof compProps.component === "undefined") {
        throw new Error(`A value of \`undefined\` was passed to the \`component\` prop. Check the value you are passing to the <${componentName}/> component.`);
      }
      const Wrapper = (props) => {
        const Comp = componentRef.current;
        return React9.createElement(Comp, props);
      };
      return Wrapper;
    }
    if ("lazyComponent" in compProps && typeof compProps.lazyComponent !== "undefined") {
      if (typeof compProps.lazyComponent === "undefined") {
        throw new Error(`A value of \`undefined\` was passed to the \`lazyComponent\` prop. Check the value you are passing to the <${componentName}/> component.`);
      }
      return React9.lazy(compProps.lazyComponent);
    }
    throw new Error("You must pass either 'component' or 'lazyComponent'");
  }, [compProps.lazyComponent]);
  return lazy;
};

// src/validation/validate-composition-id.ts
var getRegex2 = () => /^([a-zA-Z0-9-\u4E00-\u9FFF])+$/g;
var isCompositionIdValid = (id) => id.match(getRegex2());
var validateCompositionId = (id) => {
  if (!isCompositionIdValid(id)) {
    throw new Error(`Composition id can only contain a-z, A-Z, 0-9, CJK characters and -. You passed ${id}`);
  }
};
var invalidCompositionErrorMessage = `Composition ID must match ${String(getRegex2())}`;

// src/validation/validate-default-props.ts
var validateDefaultAndInputProps = (defaultProps, name, compositionId) => {
  if (!defaultProps) {
    return;
  }
  if (typeof defaultProps !== "object") {
    throw new Error(`"${name}" must be an object, but you passed a value of type ${typeof defaultProps}`);
  }
  if (Array.isArray(defaultProps)) {
    throw new Error(`"${name}" must be an object, an array was passed ${compositionId ? `for composition "${compositionId}"` : ""}`);
  }
};

// src/Composition.tsx
import { jsx as jsx7 } from "react/jsx-runtime";
var Fallback = () => {
  const { continueRender: continueRender2, delayRender: delayRender2 } = useDelayRender();
  useEffect2(() => {
    const fallback = delayRender2("Waiting for Root component to unsuspend");
    return () => continueRender2(fallback);
  }, [continueRender2, delayRender2]);
  return null;
};
var InnerComposition = ({
  width,
  height,
  fps,
  durationInFrames,
  id,
  defaultProps,
  schema,
  ...compProps
}) => {
  const compManager = useContext9(CompositionSetters);
  const { registerComposition, unregisterComposition } = compManager;
  const video = useVideo();
  const lazy = useLazyComponent({
    compProps,
    componentName: "Composition",
    noSuspense: false
  });
  const isPlayer = useIsPlayer();
  const environment = useRemotionEnvironment();
  const canUseComposition = useContext9(CanUseRemotionHooks);
  if (typeof window !== "undefined") {
    window.remotion_seenCompositionIds = Array.from(new Set([...window.remotion_seenCompositionIds ?? [], id]));
  }
  if (canUseComposition) {
    if (isPlayer) {
      throw new Error("<Composition> was mounted inside the `component` that was passed to the <Player>. See https://remotion.dev/docs/wrong-composition-mount for help.");
    }
    throw new Error("<Composition> mounted inside another composition. See https://remotion.dev/docs/wrong-composition-mount for help.");
  }
  const { folderName, parentName } = useContext9(FolderContext);
  const stack = compProps._remotionInternalStack ?? null;
  const componentFromProps = "component" in compProps ? resolveComponentIdentity(compProps.component) : null;
  useEffect2(() => {
    if (!id) {
      throw new Error("No id for composition passed.");
    }
    validateCompositionId(id);
    validateDefaultAndInputProps(defaultProps, "defaultProps", id);
    registerComposition({
      durationInFrames: durationInFrames ?? undefined,
      fps: fps ?? undefined,
      height: height ?? undefined,
      width: width ?? undefined,
      id,
      folderName,
      component: lazy,
      defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}),
      order: null,
      parentFolderName: parentName,
      componentFromProps,
      schema: schema ?? null,
      calculateMetadata: compProps.calculateMetadata ?? null,
      stack
    });
    return () => {
      unregisterComposition(id);
    };
  }, [
    durationInFrames,
    fps,
    height,
    lazy,
    id,
    folderName,
    defaultProps,
    width,
    parentName,
    componentFromProps,
    schema,
    compProps.calculateMetadata,
    stack,
    registerComposition,
    unregisterComposition
  ]);
  const resolved = useResolvedVideoConfig(id);
  const { setError, clearError } = useContext9(CompositionRenderErrorContext);
  const onError = useCallback3((error2) => {
    setError(error2);
  }, [setError]);
  const onClear = useCallback3(() => {
    clearError();
  }, [clearError]);
  if (environment.isStudio && video && video.component === lazy && video.id === id) {
    const Comp = lazy;
    if (resolved === null || resolved.type !== "success" && resolved.type !== "success-and-refreshing") {
      return null;
    }
    return createPortal(/* @__PURE__ */ jsx7(CanUseRemotionHooksProvider, {
      children: /* @__PURE__ */ jsx7(CompositionErrorBoundary, {
        onError,
        onClear,
        children: /* @__PURE__ */ jsx7(Suspense, {
          fallback: /* @__PURE__ */ jsx7(Loading, {}),
          children: /* @__PURE__ */ jsx7(Comp, {
            ...resolved.result.props ?? {}
          })
        })
      })
    }), portalNode());
  }
  if (environment.isRendering && video && video.component === lazy && video.id === id) {
    const Comp = lazy;
    if (resolved === null || resolved.type !== "success" && resolved.type !== "success-and-refreshing") {
      return null;
    }
    return createPortal(/* @__PURE__ */ jsx7(CanUseRemotionHooksProvider, {
      children: /* @__PURE__ */ jsx7(Suspense, {
        fallback: /* @__PURE__ */ jsx7(Fallback, {}),
        children: /* @__PURE__ */ jsx7(Comp, {
          ...resolved.result.props ?? {}
        })
      })
    }), portalNode());
  }
  return null;
};
var Composition = (props) => {
  const { onlyRenderComposition } = useContext9(CompositionSetters);
  const environment = useRemotionEnvironment();
  if (onlyRenderComposition && onlyRenderComposition !== props.id) {
    return null;
  }
  const composition = /* @__PURE__ */ jsx7(InnerComposition, {
    ...props
  });
  return environment.isStudio ? /* @__PURE__ */ jsx7(CompositionOrderMarker, {
    compositionId: props.id,
    children: composition
  }) : composition;
};

// src/version.ts
var VERSION = "4.0.525";

// src/multiple-versions-warning.ts
var checkMultipleRemotionVersions = () => {
  if (typeof globalThis === "undefined") {
    return;
  }
  const set = () => {
    globalThis.remotion_imported = VERSION;
    if (typeof window !== "undefined") {
      window.remotion_imported = VERSION;
    }
  };
  const alreadyImported = globalThis.remotion_imported || typeof window !== "undefined" && window.remotion_imported;
  if (alreadyImported) {
    if (alreadyImported === VERSION) {
      return;
    }
    if (typeof alreadyImported === "string" && alreadyImported.includes("webcodecs")) {
      set();
      return;
    }
    throw new TypeError(`\uD83D\uDEA8 Multiple versions of Remotion detected: ${[
      VERSION,
      typeof alreadyImported === "string" ? alreadyImported : "an older version"
    ].filter(truthy).join(" and ")}. This will cause things to break in an unexpected way.
Check that all your Remotion packages are on the same version. If your dependencies depend on Remotion, make them peer dependencies. You can also run \`npx remotion versions\` from your terminal to see which versions are mismatching.`);
  }
  set();
};

// src/Null.tsx
var Null = () => {
  throw new Error("<Null> has been removed as of Remotion v4.0.228. The native clipping APIs were experimental and subject to removal at any time. We removed them because they were sparingly used and made rendering often slower rather than faster.");
};

// src/Sequence.tsx
import {
  forwardRef as forwardRef3,
  useCallback as useCallback6,
  useContext as useContext20,
  useMemo as useMemo13,
  useRef as useRef6,
  useState as useState6
} from "react";

// src/freeze.tsx
import { useContext as useContext15, useMemo as useMemo9 } from "react";

// src/timeline-position-state.ts
var exports_timeline_position_state = {};
__export(exports_timeline_position_state, {
  useTimelineSetFrame: () => useTimelineSetFrame,
  useTimelinePosition: () => useTimelinePosition,
  useTimelineContext: () => useTimelineContext,
  usePlaying: () => usePlaying,
  usePlaybackRate: () => usePlaybackRate,
  useIsInsideFreeze: () => useIsInsideFreeze,
  useBuffering: () => useBuffering,
  useAbsoluteTimelinePosition: () => useAbsoluteTimelinePosition,
  persistCurrentFrame: () => persistCurrentFrame,
  getInitialFrameState: () => getInitialFrameState,
  getFrameForComposition: () => getFrameForComposition,
  clampFrameToCompositionRange: () => clampFrameToCompositionRange
});
import { useContext as useContext12 } from "react";

// src/TimelineContext.tsx
import {
  createContext as createContext13,
  useCallback as useCallback4,
  useLayoutEffect,
  useMemo as useMemo8,
  useRef as useRef2,
  useState as useState2
} from "react";

// src/runtime-value-store.ts
var createRuntimeValueStore = (initialSnapshot) => {
  let snapshot = initialSnapshot;
  const listeners = new Set;
  const store = {
    getSnapshot: () => snapshot,
    subscribe: (listener) => {
      listeners.add(listener);
      return () => {
        listeners.delete(listener);
      };
    }
  };
  return {
    store,
    setSnapshot: (newSnapshot) => {
      if (snapshot === newSnapshot) {
        return;
      }
      snapshot = newSnapshot;
      for (const listener of listeners) {
        listener(snapshot);
      }
    }
  };
};

// src/TimelineContext.tsx
import { jsx as jsx8 } from "react/jsx-runtime";
var missingSetTimelineContext = () => {
  throw new Error("SetTimelineContext is missing. This is likely caused by a Remotion version mismatch.");
};
var SetTimelineContext = createContext13({
  setFrame: missingSetTimelineContext,
  setPlaying: missingSetTimelineContext,
  setBuffering: missingSetTimelineContext,
  subscribePlaying: () => () => {
    return;
  },
  subscribeBuffering: () => () => {
    return;
  },
  isPlaying: () => false,
  isBuffering: missingSetTimelineContext,
  frameRef: { current: {} },
  audioAndVideoTags: { current: [] }
});
var TimelineContext = createContext13(null);
var PlaybackRateContext = createContext13(null);
var AbsoluteTimeContext = createContext13(null);
var TimelineContextProvider = ({ children, frameState }) => {
  const playingStore = useMemo8(() => createRuntimeValueStore({ playing: false }), []);
  const bufferingStore = useMemo8(() => createRuntimeValueStore({ buffering: false }), []);
  const [playbackRate, setPlaybackRate] = useState2(1);
  const audioAndVideoTags = useRef2([]);
  const [_frame, setFrame] = useState2(() => getInitialFrameState());
  const frame = frameState ?? _frame;
  const frameRef = useRef2(frame);
  frameRef.current = frame;
  const readIsPlaying = useCallback4(() => playingStore.store.getSnapshot().playing, [playingStore]);
  const readIsBuffering = useCallback4(() => bufferingStore.store.getSnapshot().buffering, [bufferingStore]);
  const { delayRender: delayRender2, continueRender: continueRender2 } = useDelayRender();
  if (typeof window !== "undefined") {
    useLayoutEffect(() => {
      window.remotion_setFrame = (f, composition, attempt) => {
        window.remotion_attempt = attempt;
        const id = delayRender2(`Setting the current frame to ${f}`);
        let asyncUpdate = true;
        setFrame((s) => {
          const currentFrame = s[composition] ?? window.remotion_initialFrame;
          if (currentFrame === f) {
            asyncUpdate = false;
            return s;
          }
          return {
            ...s,
            [composition]: f
          };
        });
        if (asyncUpdate) {
          requestAnimationFrame(() => continueRender2(id));
        } else {
          continueRender2(id);
        }
      };
      window.remotion_isPlayer = false;
    }, [continueRender2, delayRender2]);
  }
  const timelineContextValue = useMemo8(() => {
    return {
      frame,
      isPlaying: readIsPlaying,
      isInsideFreeze: false,
      audioAndVideoTags
    };
  }, [frame, readIsPlaying]);
  const playbackRateContextValue = useMemo8(() => {
    return {
      playbackRate,
      setPlaybackRate
    };
  }, [playbackRate]);
  const setTimelineContextValue = useMemo8(() => {
    return {
      setFrame,
      setPlaying: (updater) => {
        const current = playingStore.store.getSnapshot().playing;
        const next = typeof updater === "function" ? updater(current) : updater;
        if (current !== next) {
          playingStore.setSnapshot({ playing: next });
        }
      },
      setBuffering: (buffering) => {
        if (readIsBuffering() !== buffering) {
          bufferingStore.setSnapshot({ buffering });
        }
      },
      subscribePlaying: playingStore.store.subscribe,
      subscribeBuffering: bufferingStore.store.subscribe,
      isPlaying: readIsPlaying,
      isBuffering: readIsBuffering,
      frameRef,
      audioAndVideoTags
    };
  }, [bufferingStore, playingStore, readIsBuffering, readIsPlaying]);
  return /* @__PURE__ */ jsx8(AbsoluteTimeContext.Provider, {
    value: timelineContextValue,
    children: /* @__PURE__ */ jsx8(PlaybackRateContext.Provider, {
      value: playbackRateContextValue,
      children: /* @__PURE__ */ jsx8(TimelineContext.Provider, {
        value: timelineContextValue,
        children: /* @__PURE__ */ jsx8(SetTimelineContext.Provider, {
          value: setTimelineContextValue,
          children
        })
      })
    })
  });
};

// src/use-playing.ts
import { useContext as useContext10 } from "react";

// src/use-sync-external-store.ts
import * as React12 from "react";
var objectIs = typeof Object.is === "function" ? Object.is : (first, second) => first === second && (first !== 0 || 1 / first === 1 / second) || Number.isNaN(first) && Number.isNaN(second);
var checkIfSnapshotChanged = (instance) => {
  try {
    return !objectIs(instance.value, instance.getSnapshot());
  } catch {
    return true;
  }
};
var useSyncExternalStoreShimClient = (subscribe, getSnapshot) => {
  const value = getSnapshot();
  if (false) {}
  const [{ instance }, forceUpdate] = React12.useState({
    instance: { value, getSnapshot }
  });
  React12.useLayoutEffect(() => {
    instance.value = value;
    instance.getSnapshot = getSnapshot;
    if (checkIfSnapshotChanged(instance)) {
      forceUpdate({ instance });
    }
  }, [getSnapshot, instance, subscribe, value]);
  React12.useEffect(() => {
    if (checkIfSnapshotChanged(instance)) {
      forceUpdate({ instance });
    }
    return subscribe(() => {
      if (checkIfSnapshotChanged(instance)) {
        forceUpdate({ instance });
      }
    });
  }, [instance, subscribe]);
  React12.useDebugValue(value);
  return value;
};
var useSyncExternalStoreShimServer = (_subscribe, getSnapshot) => getSnapshot();
var shim = typeof window === "undefined" || typeof window.document === "undefined" || typeof window.document.createElement === "undefined" ? useSyncExternalStoreShimServer : useSyncExternalStoreShimClient;
var useSyncExternalStore2 = React12.useSyncExternalStore ?? shim;

// src/use-playing.ts
var usePlaying = () => {
  const { isPlaying } = useTimelineContext();
  const { subscribePlaying } = useContext10(SetTimelineContext);
  return useSyncExternalStore2(subscribePlaying, isPlaying, isPlaying);
};
// src/use-buffering.ts
import { useContext as useContext11 } from "react";
var useBuffering = () => {
  const { isBuffering, subscribeBuffering } = useContext11(SetTimelineContext);
  return useSyncExternalStore2(subscribeBuffering, isBuffering, isBuffering);
};

// src/timeline-position-state.ts
var makeKey = () => {
  return `remotion.time-all`;
};
var persistCurrentFrame = (time) => {
  localStorage.setItem(makeKey(), JSON.stringify(time));
};
var getInitialFrameState = () => {
  const item = localStorage.getItem(makeKey()) ?? "{}";
  const obj = JSON.parse(item);
  return obj;
};
var getFrameForComposition = (composition) => {
  const item = localStorage.getItem(makeKey()) ?? "{}";
  const obj = JSON.parse(item);
  if (obj[composition] !== undefined) {
    return Number(obj[composition]);
  }
  if (typeof window === "undefined") {
    return 0;
  }
  return window.remotion_initialFrame ?? 0;
};
var clampFrameToCompositionRange = (frame, durationInFrames) => {
  return Math.max(0, Math.min(Math.max(0, durationInFrames - 1), frame));
};
var useTimelinePositionFromContext = (state) => {
  const videoConfig = useVideo();
  const env = useRemotionEnvironment();
  if (!videoConfig) {
    return typeof window === "undefined" ? 0 : window.remotion_initialFrame ?? 0;
  }
  const unclamped = state.frame[videoConfig.id] ?? (env.isPlayer ? 0 : getFrameForComposition(videoConfig.id));
  return clampFrameToCompositionRange(unclamped, videoConfig.durationInFrames);
};
var useTimelineContext = () => {
  const state = useContext12(TimelineContext);
  if (state === null) {
    throw new Error("TimelineContext is not available. This hook must be used inside a <Player> or the Remotion Studio.");
  }
  return state;
};
var usePlaybackRate = () => {
  const state = useContext12(PlaybackRateContext);
  if (state === null) {
    throw new Error("PlaybackRateContext is not available. This hook must be used inside a <Player> or the Remotion Studio.");
  }
  return state;
};
var useTimelinePosition = () => {
  const state = useTimelineContext();
  return useTimelinePositionFromContext(state);
};
var useIsInsideFreeze = () => {
  return useTimelineContext().isInsideFreeze;
};
var useAbsoluteTimelinePosition = () => {
  const state = useContext12(AbsoluteTimeContext);
  if (state === null) {
    throw new Error("AbsoluteTimeContext is not available. This hook must be used inside a <Player> or the Remotion Studio.");
  }
  return useTimelinePositionFromContext(state);
};
var useTimelineSetFrame = () => {
  const { setFrame } = useContext12(SetTimelineContext);
  return setFrame;
};

// src/use-current-frame.ts
import { useContext as useContext13 } from "react";
var useCurrentFrame = () => {
  const canUseRemotionHooks = useContext13(CanUseRemotionHooks);
  const env = useRemotionEnvironment();
  if (!canUseRemotionHooks) {
    if (env.isPlayer) {
      throw new Error(`useCurrentFrame can only be called inside a component that was passed to <Player>. See: https://www.remotion.dev/docs/player/examples`);
    }
    throw new Error(`useCurrentFrame() can only be called inside a component that was registered as a composition. See https://www.remotion.dev/docs/the-fundamentals#defining-compositions`);
  }
  const frame = useTimelinePosition();
  const context = useContext13(SequenceContext);
  const contextOffset = context ? context.cumulatedFrom + context.relativeFrom : 0;
  return frame - contextOffset;
};

// src/use-video-config.ts
import { useContext as useContext14 } from "react";
var useVideoConfig = () => {
  const videoConfig = useUnsafeVideoConfig();
  const context = useContext14(CanUseRemotionHooks);
  const isPlayer = useIsPlayer();
  if (!videoConfig) {
    if (typeof window !== "undefined" && window.remotion_isPlayer || isPlayer) {
      throw new Error([
        "No video config found. Likely reasons:",
        "- You are probably calling useVideoConfig() from outside the component passed to <Player />. See https://www.remotion.dev/docs/player/examples for how to set up the Player correctly.",
        "- You have multiple versions of Remotion installed which causes the React context to get lost."
      ].join("-"));
    }
    throw new Error("No video config found. You are probably calling useVideoConfig() from a component which has not been registered as a <Composition />. See https://www.remotion.dev/docs/the-fundamentals#defining-compositions for more information.");
  }
  if (!context) {
    throw new Error("Called useVideoConfig() outside a Remotion composition.");
  }
  return videoConfig;
};

// src/freeze.tsx
import { jsx as jsx9 } from "react/jsx-runtime";
var Freeze = ({
  frame: frameToFreeze,
  children,
  active = true
}) => {
  const frame = useCurrentFrame();
  const videoConfig = useVideoConfig();
  if (typeof frameToFreeze === "undefined") {
    throw new Error(`The <Freeze /> component requires a 'frame' prop, but none was passed.`);
  }
  if (typeof frameToFreeze !== "number") {
    throw new Error(`The 'frame' prop of <Freeze /> must be a number, but is of type ${typeof frameToFreeze}`);
  }
  if (Number.isNaN(frameToFreeze)) {
    throw new Error(`The 'frame' prop of <Freeze /> must be a real number, but it is NaN.`);
  }
  if (!Number.isFinite(frameToFreeze)) {
    throw new Error(`The 'frame' prop of <Freeze /> must be a finite number, but it is ${frameToFreeze}.`);
  }
  const isActive = useMemo9(() => {
    if (typeof active === "boolean") {
      return active;
    }
    if (typeof active === "function") {
      return active(frame);
    }
  }, [active, frame]);
  const timelineContext = useTimelineContext();
  const sequenceContext = useContext15(SequenceContext);
  const relativeFrom = sequenceContext?.relativeFrom ?? 0;
  const timelineValue = useMemo9(() => {
    if (!isActive) {
      return timelineContext;
    }
    return {
      ...timelineContext,
      isPlaying: () => false,
      isInsideFreeze: true,
      frame: {
        [videoConfig.id]: frameToFreeze + relativeFrom
      }
    };
  }, [isActive, timelineContext, videoConfig.id, frameToFreeze, relativeFrom]);
  const newSequenceContext = useMemo9(() => {
    if (!sequenceContext) {
      return null;
    }
    if (!isActive) {
      return sequenceContext;
    }
    return {
      ...sequenceContext,
      cumulatedFrom: 0
    };
  }, [sequenceContext, isActive]);
  return /* @__PURE__ */ jsx9(TimelineContext.Provider, {
    value: timelineValue,
    children: /* @__PURE__ */ jsx9(SequenceContext.Provider, {
      value: newSequenceContext,
      children
    })
  });
};

// src/interactivity-schema.ts
var captionsSchema = {
  captions: {
    type: "remotion-captions",
    default: undefined,
    description: "Captions",
    keyframable: false
  }
};
var transformSchema = {
  "style.transformOrigin": {
    type: "transform-origin",
    step: 1,
    default: "50% 50%",
    description: "Transform origin"
  },
  "style.translate": {
    type: "translate",
    step: 1,
    default: "0px 0px",
    description: "Offset"
  },
  "style.scale": {
    type: "scale",
    max: 100,
    step: 0.01,
    default: 1,
    description: "Scale",
    defaultKeyframeOutput: "perceptual-scale"
  },
  "style.rotate": {
    type: "rotation-css",
    step: 1,
    default: "0deg",
    description: "Rotation"
  },
  "style.opacity": {
    type: "number",
    min: 0,
    max: 1,
    step: 0.01,
    default: 1,
    description: "Opacity",
    hiddenFromList: false
  }
};
var sequenceVisualStyleSchema = transformSchema;
var textSchema = {
  "style.color": {
    type: "color",
    default: undefined,
    description: "Color"
  },
  "style.fontFamily": {
    type: "font-family",
    default: undefined,
    description: "Font family",
    keyframable: false
  },
  "style.fontSize": {
    type: "number",
    default: undefined,
    min: 0,
    step: 1,
    description: "Font size",
    hiddenFromList: false
  },
  "style.lineHeight": {
    type: "number",
    default: undefined,
    min: 0,
    step: 0.05,
    description: "Line height",
    hiddenFromList: false
  },
  "style.fontWeight": {
    type: "font-weight",
    default: 400,
    description: "Font weight",
    keyframable: false
  },
  "style.fontStyle": {
    type: "enum",
    default: "normal",
    description: "Font style",
    variants: {
      normal: {},
      italic: {},
      oblique: {}
    }
  },
  "style.textAlign": {
    type: "enum",
    default: "left",
    description: "Text align",
    variants: {
      left: {},
      center: {},
      right: {},
      justify: {},
      start: {},
      end: {}
    }
  },
  "style.letterSpacing": {
    type: "number",
    default: undefined,
    step: 0.1,
    description: "Letter spacing",
    hiddenFromList: false
  }
};
var borderSchema = {
  "style.borderWidth": {
    type: "number",
    default: undefined,
    min: 0,
    step: 1,
    description: "Border width",
    hiddenFromList: false
  },
  "style.borderStyle": {
    type: "enum",
    default: "none",
    description: "Border style",
    variants: {
      none: {},
      hidden: {},
      solid: {},
      dashed: {},
      dotted: {},
      double: {},
      groove: {},
      ridge: {},
      inset: {},
      outset: {}
    }
  },
  "style.borderColor": {
    type: "color",
    default: undefined,
    description: "Border color"
  }
};
var borderRadiusSchema = {
  "style.borderRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Border radius",
    hiddenFromList: false,
    keyframable: true
  },
  "style.borderTopLeftRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Top left radius",
    hiddenFromList: false
  },
  "style.borderTopRightRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Top right radius",
    hiddenFromList: false
  },
  "style.borderBottomRightRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Bottom right radius",
    hiddenFromList: false
  },
  "style.borderBottomLeftRadius": {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    description: "Bottom left radius",
    hiddenFromList: false
  }
};
var backgroundSchema = {
  "style.backgroundColor": {
    type: "color",
    default: "transparent",
    description: "Color"
  }
};
var svgColorSchema = {
  color: {
    type: "color",
    default: undefined,
    description: "Current color"
  }
};
var svgStrokeSchema = {
  ...svgColorSchema,
  stroke: {
    type: "color",
    default: "none",
    description: "Stroke"
  },
  strokeWidth: {
    type: "number",
    default: 1,
    description: "Stroke width",
    min: 0,
    step: 1,
    hiddenFromList: false
  }
};
var svgPaintSchema = {
  fill: {
    type: "color",
    default: undefined,
    description: "Fill"
  },
  ...svgStrokeSchema
};
var textContentSchema = {
  children: {
    type: "text-content",
    default: "",
    description: "Text",
    keyframable: false
  }
};
var premountSchema = {
  premountFor: {
    type: "number",
    default: 0,
    description: "Premount For",
    min: 0,
    step: 1,
    hiddenFromList: false,
    keyframable: false
  },
  postmountFor: {
    type: "number",
    default: 0,
    min: 0,
    step: 1,
    hiddenFromList: true,
    keyframable: false
  }
};
var sequencePremountSchema = {
  ...premountSchema
};
var cropSchema = {
  cropLeft: {
    type: "number",
    default: 0,
    description: "Crop left",
    min: 0,
    max: 1,
    step: 0.01,
    hiddenFromList: false,
    keyframable: true
  },
  cropRight: {
    type: "number",
    default: 0,
    description: "Crop right",
    min: 0,
    max: 1,
    step: 0.01,
    hiddenFromList: false,
    keyframable: true
  },
  cropTop: {
    type: "number",
    default: 0,
    description: "Crop top",
    min: 0,
    max: 1,
    step: 0.01,
    hiddenFromList: false,
    keyframable: true
  },
  cropBottom: {
    type: "number",
    default: 0,
    description: "Crop bottom",
    min: 0,
    max: 1,
    step: 0.01,
    hiddenFromList: false,
    keyframable: true
  }
};
var sequenceCropSchema = cropSchema;
var sequenceStyleSchema = {
  ...sequenceCropSchema,
  ...transformSchema,
  ...backgroundSchema,
  ...borderSchema,
  ...borderRadiusSchema,
  ...sequencePremountSchema
};
var hiddenField = {
  type: "boolean",
  default: false,
  description: "Hidden"
};
var showInTimelineField = {
  type: "hidden"
};
var sequenceNameField = {
  type: "hidden"
};
var extendSchemaWithSequenceName = (schema) => {
  return {
    name: sequenceNameField,
    ...schema
  };
};
var durationInFramesField = {
  type: "number",
  default: undefined,
  min: 1,
  step: 1,
  hiddenFromList: true
};
var fromField = {
  type: "number",
  default: 0,
  step: 1,
  hiddenFromList: true
};
var trimBeforeField = {
  type: "number",
  default: 0,
  min: 0,
  step: 1,
  hiddenFromList: true
};
var freezeField = {
  type: "number",
  default: null,
  step: 1,
  hiddenFromList: true
};
var baseSchema = {
  durationInFrames: durationInFramesField,
  from: fromField,
  trimBefore: trimBeforeField,
  freeze: freezeField,
  hidden: hiddenField,
  name: sequenceNameField,
  showInTimeline: showInTimelineField
};
var sequenceSchema = {
  ...baseSchema,
  layout: {
    type: "enum",
    default: "absolute-fill",
    description: "Layout",
    variants: {
      "absolute-fill": sequenceStyleSchema,
      none: {}
    }
  }
};
var baseSchemaWithoutFrom = {
  durationInFrames: durationInFramesField,
  trimBefore: trimBeforeField,
  freeze: freezeField,
  hidden: hiddenField,
  name: sequenceNameField,
  showInTimeline: showInTimelineField
};
var sequenceSchemaWithoutFrom = {
  ...baseSchemaWithoutFrom,
  layout: sequenceSchema.layout
};
var sequenceSchemaDefaultLayoutNone = {
  ...sequenceSchema,
  layout: {
    ...sequenceSchema.layout,
    default: "none"
  }
};

// src/sequence-crop.ts
var clampCrop = (value) => {
  return Math.min(1, Math.max(0, value ?? 0));
};
var resolveAxis = (start, end) => {
  const resolvedStart = clampCrop(start);
  const resolvedEnd = clampCrop(end);
  if (resolvedStart + resolvedEnd > 1) {
    return [0.5, 0.5];
  }
  return [resolvedStart, resolvedEnd];
};
var resolveSequenceCrop = ({
  cropLeft,
  cropRight,
  cropTop,
  cropBottom
}) => {
  const [left, right] = resolveAxis(cropLeft, cropRight);
  const [top, bottom] = resolveAxis(cropTop, cropBottom);
  return { left, right, top, bottom };
};
var getSequenceCropClipPath = ({
  left,
  right,
  top,
  bottom,
  style
}) => {
  if (left === 0 && right === 0 && top === 0 && bottom === 0) {
    return null;
  }
  const serializeRadius = (radius) => typeof radius === "number" ? `${radius}px` : radius;
  const shorthand = serializeRadius(style?.borderRadius);
  const longhands = [
    style?.borderTopLeftRadius,
    style?.borderTopRightRadius,
    style?.borderBottomRightRadius,
    style?.borderBottomLeftRadius
  ];
  const serializedBorderRadius = shorthand || (longhands.some((radius) => radius !== undefined) ? longhands.map((radius) => serializeRadius(radius) ?? "0px").join(" ") : undefined);
  const rounded = serializedBorderRadius ? ` round ${serializedBorderRadius}` : "";
  return `inset(${top * 100}% ${right * 100}% ${bottom * 100}% ${left * 100}%${rounded})`;
};
var validateSequenceCrop = (crop, componentName = "<Sequence />") => {
  for (const [name, value] of Object.entries(crop)) {
    if (value === undefined) {
      continue;
    }
    if (typeof value !== "number" || !Number.isFinite(value)) {
      throw new TypeError(`The "${name}" prop of ${componentName} must be a finite number, but got ${String(value)}.`);
    }
    if (value > 100) {
      throw new RangeError(`The "${name}" prop of ${componentName} must be between 0 and 1, but got ${value}. The crop range is 0 to 1, not 0 to 100.`);
    }
  }
};

// src/SequenceManager.tsx
import React14, { useCallback as useCallback5, useMemo as useMemo10, useRef as useRef3, useState as useState4 } from "react";
import { jsx as jsx10 } from "react/jsx-runtime";
var useIsomorphicLayoutEffect = typeof window === "undefined" ? React14.useEffect : React14.useLayoutEffect;
var SequenceManager = React14.createContext({
  registerSequence: () => {
    throw new Error("SequenceManagerContext not initialized");
  },
  updateSequence: null,
  unregisterSequence: () => {
    throw new Error("SequenceManagerContext not initialized");
  },
  sequences: []
});
var SequenceManagerRefContext = React14.createContext({
  current: []
});
var SequenceRegistrationContext = React14.createContext(false);
var makeSequencePropsSubscriptionKey = (key) => {
  return `${key.absolutePath}\x00${key.nodePath.join(".")}\x00${key.sequenceKeys.join(".")}\x00${key.effectKeys.map((keys) => keys.join(".")).join(".")}`;
};
var VisualModePropStatusesContext = React14.createContext({
  propStatuses: {}
});
var VisualModePropStatusesRefContext = React14.createContext({
  current: {}
});
var VisualModeDragOverridesContext = React14.createContext({
  getDragOverrides: () => {
    throw new Error("VisualModeDragOverridesContext not initialized");
  },
  getEffectDragOverrides: () => {
    throw new Error("VisualModeDragOverridesContext not initialized");
  }
});
var VisualModeSettersContext = React14.createContext({
  setDragOverrides: () => {
    throw new Error("VisualModeSettersContext not initialized");
  },
  clearDragOverrides: () => {
    throw new Error("VisualModeSettersContext not initialized");
  },
  setEffectDragOverrides: () => {
    throw new Error("VisualModeSettersContext not initialized");
  },
  clearEffectDragOverrides: () => {
    throw new Error("VisualModeSettersContext not initialized");
  },
  setPropStatuses: () => {
    throw new Error("VisualModeSettersContext not initialized");
  },
  remapPropStatuses: () => {
    throw new Error("VisualModeSettersContext not initialized");
  }
});
var effectDragOverridesKey = (nodePath, effectIndex) => `${makeSequencePropsSubscriptionKey(nodePath)}.effects.${effectIndex}`;
var SequenceManagerProvider = ({ children }) => {
  const { isStudio } = useRemotionEnvironment();
  const [sequenceManagerId] = useState4(() => String(Math.random()));
  const committedOrderRef = useRef3(null);
  const committedOrderIdsRef = useRef3(null);
  const [sequences, setSequences] = useState4([]);
  const sequencesRef = useRef3(sequences);
  sequencesRef.current = sequences;
  const [dragOverrides, setControlOverrides] = useState4({});
  const controlOverridesRef = useRef3(dragOverrides);
  controlOverridesRef.current = dragOverrides;
  const [effectDragOverridesState, setEffectDragOverridesState] = useState4({});
  const [propStatuses, setPropStatusesMapState] = useState4({});
  const propStatusesRef = useRef3(propStatuses);
  propStatusesRef.current = propStatuses;
  const setDragOverrides = useCallback5((nodePath, key, value) => {
    setControlOverrides((prev) => ({
      ...prev,
      [makeSequencePropsSubscriptionKey(nodePath)]: {
        ...prev[makeSequencePropsSubscriptionKey(nodePath)],
        [key]: value
      }
    }));
  }, []);
  const clearDragOverrides = useCallback5((nodePath) => {
    setControlOverrides((prev) => {
      const key = makeSequencePropsSubscriptionKey(nodePath);
      if (!prev[key]) {
        return prev;
      }
      const next = { ...prev };
      delete next[key];
      return next;
    });
  }, []);
  const setEffectDragOverrides = useCallback5((nodePath, effectIndex, key, value) => {
    setEffectDragOverridesState((prev) => {
      const mapKey = effectDragOverridesKey(nodePath, effectIndex);
      return {
        ...prev,
        [mapKey]: {
          ...prev[mapKey],
          [key]: value
        }
      };
    });
  }, []);
  const clearEffectDragOverrides = useCallback5((nodePath, effectIndex) => {
    setEffectDragOverridesState((prev) => {
      const mapKey = effectDragOverridesKey(nodePath, effectIndex);
      if (!prev[mapKey]) {
        return prev;
      }
      const next = { ...prev };
      delete next[mapKey];
      return next;
    });
  }, []);
  const setPropStatuses = useCallback5((nodePath, values) => {
    setPropStatusesMapState((prev) => {
      const key = makeSequencePropsSubscriptionKey(nodePath);
      const prevKey = prev[key];
      const newKey = values(prevKey);
      if (prevKey === newKey) {
        return prev;
      }
      return { ...prev, [key]: newKey };
    });
  }, []);
  const remapPropStatuses = useCallback5((remappings) => {
    setPropStatusesMapState((prev) => {
      const next = { ...prev };
      for (const remapping of remappings) {
        delete next[makeSequencePropsSubscriptionKey(remapping.previousNodePath)];
      }
      for (const remapping of remappings) {
        if (remapping.nodePath !== null && remapping.result !== null) {
          next[makeSequencePropsSubscriptionKey(remapping.nodePath)] = remapping.result;
        }
      }
      return next;
    });
  }, []);
  useIsomorphicLayoutEffect(() => {
    if (!isStudio) {
      return;
    }
    let unmounted = false;
    const onCommitOrder = (event) => {
      const { detail } = event;
      const managerOrder = detail.sequenceManagers.find((item) => item.managerId === sequenceManagerId);
      if (!managerOrder) {
        return;
      }
      const previousOrder = committedOrderIdsRef.current;
      if (previousOrder !== null && previousOrder.length === managerOrder.sequenceIds.length && previousOrder.every((sequenceId, index) => sequenceId === managerOrder.sequenceIds[index])) {
        return;
      }
      const order = new Map(managerOrder.sequenceIds.map((sequenceId, index) => [
        sequenceId,
        index
      ]));
      committedOrderIdsRef.current = managerOrder.sequenceIds;
      committedOrderRef.current = order;
      queueMicrotask(() => {
        if (unmounted) {
          return;
        }
        setSequences((currentSequences) => {
          let changed = false;
          const nextSequences = currentSequences.map((sequence) => {
            const timelineOrder = order.get(sequence.id) ?? null;
            if (sequence.timelineOrder === timelineOrder) {
              return sequence;
            }
            changed = true;
            return { ...sequence, timelineOrder };
          });
          return changed ? nextSequences : currentSequences;
        });
      });
    };
    window.addEventListener(COMMIT_ORDER_EVENT, onCommitOrder);
    return () => {
      unmounted = true;
      window.removeEventListener(COMMIT_ORDER_EVENT, onCommitOrder);
    };
  }, [isStudio, sequenceManagerId]);
  const registerSequence = useCallback5((seq) => {
    setSequences((seqs) => {
      return [
        ...seqs,
        {
          ...seq,
          timelineOrder: committedOrderRef.current?.get(seq.id) ?? null
        }
      ];
    });
  }, []);
  const updateSequence = useCallback5((seq) => {
    setSequences((seqs) => {
      const index = seqs.findIndex((item) => item.id === seq.id);
      if (index === -1) {
        return seqs;
      }
      const next = [...seqs];
      next[index] = {
        ...seq,
        timelineOrder: committedOrderRef.current?.get(seq.id) ?? null
      };
      return next;
    });
  }, []);
  const unregisterSequence = useCallback5((seq) => {
    setSequences((seqs) => seqs.filter((s) => s.id !== seq));
  }, []);
  const sequenceContext = useMemo10(() => {
    return {
      registerSequence,
      sequences,
      updateSequence,
      unregisterSequence
    };
  }, [registerSequence, sequences, unregisterSequence, updateSequence]);
  const getDragOverrides = useCallback5((nodePath) => {
    return dragOverrides[makeSequencePropsSubscriptionKey(nodePath)] ?? {};
  }, [dragOverrides]);
  const getEffectDragOverrides = useCallback5((nodePath, effectIndex) => {
    return effectDragOverridesState[effectDragOverridesKey(nodePath, effectIndex)] ?? {};
  }, [effectDragOverridesState]);
  const propStatusesContext = useMemo10(() => {
    return {
      propStatuses
    };
  }, [propStatuses]);
  const dragOverridesContext = useMemo10(() => {
    return {
      getDragOverrides,
      getEffectDragOverrides
    };
  }, [getDragOverrides, getEffectDragOverrides]);
  const settersContext = useMemo10(() => {
    return {
      setDragOverrides,
      clearDragOverrides,
      setEffectDragOverrides,
      clearEffectDragOverrides,
      setPropStatuses,
      remapPropStatuses
    };
  }, [
    setDragOverrides,
    clearDragOverrides,
    setEffectDragOverrides,
    clearEffectDragOverrides,
    setPropStatuses,
    remapPropStatuses
  ]);
  const providers = /* @__PURE__ */ jsx10(SequenceManagerRefContext.Provider, {
    value: sequencesRef,
    children: /* @__PURE__ */ jsx10(SequenceManager.Provider, {
      value: sequenceContext,
      children: /* @__PURE__ */ jsx10(VisualModePropStatusesRefContext.Provider, {
        value: propStatusesRef,
        children: /* @__PURE__ */ jsx10(VisualModePropStatusesContext.Provider, {
          value: propStatusesContext,
          children: /* @__PURE__ */ jsx10(VisualModeDragOverridesContext.Provider, {
            value: dragOverridesContext,
            children: /* @__PURE__ */ jsx10(VisualModeSettersContext.Provider, {
              value: settersContext,
              children
            })
          })
        })
      })
    })
  });
  return isStudio ? /* @__PURE__ */ jsx10(SequenceManagerOrderMarker, {
    managerId: sequenceManagerId,
    children: providers
  }) : providers;
};

// src/series/is-inside-series.tsx
import React15, { createContext as createContext14 } from "react";
import { jsx as jsx11 } from "react/jsx-runtime";
var IsInsideSeriesContext = createContext14(false);
var IsInsideSeriesContainer = ({ children }) => {
  return /* @__PURE__ */ jsx11(IsInsideSeriesContext.Provider, {
    value: true,
    children
  });
};
var IsNotInsideSeriesProvider = ({ children }) => {
  return /* @__PURE__ */ jsx11(IsInsideSeriesContext.Provider, {
    value: false,
    children
  });
};
var useRequireToBeInsideSeries = () => {
  const isInsideSeries = React15.useContext(IsInsideSeriesContext);
  if (!isInsideSeries) {
    throw new Error("This component must be inside a <Series /> component.");
  }
};

// src/use-premounting.ts
import { useContext as useContext16, useMemo as useMemo11 } from "react";

// src/PremountContext.tsx
import { createContext as createContext15 } from "react";
var PremountContext = createContext15({
  premountFramesRemaining: 0
});

// src/v5-flag.ts
var ENABLE_V5_BREAKING_CHANGES = false;
var resolveV5Default = (value) => {
  return value ?? ENABLE_V5_BREAKING_CHANGES;
};

// src/use-premounting.ts
var usePremounting = ({
  from,
  durationInFrames,
  premountFor,
  postmountFor,
  style,
  styleWhilePremounted,
  styleWhilePostmounted,
  hideWhilePremounted
}) => {
  const parentPremountContext = useContext16(PremountContext);
  const frame = useCurrentFrame() - parentPremountContext.premountFramesRemaining;
  const environment = useRemotionEnvironment();
  const { fps } = useVideoConfig();
  const effectivePremountFor = ENABLE_V5_BREAKING_CHANGES ? premountFor ?? fps : premountFor ?? 0;
  const effectivePostmountFor = postmountFor ?? 0;
  const endThreshold = Math.ceil(from + durationInFrames - 1);
  const premountingActive = !environment.isRendering && frame < from && frame >= from - effectivePremountFor;
  const postmountingActive = !environment.isRendering && frame > endThreshold && frame <= endThreshold + effectivePostmountFor;
  const isPremountingOrPostmounting = premountingActive || postmountingActive;
  const freezeFrame = premountingActive ? from : postmountingActive ? from + durationInFrames - 1 : 0;
  const premountingStyle = useMemo11(() => {
    if (!isPremountingOrPostmounting) {
      return style;
    }
    return {
      ...style,
      ...hideWhilePremounted === "opacity" ? { opacity: 0 } : { display: "none" },
      pointerEvents: "none",
      ...premountingActive ? styleWhilePremounted : {},
      ...postmountingActive ? styleWhilePostmounted : {}
    };
  }, [
    isPremountingOrPostmounting,
    hideWhilePremounted,
    postmountingActive,
    premountingActive,
    style,
    styleWhilePostmounted,
    styleWhilePremounted
  ]);
  return {
    effectivePremountFor,
    effectivePostmountFor,
    premountingActive,
    postmountingActive,
    isPremountingOrPostmounting,
    freezeFrame,
    premountingStyle
  };
};

// src/use-sequence-registration.ts
import { useContext as useContext17, useEffect as useEffect4, useRef as useRef4 } from "react";
var useSequenceRegistration = ({
  getSequence,
  id
}) => {
  const { registerSequence, unregisterSequence, updateSequence } = useContext17(SequenceManager);
  const getSequenceRef = useRef4(getSequence);
  getSequenceRef.current = getSequence;
  const lastRegisteredGetterRef = useRef4(null);
  const registrationEnabled = getSequence !== null;
  useEffect4(() => {
    if (!registrationEnabled) {
      return;
    }
    const currentGetter = getSequenceRef.current;
    if (currentGetter === null) {
      throw new Error("Expected a sequence registration getter");
    }
    registerSequence(currentGetter());
    lastRegisteredGetterRef.current = currentGetter;
    return () => {
      lastRegisteredGetterRef.current = null;
      unregisterSequence(id);
    };
  }, [id, registerSequence, registrationEnabled, unregisterSequence]);
  useEffect4(() => {
    if (getSequence === null || updateSequence === null || lastRegisteredGetterRef.current === getSequence) {
      return;
    }
    updateSequence(getSequence());
    lastRegisteredGetterRef.current = getSequence;
  }, [getSequence, updateSequence]);
};

// src/with-interactivity-schema.ts
import React16, {
  createContext as createContext17,
  forwardRef as forwardRef2,
  useContext as useContext19,
  useLayoutEffect as useLayoutEffect4,
  useMemo as useMemo12,
  useState as useState5
} from "react";

// src/delete-nested-key.ts
var deleteNestedKey = (obj, keysToRemove) => {
  for (const key of keysToRemove) {
    const parts = key.split(".");
    const parents = [obj];
    let current = obj;
    for (let i = 0;i < parts.length - 1; i++) {
      const part = parts[i];
      const next = current[part];
      if (next === undefined || next === null) {
        current = null;
        break;
      }
      current = next;
      parents.push(current);
    }
    if (current === null) {
      continue;
    }
    delete current[parts[parts.length - 1]];
    for (let i = parents.length - 1;i > 0; i--) {
      const parent = parents[i];
      if (Object.keys(parent).length === 0) {
        const parentKey = parts[i - 1];
        delete parents[i - 1][parentKey];
      } else {
        break;
      }
    }
  }
  return obj;
};

// src/effects/use-memoized-effects.ts
import { useContext as useContext18, useLayoutEffect as useLayoutEffect3, useRef as useRef5 } from "react";

// src/bezier.ts
var NEWTON_ITERATIONS = 4;
var NEWTON_MIN_SLOPE = 0.001;
var SUBDIVISION_PRECISION = 0.0000001;
var SUBDIVISION_MAX_ITERATIONS = 10;
var kSplineTableSize = 11;
var kSampleStepSize = 1 / (kSplineTableSize - 1);
var float32ArraySupported = typeof Float32Array === "function";
function a(aA1, aA2) {
  return 1 - 3 * aA2 + 3 * aA1;
}
function b(aA1, aA2) {
  return 3 * aA2 - 6 * aA1;
}
function c(aA1) {
  return 3 * aA1;
}
function calcBezier(aT, aA1, aA2) {
  return ((a(aA1, aA2) * aT + b(aA1, aA2)) * aT + c(aA1)) * aT;
}
function getSlope(aT, aA1, aA2) {
  return 3 * a(aA1, aA2) * aT * aT + 2 * b(aA1, aA2) * aT + c(aA1);
}
function binarySubdivide({
  aX,
  _aA,
  _aB,
  mX1,
  mX2
}) {
  let currentX;
  let currentT;
  let i = 0;
  let aA = _aA;
  let aB = _aB;
  do {
    currentT = aA + (aB - aA) / 2;
    currentX = calcBezier(currentT, mX1, mX2) - aX;
    if (currentX > 0) {
      aB = currentT;
    } else {
      aA = currentT;
    }
  } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
  return currentT;
}
function newtonRaphsonIterate(aX, _aGuessT, mX1, mX2) {
  let aGuessT = _aGuessT;
  for (let i = 0;i < NEWTON_ITERATIONS; ++i) {
    const currentSlope = getSlope(aGuessT, mX1, mX2);
    if (currentSlope === 0) {
      return aGuessT;
    }
    const currentX = calcBezier(aGuessT, mX1, mX2) - aX;
    aGuessT -= currentX / currentSlope;
  }
  return aGuessT;
}
function bezier(mX1, mY1, mX2, mY2) {
  if (!(mX1 >= 0 && mX1 <= 1 && mX2 >= 0 && mX2 <= 1)) {
    throw new Error("bezier x values must be in [0, 1] range");
  }
  const sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
  if (mX1 !== mY1 || mX2 !== mY2) {
    for (let i = 0;i < kSplineTableSize; ++i) {
      sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
    }
  }
  function getTForX(aX) {
    let intervalStart = 0;
    let currentSample = 1;
    const lastSample = kSplineTableSize - 1;
    for (;currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
      intervalStart += kSampleStepSize;
    }
    --currentSample;
    const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
    const guessForT = intervalStart + dist * kSampleStepSize;
    const initialSlope = getSlope(guessForT, mX1, mX2);
    if (initialSlope >= NEWTON_MIN_SLOPE) {
      return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
    }
    if (initialSlope === 0) {
      return guessForT;
    }
    return binarySubdivide({
      aX,
      _aA: intervalStart,
      _aB: intervalStart + kSampleStepSize,
      mX1,
      mX2
    });
  }
  return function(x) {
    const clampedX = Math.min(1, Math.max(0, x));
    if (mX1 === mY1 && mX2 === mY2) {
      return clampedX;
    }
    if (clampedX === 0) {
      return 0;
    }
    if (clampedX === 1) {
      return 1;
    }
    return calcBezier(getTForX(clampedX), mY1, mY2);
  };
}

// src/normalize-number.ts
var normalizeNumber = (value) => {
  return Math.round(value * 1e6) / 1e6;
};

// src/interpolate.ts
var angleUnits = new Set(["deg", "rad", "grad", "turn"]);
var lengthUnits = new Set([
  "%",
  "cap",
  "ch",
  "cm",
  "cqb",
  "cqh",
  "cqi",
  "cqmax",
  "cqmin",
  "cqw",
  "dvh",
  "dvw",
  "em",
  "ex",
  "ic",
  "in",
  "lh",
  "lvh",
  "lvw",
  "mm",
  "pc",
  "pt",
  "px",
  "q",
  "rem",
  "rlh",
  "svh",
  "svw",
  "vb",
  "vh",
  "vi",
  "vmax",
  "vmin",
  "vw"
]);
var cssNumberRegex = /^([+-]?(?:\d+\.?\d*|\.\d+))([a-zA-Z%]+)?$/;
var transformOriginKeywords = new Set([
  "left",
  "center",
  "right",
  "top",
  "bottom"
]);
var transformOriginKeywordOptions = (keyword) => {
  if (keyword === "left") {
    return [{ axis: "x", value: { value: 0, unit: "%" } }];
  }
  if (keyword === "right") {
    return [{ axis: "x", value: { value: 100, unit: "%" } }];
  }
  if (keyword === "top") {
    return [{ axis: "y", value: { value: 0, unit: "%" } }];
  }
  if (keyword === "bottom") {
    return [{ axis: "y", value: { value: 100, unit: "%" } }];
  }
  return [
    { axis: "x", value: { value: 50, unit: "%" } },
    { axis: "y", value: { value: 50, unit: "%" } }
  ];
};
var transformOriginCenter = { value: 50, unit: "%" };
var stringifyNumber = (value) => {
  return String(normalizeNumber(value));
};

class UnsupportedStringInterpolationValueError extends TypeError {
}
var parseStringInterpolationComponent = (component, value) => {
  const match = cssNumberRegex.exec(component);
  if (match === null) {
    throw new UnsupportedStringInterpolationValueError(`Cannot interpolate "${value}" because "${component}" is not a supported scale, translate, or rotate value`);
  }
  const unit = match[2] ?? null;
  const numberValue = Number(match[1]);
  if (!Number.isFinite(numberValue)) {
    throw new TypeError(`Cannot interpolate "${value}" because "${component}" is not finite`);
  }
  if (unit === null) {
    return { kind: "scale", value: numberValue, unit: null };
  }
  if (angleUnits.has(unit)) {
    return { kind: "rotate", value: numberValue, unit };
  }
  if (lengthUnits.has(unit)) {
    return { kind: "translate", value: numberValue, unit };
  }
  throw new TypeError(`Cannot interpolate "${value}" because "${unit}" is not a supported translate or rotate unit`);
};
var parseTransformOriginLengthPercentage = ({
  component,
  value,
  allowPercentage
}) => {
  const match = cssNumberRegex.exec(component);
  if (match === null) {
    throw new TypeError(`Cannot interpolate "${value}" because "${component}" is not a supported transform-origin ${allowPercentage ? "length-percentage" : "z length"}`);
  }
  const unit = match[2] ?? null;
  const numberValue = Number(match[1]);
  if (!Number.isFinite(numberValue)) {
    throw new TypeError(`Cannot interpolate "${value}" because "${component}" is not finite`);
  }
  if (unit === null || !lengthUnits.has(unit) || !allowPercentage && unit === "%") {
    throw new TypeError(`Cannot interpolate "${value}" because "${component}" is not a supported transform-origin ${allowPercentage ? "length-percentage" : "z length"}`);
  }
  return { value: numberValue, unit };
};
var parseTransformOriginToken = (component, value) => {
  const lower = component.toLowerCase();
  if (transformOriginKeywords.has(lower)) {
    return { type: "keyword", keyword: lower };
  }
  return {
    type: "length-percentage",
    parsed: parseTransformOriginLengthPercentage({
      component,
      value,
      allowPercentage: true
    })
  };
};
var parseTwoTransformOriginKeywords = (first, second, value) => {
  const candidates = [];
  for (const firstOption of transformOriginKeywordOptions(first)) {
    for (const secondOption of transformOriginKeywordOptions(second)) {
      if (firstOption.axis === secondOption.axis) {
        continue;
      }
      candidates.push(firstOption.axis === "x" ? [firstOption.value, secondOption.value] : [secondOption.value, firstOption.value]);
    }
  }
  if (candidates.length === 0) {
    throw new TypeError(`Cannot interpolate "${value}" because "${first} ${second}" is not a valid transform-origin keyword pair`);
  }
  return candidates[0];
};
var parseTransformOriginXY = (parts, value) => {
  if (parts.length === 1) {
    const token = parseTransformOriginToken(parts[0], value);
    if (token.type === "length-percentage") {
      return [token.parsed, transformOriginCenter];
    }
    if (token.keyword === "top" || token.keyword === "bottom") {
      return [
        transformOriginCenter,
        transformOriginKeywordOptions(token.keyword)[0].value
      ];
    }
    return [
      transformOriginKeywordOptions(token.keyword)[0].value,
      transformOriginCenter
    ];
  }
  const first = parseTransformOriginToken(parts[0], value);
  const second = parseTransformOriginToken(parts[1], value);
  if (first.type === "length-percentage" && second.type === "length-percentage") {
    return [first.parsed, second.parsed];
  }
  if (first.type === "keyword" && second.type === "keyword") {
    return parseTwoTransformOriginKeywords(first.keyword, second.keyword, value);
  }
  const keyword = first.type === "keyword" ? first : second.type === "keyword" ? second : null;
  const length = first.type === "length-percentage" ? first.parsed : second.type === "length-percentage" ? second.parsed : null;
  if (keyword === null || length === null) {
    throw new Error("Expected a keyword and a length-percentage value");
  }
  const keywordIsFirst = first.type === "keyword";
  if (keyword.keyword === "left" || keyword.keyword === "right") {
    if (!keywordIsFirst) {
      throw new TypeError(`Cannot interpolate "${value}" because horizontal transform-origin keywords must come before a length-percentage value`);
    }
    return [transformOriginKeywordOptions(keyword.keyword)[0].value, length];
  }
  if (keyword.keyword === "top" || keyword.keyword === "bottom") {
    return [length, transformOriginKeywordOptions(keyword.keyword)[0].value];
  }
  return keywordIsFirst ? [transformOriginCenter, length] : [length, transformOriginCenter];
};
var parseTransformOriginValue = (output, parts) => {
  const [x, y] = parseTransformOriginXY(parts.slice(0, 2), output);
  const z = parts[2] === undefined ? { value: 0, unit: null } : parseTransformOriginLengthPercentage({
    component: parts[2],
    value: output,
    allowPercentage: false
  });
  return {
    kind: "translate",
    values: [x.value, y.value, z.value, 0],
    units: [x.unit, y.unit, z.unit, null],
    dimensions: parts[2] === undefined ? 2 : 3,
    axisRotation: false
  };
};
var parseAxisRotationValue = (output) => {
  const parts = output.trim().split(/\s+/);
  const keywordAxis = parts.length === 2 ? parts[0].toLowerCase() : null;
  if (keywordAxis === "x" || keywordAxis === "y" || keywordAxis === "z") {
    const keywordAngle = parseStringInterpolationComponent(parts[1], output);
    if (keywordAngle.kind !== "rotate") {
      return null;
    }
    return {
      kind: "rotate",
      values: keywordAxis === "x" ? [1, 0, 0, keywordAngle.value] : keywordAxis === "y" ? [0, 1, 0, keywordAngle.value] : [0, 0, 1, keywordAngle.value],
      units: [null, null, null, keywordAngle.unit],
      dimensions: 4,
      axisRotation: true
    };
  }
  if (parts.length !== 4) {
    return null;
  }
  const axis = parts.slice(0, 3).map(Number);
  if (!axis.every(Number.isFinite)) {
    return null;
  }
  const vectorAngle = parseStringInterpolationComponent(parts[3], output);
  if (vectorAngle.kind !== "rotate") {
    return null;
  }
  return {
    kind: "rotate",
    values: [axis[0], axis[1], axis[2], vectorAngle.value],
    units: [null, null, null, vectorAngle.unit],
    dimensions: 4,
    axisRotation: true
  };
};
var parseStringInterpolationValue = (output) => {
  if (typeof output === "number") {
    if (!Number.isFinite(output)) {
      throw new Error(`outputRange must contain only finite numbers, but got [${output}]`);
    }
    return {
      kind: "scale",
      values: [output, output, 1, 0],
      units: [null, null, null, null],
      dimensions: 1,
      axisRotation: false
    };
  }
  const axisRotation = parseAxisRotationValue(output);
  if (axisRotation !== null) {
    return axisRotation;
  }
  const parts = output.trim().split(/\s+/);
  if (parts.length < 1 || parts.length > 3 || parts[0] === "") {
    throw new TypeError(`String outputRange values must contain 1 to 3 components, but got "${output}"`);
  }
  if (parts.some((part) => transformOriginKeywords.has(part.toLowerCase()))) {
    return parseTransformOriginValue(output, parts);
  }
  const parsed = parts.map((part) => parseStringInterpolationComponent(part, output));
  const [{ kind }] = parsed;
  for (const part of parsed) {
    if (part.kind !== kind) {
      throw new TypeError(`Cannot interpolate "${output}" because it mixes ${kind} and ${part.kind} values`);
    }
  }
  if (kind === "scale") {
    const x = parsed[0].value;
    const y = parsed[1]?.value ?? x;
    const z = parsed[2]?.value ?? 1;
    return {
      kind,
      values: [x, y, z, 0],
      units: [null, null, null, null],
      dimensions: parsed.length,
      axisRotation: false
    };
  }
  return {
    kind,
    values: [parsed[0].value, parsed[1]?.value ?? 0, parsed[2]?.value ?? 0, 0],
    units: [
      parsed[0].unit,
      parsed[1]?.unit ?? null,
      parsed[2]?.unit ?? null,
      null
    ],
    dimensions: parsed.length,
    axisRotation: false
  };
};
var serializeStringInterpolationValue = ({
  kind,
  values,
  units,
  dimensions,
  axisRotation
}) => {
  if (axisRotation) {
    return `${stringifyNumber(values[0])} ${stringifyNumber(values[1])} ${stringifyNumber(values[2])} ${stringifyNumber(values[3])}${units[3]}`;
  }
  if (kind === "scale") {
    return values.slice(0, dimensions).map((value) => stringifyNumber(value)).join(" ");
  }
  return values.slice(0, dimensions).map((value, index) => `${stringifyNumber(value)}${units[index]}`).join(" ");
};
var toSignedArea = (scale) => {
  if (scale === 0) {
    return 0;
  }
  return Math.sign(scale) * scale * scale;
};
var fromSignedArea = (area) => {
  if (area === 0) {
    return 0;
  }
  return Math.sign(area) * Math.sqrt(Math.abs(area));
};
function interpolateFunction(input, inputRange, outputRange, options) {
  const { extrapolateLeft, extrapolateRight, easing, output } = options;
  let result = input;
  const [inputMin, inputMax] = inputRange;
  const [outputMin, outputMax] = outputRange;
  if (result < inputMin) {
    if (extrapolateLeft === "identity") {
      return result;
    }
    if (extrapolateLeft === "clamp") {
      result = inputMin;
    } else if (extrapolateLeft === "wrap") {
      const range = inputMax - inputMin;
      result = ((result - inputMin) % range + range) % range + inputMin;
    } else if (extrapolateLeft === "extend") {}
  }
  if (result > inputMax) {
    if (extrapolateRight === "identity") {
      return result;
    }
    if (extrapolateRight === "clamp") {
      result = inputMax;
    } else if (extrapolateRight === "wrap") {
      const range = inputMax - inputMin;
      result = ((result - inputMin) % range + range) % range + inputMin;
    } else if (extrapolateRight === "extend") {}
  }
  if (outputMin === outputMax) {
    return outputMin;
  }
  result = (result - inputMin) / (inputMax - inputMin);
  result = easing(result);
  if (output === "perceptual-scale") {
    const signedAreaMin = toSignedArea(outputMin);
    const signedAreaMax = toSignedArea(outputMax);
    result = fromSignedArea(result * (signedAreaMax - signedAreaMin) + signedAreaMin);
  } else {
    result = result * (outputMax - outputMin) + outputMin;
  }
  return result;
}
function findRange(input, inputRange) {
  let i;
  for (i = 1;i < inputRange.length - 1; ++i) {
    if (inputRange[i] >= input) {
      break;
    }
  }
  return i - 1;
}
var defaultEasing = (num) => num;
var resolveOutputOption = (output) => {
  return output ?? "linear";
};
var shouldExtendRightForEasing = (easing) => {
  return easing.remotionShouldExtendRight === true;
};
var resolveEasingForSegment = ({
  easing,
  segmentIndex
}) => {
  if (easing === undefined) {
    return defaultEasing;
  }
  if (typeof easing === "function") {
    return easing;
  }
  return easing[segmentIndex];
};
var interpolateSegment = ({
  input,
  inputRange,
  outputRange,
  easing,
  extrapolateLeft,
  extrapolateRight,
  output
}) => {
  return interpolateFunction(input, inputRange, outputRange, {
    easing,
    extrapolateLeft,
    extrapolateRight: input > inputRange[1] && extrapolateRight === "clamp" && shouldExtendRightForEasing(easing) ? "extend" : extrapolateRight,
    output
  });
};
var interpolateNumber = ({
  input,
  inputRange,
  outputRange,
  options
}) => {
  const output = resolveOutputOption(options?.output);
  if (inputRange.length === 1) {
    return outputRange[0];
  }
  const easingOption = options?.easing;
  let extrapolateLeft = "extend";
  if (options?.extrapolateLeft !== undefined) {
    extrapolateLeft = options.extrapolateLeft;
  }
  let extrapolateRight = "extend";
  if (options?.extrapolateRight !== undefined) {
    extrapolateRight = options.extrapolateRight;
  }
  const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
  const range = findRange(posterizedInput, inputRange);
  const easing = resolveEasingForSegment({
    easing: easingOption,
    segmentIndex: range
  });
  let result = interpolateSegment({
    input: posterizedInput,
    inputRange: [inputRange[range], inputRange[range + 1]],
    outputRange: [outputRange[range], outputRange[range + 1]],
    easing,
    extrapolateLeft,
    extrapolateRight,
    output
  });
  for (let segmentIndex = 0;segmentIndex < range; segmentIndex++) {
    const previousEasing = resolveEasingForSegment({
      easing: easingOption,
      segmentIndex
    });
    if (!shouldExtendRightForEasing(previousEasing)) {
      continue;
    }
    const previousSegmentEnd = inputRange[segmentIndex + 1];
    if (posterizedInput <= previousSegmentEnd) {
      continue;
    }
    const continuedSegmentValue = interpolateSegment({
      input: posterizedInput,
      inputRange: [inputRange[segmentIndex], previousSegmentEnd],
      outputRange: [outputRange[segmentIndex], outputRange[segmentIndex + 1]],
      easing: previousEasing,
      extrapolateLeft,
      extrapolateRight: "extend",
      output
    });
    result += continuedSegmentValue - outputRange[segmentIndex + 1];
  }
  return result;
};
var interpolateString = ({
  input,
  inputRange,
  outputRange,
  options
}) => {
  const initiallyParsedOutputRange = outputRange.map(parseStringInterpolationValue);
  const hasAxisRotation = initiallyParsedOutputRange.some((parsed) => parsed.axisRotation);
  const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
  const segmentIndex = inputRange.length === 1 ? 0 : findRange(posterizedInput, inputRange);
  const parsedOutputRange = hasAxisRotation ? initiallyParsedOutputRange.map((parsed, index) => {
    if (parsed.kind !== "rotate") {
      return parsed;
    }
    if (parsed.axisRotation) {
      return parsed;
    }
    if (parsed.dimensions !== 1) {
      throw new TypeError("Cannot interpolate a multi-angle rotate value with an axis rotation");
    }
    const adjacentAxisRotation = parsed.values[0] === 0 ? index === 0 ? initiallyParsedOutputRange.find((candidate) => candidate.axisRotation) : index === initiallyParsedOutputRange.length - 1 ? [...initiallyParsedOutputRange].reverse().find((candidate) => candidate.axisRotation) : index === segmentIndex ? initiallyParsedOutputRange[index + 1] : index === segmentIndex + 1 ? initiallyParsedOutputRange[index - 1] : undefined : undefined;
    const axis = adjacentAxisRotation?.axisRotation ? adjacentAxisRotation.values : [0, 0, 1];
    return {
      kind: "rotate",
      values: [axis[0], axis[1], axis[2], parsed.values[0]],
      units: [null, null, null, parsed.units[0]],
      dimensions: 4,
      axisRotation: true
    };
  }) : initiallyParsedOutputRange;
  const kind = parsedOutputRange[0]?.kind;
  if (kind === undefined) {
    throw new Error("outputRange must have at least 1 element");
  }
  for (const parsed of parsedOutputRange) {
    if (parsed.kind !== kind) {
      throw new TypeError(`Cannot interpolate ${kind} values with ${parsed.kind} values`);
    }
  }
  const dimensions = Math.max(...parsedOutputRange.map((parsed) => parsed.dimensions));
  const units = [
    null,
    null,
    null,
    null
  ];
  if (kind !== "scale") {
    for (let axis = 0;axis < dimensions; axis++) {
      if (hasAxisRotation && axis < 3) {
        continue;
      }
      for (const parsed of parsedOutputRange) {
        const unit = parsed.units[axis];
        if (unit === null) {
          continue;
        }
        if (units[axis] === null) {
          units[axis] = unit;
          continue;
        }
        if (units[axis] !== unit) {
          throw new TypeError(`Cannot interpolate ${kind} values with different units on axis ${axis + 1}: ${units[axis]} and ${unit}`);
        }
      }
      if (units[axis] === null) {
        throw new TypeError(`Cannot interpolate ${kind} values because axis ${axis + 1} has no unit`);
      }
    }
  }
  const values = [0, 0, 0, 0];
  for (let axis = 0;axis < dimensions; axis++) {
    values[axis] = interpolateNumber({
      input,
      inputRange,
      outputRange: parsedOutputRange.map((parsed) => parsed.values[axis]),
      options
    });
  }
  return serializeStringInterpolationValue({
    kind,
    values,
    units,
    dimensions,
    axisRotation: hasAxisRotation
  });
};
var interpolateDiscreteString = ({
  input,
  inputRange,
  outputRange,
  options
}) => {
  if (inputRange.length === 1) {
    return outputRange[0];
  }
  for (let segmentIndex = 0;segmentIndex < inputRange.length - 1; segmentIndex++) {
    if (resolveEasingForSegment({
      easing: options?.easing,
      segmentIndex
    }) !== Easing.step1) {
      throw new TypeError("Non-numeric strings can only be interpolated using Easing.step1");
    }
  }
  const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
  const inputMin = inputRange[0];
  const inputMax = inputRange[inputRange.length - 1];
  let resolvedInput = posterizedInput;
  if (resolvedInput < inputMin) {
    if (options?.extrapolateLeft === "identity") {
      throw new TypeError('extrapolateLeft: "identity" is not supported for non-numeric strings');
    }
    if (options?.extrapolateLeft === "wrap") {
      const wrapRange = inputMax - inputMin;
      resolvedInput = ((resolvedInput - inputMin) % wrapRange + wrapRange) % wrapRange + inputMin;
    } else {
      return outputRange[0];
    }
  }
  if (resolvedInput > inputMax) {
    if (options?.extrapolateRight === "identity") {
      throw new TypeError('extrapolateRight: "identity" is not supported for non-numeric strings');
    }
    if (options?.extrapolateRight === "wrap") {
      const wrapRange = inputMax - inputMin;
      resolvedInput = ((resolvedInput - inputMin) % wrapRange + wrapRange) % wrapRange + inputMin;
    } else {
      return outputRange[outputRange.length - 1];
    }
  }
  const range = findRange(resolvedInput, inputRange);
  return resolvedInput >= inputRange[range + 1] ? outputRange[range + 1] : outputRange[range];
};
var validateTupleOutputRange = (outputRange) => {
  const dimensions = outputRange[0]?.length;
  if (dimensions === undefined) {
    throw new Error("outputRange must have at least 1 element");
  }
  if (dimensions === 0) {
    throw new TypeError("outputRange tuples must contain at least 1 number");
  }
  for (const output of outputRange) {
    if (output.length !== dimensions) {
      throw new TypeError(`outputRange tuples must all have the same length, but got ${dimensions} and ${output.length}`);
    }
    for (const value of output) {
      if (typeof value !== "number" || !Number.isFinite(value)) {
        throw new TypeError(`outputRange tuples must contain only finite numbers, but got [${output.join(",")}]`);
      }
    }
  }
  return dimensions;
};
var interpolateTuple = ({
  input,
  inputRange,
  outputRange,
  options
}) => {
  const dimensions = validateTupleOutputRange(outputRange);
  return new Array(dimensions).fill(true).map((_, axis) => interpolateNumber({
    input,
    inputRange,
    outputRange: outputRange.map((output) => output[axis]),
    options
  }));
};
function checkValidInputRange(arr) {
  for (let i = 1;i < arr.length; ++i) {
    if (!(arr[i] > arr[i - 1])) {
      throw new Error(`inputRange must be strictly monotonically increasing but got [${arr.join(",")}]`);
    }
  }
}
function checkInfiniteRange(name, arr) {
  if (arr.length < 1) {
    throw new Error(name + " must have at least 1 element");
  }
  for (const element of arr) {
    if (typeof element !== "number") {
      throw new Error(`${name} must contain only numbers`);
    }
    if (!Number.isFinite(element)) {
      throw new Error(`${name} must contain only finite numbers, but got [${arr.join(",")}]`);
    }
  }
}
function assertValidInterpolateEasingOption(easing, inputRangeLength) {
  if (easing === undefined) {
    return;
  }
  if (typeof easing === "function") {
    return;
  }
  const expectedLength = inputRangeLength - 1;
  if (easing.length !== expectedLength) {
    throw new Error(`When easing is an array, it must have one entry per segment between keyframes (length inputRange.length - 1 = ${expectedLength}), but got length ${easing.length}`);
  }
  for (let i = 0;i < easing.length; i++) {
    if (typeof easing[i] !== "function") {
      throw new Error(`easing[${i}] must be a function`);
    }
  }
}
function assertValidInterpolatePosterizeOption(posterize) {
  if (posterize === undefined) {
    return;
  }
  if (typeof posterize !== "number" || !Number.isFinite(posterize) || posterize <= 0) {
    throw new Error(`posterize must be a positive finite number, but got ${posterize}`);
  }
}
function assertValidInterpolateOutputOption(output) {
  if (output === undefined || output === "linear" || output === "perceptual-scale") {
    return;
  }
  throw new Error(`output must be "linear" or "perceptual-scale", but got ${String(output)}`);
}
function interpolate(input, inputRange, outputRange, options) {
  if (typeof input === "undefined") {
    throw new Error("input can not be undefined");
  }
  if (typeof inputRange === "undefined") {
    throw new Error("inputRange can not be undefined");
  }
  if (typeof outputRange === "undefined") {
    throw new Error("outputRange can not be undefined");
  }
  if (inputRange.length !== outputRange.length) {
    throw new Error("inputRange (" + inputRange.length + ") and outputRange (" + outputRange.length + ") must have the same length");
  }
  checkInfiniteRange("inputRange", inputRange);
  checkValidInputRange(inputRange);
  assertValidInterpolateEasingOption(options?.easing, inputRange.length);
  assertValidInterpolatePosterizeOption(options?.posterize);
  assertValidInterpolateOutputOption(options?.output);
  if (typeof input !== "number") {
    throw new TypeError("Cannot interpolate an input which is not a number");
  }
  if (!Array.isArray(outputRange)) {
    throw new Error("outputRange must contain only numbers");
  }
  const hasStringOutput = outputRange.some((output) => typeof output === "string");
  if (hasStringOutput) {
    if (!outputRange.every((output) => typeof output === "string" || typeof output === "number")) {
      throw new TypeError("outputRange must contain only numbers, or supported scale, translate, and rotate strings");
    }
    try {
      return interpolateString({ input, inputRange, outputRange, options });
    } catch (error2) {
      if (!outputRange.every((output) => typeof output === "string")) {
        throw error2;
      }
      const hasNonNumericString = outputRange.some((output) => {
        try {
          parseStringInterpolationValue(output);
          return false;
        } catch (parseError) {
          return parseError instanceof UnsupportedStringInterpolationValueError;
        }
      });
      if (!hasNonNumericString) {
        throw error2;
      }
      return interpolateDiscreteString({
        input,
        inputRange,
        outputRange,
        options
      });
    }
  }
  if (outputRange.every((output) => Array.isArray(output))) {
    return interpolateTuple({ input, inputRange, outputRange, options });
  }
  if (!outputRange.every((output) => typeof output === "number")) {
    throw new TypeError("outputRange must contain only numbers, numeric tuples, or supported scale, translate, and rotate strings");
  }
  checkInfiniteRange("outputRange", outputRange);
  return interpolateNumber({ input, inputRange, outputRange, options });
}

// src/validate-frame.ts
var validateFrame = ({
  allowFloats,
  durationInFrames,
  frame
}) => {
  if (typeof frame === "undefined") {
    throw new TypeError(`Argument missing for parameter "frame"`);
  }
  if (typeof frame !== "number") {
    throw new TypeError(`Argument passed for "frame" is not a number: ${frame}`);
  }
  if (!Number.isFinite(frame)) {
    throw new RangeError(`Frame ${frame} is not finite`);
  }
  if (frame % 1 !== 0 && !allowFloats) {
    throw new RangeError(`Argument for frame must be an integer, but got ${frame}`);
  }
  if (frame < 0 && frame < -durationInFrames) {
    throw new RangeError(`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the lowest frame that can be rendered is ${-durationInFrames}`);
  }
  if (frame > durationInFrames - 1) {
    throw new RangeError(`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the highest frame that can be rendered is ${durationInFrames - 1}`);
  }
};

// src/validation/validation-spring-duration.ts
var validateSpringDuration = (dur) => {
  if (typeof dur === "undefined") {
    return;
  }
  if (typeof dur !== "number") {
    throw new TypeError(`A "duration" of a spring must be a "number" but is "${typeof dur}"`);
  }
  if (Number.isNaN(dur)) {
    throw new TypeError('A "duration" of a spring is NaN, which it must not be');
  }
  if (!Number.isFinite(dur)) {
    throw new TypeError('A "duration" of a spring must be finite, but is ' + dur);
  }
  if (dur <= 0) {
    throw new TypeError('A "duration" of a spring must be positive, but is ' + dur);
  }
};

// src/spring/spring-utils.ts
var defaultSpringConfig = {
  damping: 10,
  mass: 1,
  stiffness: 100,
  overshootClamping: false
};
var advanceCache = {};
function advance({
  animation,
  now,
  config
}) {
  const { toValue, lastTimestamp, current, velocity } = animation;
  const deltaTime = Math.min(now - lastTimestamp, 64);
  if (config.damping <= 0) {
    throw new Error("Spring damping must be greater than 0, otherwise the spring() animation will never end, causing an infinite loop.");
  }
  const c2 = config.damping;
  const m = config.mass;
  const k = config.stiffness;
  const cacheKey = [
    toValue,
    lastTimestamp,
    current,
    velocity,
    c2,
    m,
    k,
    now
  ].join("-");
  if (advanceCache[cacheKey]) {
    return advanceCache[cacheKey];
  }
  const v0 = -velocity;
  const x0 = toValue - current;
  const zeta = c2 / (2 * Math.sqrt(k * m));
  const omega0 = Math.sqrt(k / m);
  const omega1 = omega0 * Math.sqrt(1 - zeta ** 2);
  const t = deltaTime / 1000;
  const sin1 = Math.sin(omega1 * t);
  const cos1 = Math.cos(omega1 * t);
  const underDampedEnvelope = Math.exp(-zeta * omega0 * t);
  const underDampedFrag1 = underDampedEnvelope * (sin1 * ((v0 + zeta * omega0 * x0) / omega1) + x0 * cos1);
  const underDampedPosition = toValue - underDampedFrag1;
  const underDampedVelocity = zeta * omega0 * underDampedFrag1 - underDampedEnvelope * (cos1 * (v0 + zeta * omega0 * x0) - omega1 * x0 * sin1);
  const criticallyDampedEnvelope = Math.exp(-omega0 * t);
  const criticallyDampedPosition = toValue - criticallyDampedEnvelope * (x0 + (v0 + omega0 * x0) * t);
  const criticallyDampedVelocity = criticallyDampedEnvelope * (v0 * (t * omega0 - 1) + t * x0 * omega0 * omega0);
  const animationNode = {
    toValue,
    prevPosition: current,
    lastTimestamp: now,
    current: zeta < 1 ? underDampedPosition : criticallyDampedPosition,
    velocity: zeta < 1 ? underDampedVelocity : criticallyDampedVelocity
  };
  advanceCache[cacheKey] = animationNode;
  return animationNode;
}
var calculationCache = {};
function springCalculation({
  frame,
  fps,
  config = {}
}) {
  const from = 0;
  const to = 1;
  const cacheKey = [
    frame,
    fps,
    config.damping,
    config.mass,
    config.overshootClamping,
    config.stiffness
  ].join("-");
  if (calculationCache[cacheKey]) {
    return calculationCache[cacheKey];
  }
  let animation = {
    lastTimestamp: 0,
    current: from,
    toValue: to,
    velocity: 0,
    prevPosition: 0
  };
  const frameClamped = Math.max(0, frame);
  const unevenRest = frameClamped % 1;
  for (let f = 0;f <= Math.floor(frameClamped); f++) {
    const time = f / fps * 1000;
    animation = advance({
      animation,
      now: time,
      config: {
        ...defaultSpringConfig,
        ...config
      }
    });
  }
  if (unevenRest > 0) {
    animation = advance({
      animation,
      now: frameClamped / fps * 1000,
      config: {
        ...defaultSpringConfig,
        ...config
      }
    });
  }
  calculationCache[cacheKey] = animation;
  return animation;
}

// src/spring/measure-spring.ts
var cache = new Map;
function measureSpring({
  fps,
  config = {},
  threshold = 0.005
}) {
  if (typeof threshold !== "number") {
    throw new TypeError(`threshold must be a number, got ${threshold} of type ${typeof threshold}`);
  }
  if (threshold === 0) {
    return Infinity;
  }
  if (threshold === 1) {
    return 0;
  }
  if (isNaN(threshold)) {
    throw new TypeError("Threshold is NaN");
  }
  if (!Number.isFinite(threshold)) {
    throw new TypeError("Threshold is not finite");
  }
  if (threshold < 0) {
    throw new TypeError("Threshold is below 0");
  }
  const cacheKey = [
    fps,
    config.damping,
    config.mass,
    config.overshootClamping,
    config.stiffness,
    threshold
  ].join("-");
  if (cache.has(cacheKey)) {
    return cache.get(cacheKey);
  }
  validateFps(fps, "to the measureSpring() function", false);
  let frame = 0;
  let finishedFrame = 0;
  const calc = () => {
    return springCalculation({
      fps,
      frame,
      config
    });
  };
  let animation = calc();
  const calcDifference = () => {
    return Math.abs(animation.current - animation.toValue);
  };
  let difference = calcDifference();
  while (difference >= threshold) {
    frame++;
    animation = calc();
    difference = calcDifference();
  }
  finishedFrame = frame;
  for (let i = 0;i < 20; i++) {
    frame++;
    animation = calc();
    difference = calcDifference();
    if (difference >= threshold) {
      i = 0;
      finishedFrame = frame + 1;
    }
  }
  cache.set(cacheKey, finishedFrame);
  return finishedFrame;
}

// src/spring/index.ts
function spring({
  frame: passedFrame,
  fps,
  config = {},
  from = 0,
  to = 1,
  durationInFrames: passedDurationInFrames,
  durationRestThreshold,
  delay = 0,
  reverse = false
}) {
  validateSpringDuration(passedDurationInFrames);
  validateFrame({
    frame: passedFrame,
    durationInFrames: Infinity,
    allowFloats: true
  });
  validateFps(fps, "to spring()", false);
  const needsToCalculateNaturalDuration = reverse || typeof passedDurationInFrames !== "undefined";
  const naturalDuration = needsToCalculateNaturalDuration ? measureSpring({
    fps,
    config,
    threshold: durationRestThreshold
  }) : undefined;
  const naturalDurationGetter = needsToCalculateNaturalDuration ? {
    get: () => naturalDuration
  } : {
    get: () => {
      throw new Error("did not calculate natural duration, this is an error with Remotion. Please report");
    }
  };
  const reverseProcessed = reverse ? (passedDurationInFrames ?? naturalDurationGetter.get()) - passedFrame : passedFrame;
  const delayProcessed = reverseProcessed + (reverse ? delay : -delay);
  const durationProcessed = passedDurationInFrames === undefined ? delayProcessed : delayProcessed / (passedDurationInFrames / naturalDurationGetter.get());
  if (passedDurationInFrames && delayProcessed > passedDurationInFrames) {
    return to;
  }
  const spr = springCalculation({
    fps,
    frame: durationProcessed,
    config
  });
  const inner = config.overshootClamping ? to >= from ? Math.min(spr.current, to) : Math.max(spr.current, to) : spr.current;
  const interpolated = from === 0 && to === 1 ? inner : interpolate(inner, [0, 1], [from, to]);
  return interpolated;
}

// src/easing.ts
var clampUnit = (t) => Math.min(1, Math.max(0, t));
var springEasingDurationInFrames = 30;

class Easing {
  static step0(n) {
    return n > 0 ? 1 : 0;
  }
  static step1(n) {
    return n >= 1 ? 1 : 0;
  }
  static linear(t) {
    return t;
  }
  static ease(t) {
    return Easing.bezier(0.42, 0, 1, 1)(t);
  }
  static quad(t) {
    return t * t;
  }
  static cubic(t) {
    return t * t * t;
  }
  static poly(n) {
    return (t) => t ** n;
  }
  static sin(t) {
    return 1 - Math.cos(t * Math.PI / 2);
  }
  static circle(t) {
    const u = clampUnit(t);
    return 1 - Math.sqrt(1 - u * u);
  }
  static exp(t) {
    return 2 ** (10 * (t - 1));
  }
  static elastic(bounciness = 1) {
    const p = bounciness * Math.PI;
    return (t) => 1 - Math.cos(t * Math.PI / 2) ** 3 * Math.cos(t * p);
  }
  static back(s = 1.70158) {
    return (t) => t * t * ((s + 1) * t - s);
  }
  static spring({
    allowTail = false,
    durationRestThreshold,
    ...config
  } = {}) {
    const easing = (t) => {
      if (t <= 0) {
        return 0;
      }
      if (!allowTail && t >= 1) {
        return 1;
      }
      if (allowTail) {
        return spring({
          fps: springEasingDurationInFrames,
          frame: t * measureSpring({
            fps: springEasingDurationInFrames,
            config,
            threshold: durationRestThreshold
          }),
          config
        });
      }
      return spring({
        fps: springEasingDurationInFrames,
        frame: t * springEasingDurationInFrames,
        config,
        durationInFrames: springEasingDurationInFrames,
        durationRestThreshold
      });
    };
    return Object.assign(easing, {
      remotionShouldExtendRight: allowTail
    });
  }
  static bounce(t) {
    const u = clampUnit(t);
    if (u < 1 / 2.75) {
      return 7.5625 * u * u;
    }
    if (u < 2 / 2.75) {
      const t2_ = u - 1.5 / 2.75;
      return 7.5625 * t2_ * t2_ + 0.75;
    }
    if (u < 2.5 / 2.75) {
      const t2_ = u - 2.25 / 2.75;
      return 7.5625 * t2_ * t2_ + 0.9375;
    }
    const t2 = u - 2.625 / 2.75;
    return 7.5625 * t2 * t2 + 0.984375;
  }
  static bezier(x1, y1, x2, y2) {
    return bezier(x1, y1, x2, y2);
  }
  static in(easing) {
    return easing;
  }
  static out(easing) {
    return (t) => 1 - easing(1 - t);
  }
  static inOut(easing) {
    return (t) => {
      if (t < 0.5) {
        return easing(t * 2) / 2;
      }
      return 1 - easing((1 - t) * 2) / 2;
    };
  }
}

// src/interpolate-colors.ts
var NUMBER = "[-+]?\\d*\\.?\\d+";
var PERCENTAGE = NUMBER + "%";
function call(...args) {
  return "\\(\\s*(" + args.join(")\\s*,\\s*(") + ")\\s*\\)";
}
var MODERN_VALUE = "(?:none|[-+]?\\d*\\.?\\d+(?:%|deg|rad|grad|turn)?)";
function modernColorCall(name) {
  return new RegExp(name + "\\(\\s*(" + MODERN_VALUE + ")\\s+(" + MODERN_VALUE + ")\\s+(" + MODERN_VALUE + ")(?:\\s*\\/\\s*(" + MODERN_VALUE + "))?\\s*\\)");
}
function getMatchers() {
  const cachedMatchers = {
    rgb: undefined,
    rgba: undefined,
    hsl: undefined,
    hsla: undefined,
    hex3: undefined,
    hex4: undefined,
    hex5: undefined,
    hex6: undefined,
    hex8: undefined,
    oklch: undefined,
    oklab: undefined,
    lab: undefined,
    lch: undefined,
    hwb: undefined
  };
  if (cachedMatchers.rgb === undefined) {
    cachedMatchers.rgb = new RegExp("rgb" + call(NUMBER, NUMBER, NUMBER));
    cachedMatchers.rgba = new RegExp("rgba" + call(NUMBER, NUMBER, NUMBER, NUMBER));
    cachedMatchers.hsl = new RegExp("hsl" + call(NUMBER, PERCENTAGE, PERCENTAGE));
    cachedMatchers.hsla = new RegExp("hsla" + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER));
    cachedMatchers.hex3 = /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
    cachedMatchers.hex4 = /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/;
    cachedMatchers.hex6 = /^#([0-9a-fA-F]{6})$/;
    cachedMatchers.hex8 = /^#([0-9a-fA-F]{8})$/;
    cachedMatchers.oklch = modernColorCall("oklch");
    cachedMatchers.oklab = modernColorCall("oklab");
    cachedMatchers.lab = modernColorCall("lab");
    cachedMatchers.lch = modernColorCall("lch");
    cachedMatchers.hwb = modernColorCall("hwb");
  }
  return cachedMatchers;
}
function hue2rgb(p, q, t) {
  if (t < 0) {
    t += 1;
  }
  if (t > 1) {
    t -= 1;
  }
  if (t < 1 / 6) {
    return p + (q - p) * 6 * t;
  }
  if (t < 1 / 2) {
    return q;
  }
  if (t < 2 / 3) {
    return p + (q - p) * (2 / 3 - t) * 6;
  }
  return p;
}
function hslToRgb(h, s, l) {
  const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  const p = 2 * l - q;
  const r = hue2rgb(p, q, h + 1 / 3);
  const g = hue2rgb(p, q, h);
  const b2 = hue2rgb(p, q, h - 1 / 3);
  return Math.round(r * 255) << 24 | Math.round(g * 255) << 16 | Math.round(b2 * 255) << 8;
}
function parse255(str) {
  const int = Number.parseInt(str, 10);
  if (int < 0) {
    return 0;
  }
  if (int > 255) {
    return 255;
  }
  return int;
}
function parse360(str) {
  const int = Number.parseFloat(str);
  return (int % 360 + 360) % 360 / 360;
}
function parse1(str) {
  const num = Number.parseFloat(str);
  if (num < 0) {
    return 0;
  }
  if (num > 1) {
    return 255;
  }
  return Math.round(num * 255);
}
function parsePercentage(str) {
  const int = Number.parseFloat(str);
  if (int < 0) {
    return 0;
  }
  if (int > 100) {
    return 1;
  }
  return int / 100;
}
function parseModernComponent(str, percentScale) {
  if (str === "none")
    return 0;
  if (str.endsWith("%")) {
    return Number.parseFloat(str) / 100 * percentScale;
  }
  return Number.parseFloat(str);
}
function parseHueAngle(str) {
  if (str === "none")
    return 0;
  if (str.endsWith("rad")) {
    return Number.parseFloat(str) * 180 / Math.PI;
  }
  if (str.endsWith("grad"))
    return Number.parseFloat(str) * 0.9;
  if (str.endsWith("turn"))
    return Number.parseFloat(str) * 360;
  return Number.parseFloat(str);
}
function parseModernAlpha(str) {
  if (str === undefined || str === "none")
    return 1;
  if (str.endsWith("%")) {
    return Math.max(0, Math.min(1, Number.parseFloat(str) / 100));
  }
  return Math.max(0, Math.min(1, Number.parseFloat(str)));
}
function linearToSrgb(c2) {
  if (c2 <= 0.0031308)
    return 12.92 * c2;
  return 1.055 * c2 ** (1 / 2.4) - 0.055;
}
function clamp01(v) {
  return Math.max(0, Math.min(1, v));
}
function rgbFloatToInt(r, g, b2, alpha) {
  const ri = Math.round(clamp01(r) * 255);
  const gi = Math.round(clamp01(g) * 255);
  const bi = Math.round(clamp01(b2) * 255);
  const ai = Math.round(clamp01(alpha) * 255);
  return (ri << 24 | gi << 16 | bi << 8 | ai) >>> 0;
}
function oklabToSrgb(L, a2, b2) {
  const l_ = L + 0.3963377774 * a2 + 0.2158037573 * b2;
  const m_ = L - 0.1055613458 * a2 - 0.0638541728 * b2;
  const s_ = L - 0.0894841775 * a2 - 1.291485548 * b2;
  const l = l_ * l_ * l_;
  const m = m_ * m_ * m_;
  const s = s_ * s_ * s_;
  const rLin = 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
  const gLin = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
  const bLin = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;
  return [linearToSrgb(rLin), linearToSrgb(gLin), linearToSrgb(bLin)];
}
function labToSrgb(L, a2, b2) {
  const epsilon = 216 / 24389;
  const kappa = 24389 / 27;
  const Xn = 0.95047;
  const Yn = 1;
  const Zn = 1.08883;
  const fy = (L + 16) / 116;
  const fx = a2 / 500 + fy;
  const fz = fy - b2 / 200;
  const fx3 = fx * fx * fx;
  const fz3 = fz * fz * fz;
  const xr = fx3 > epsilon ? fx3 : (116 * fx - 16) / kappa;
  const yr = L > kappa * epsilon ? ((L + 16) / 116) ** 3 : L / kappa;
  const zr = fz3 > epsilon ? fz3 : (116 * fz - 16) / kappa;
  const X = xr * Xn;
  const Y = yr * Yn;
  const Z = zr * Zn;
  const rLin = 3.2404542 * X - 1.5371385 * Y - 0.4985314 * Z;
  const gLin = -0.969266 * X + 1.8760108 * Y + 0.041556 * Z;
  const bLin = 0.0556434 * X - 0.2040259 * Y + 1.0572252 * Z;
  return [linearToSrgb(rLin), linearToSrgb(gLin), linearToSrgb(bLin)];
}
function hwbToSrgb(h, w, bk) {
  if (w + bk >= 1) {
    const gray = w / (w + bk);
    return [gray, gray, gray];
  }
  const q = 1;
  const p = 0;
  const r = hue2rgb(p, q, h + 1 / 3);
  const g = hue2rgb(p, q, h);
  const bl = hue2rgb(p, q, h - 1 / 3);
  const factor = 1 - w - bk;
  return [r * factor + w, g * factor + w, bl * factor + w];
}
var colorNames = {
  transparent: 0,
  aliceblue: 4042850303,
  antiquewhite: 4209760255,
  aqua: 16777215,
  aquamarine: 2147472639,
  azure: 4043309055,
  beige: 4126530815,
  bisque: 4293182719,
  black: 255,
  blanchedalmond: 4293643775,
  blue: 65535,
  blueviolet: 2318131967,
  brown: 2771004159,
  burlywood: 3736635391,
  burntsienna: 3934150143,
  cadetblue: 1604231423,
  chartreuse: 2147418367,
  chocolate: 3530104575,
  coral: 4286533887,
  cornflowerblue: 1687547391,
  cornsilk: 4294499583,
  crimson: 3692313855,
  cyan: 16777215,
  darkblue: 35839,
  darkcyan: 9145343,
  darkgoldenrod: 3095792639,
  darkgray: 2846468607,
  darkgreen: 6553855,
  darkgrey: 2846468607,
  darkkhaki: 3182914559,
  darkmagenta: 2332068863,
  darkolivegreen: 1433087999,
  darkorange: 4287365375,
  darkorchid: 2570243327,
  darkred: 2332033279,
  darksalmon: 3918953215,
  darkseagreen: 2411499519,
  darkslateblue: 1211993087,
  darkslategray: 793726975,
  darkslategrey: 793726975,
  darkturquoise: 13554175,
  darkviolet: 2483082239,
  deeppink: 4279538687,
  deepskyblue: 12582911,
  dimgray: 1768516095,
  dimgrey: 1768516095,
  dodgerblue: 512819199,
  firebrick: 2988581631,
  floralwhite: 4294635775,
  forestgreen: 579543807,
  fuchsia: 4278255615,
  gainsboro: 3705462015,
  ghostwhite: 4177068031,
  gold: 4292280575,
  goldenrod: 3668254975,
  gray: 2155905279,
  green: 8388863,
  greenyellow: 2919182335,
  grey: 2155905279,
  honeydew: 4043305215,
  hotpink: 4285117695,
  indianred: 3445382399,
  indigo: 1258324735,
  ivory: 4294963455,
  khaki: 4041641215,
  lavender: 3873897215,
  lavenderblush: 4293981695,
  lawngreen: 2096890111,
  lemonchiffon: 4294626815,
  lightblue: 2916673279,
  lightcoral: 4034953471,
  lightcyan: 3774873599,
  lightgoldenrodyellow: 4210742015,
  lightgray: 3553874943,
  lightgreen: 2431553791,
  lightgrey: 3553874943,
  lightpink: 4290167295,
  lightsalmon: 4288707327,
  lightseagreen: 548580095,
  lightskyblue: 2278488831,
  lightslategray: 2005441023,
  lightslategrey: 2005441023,
  lightsteelblue: 2965692159,
  lightyellow: 4294959359,
  lime: 16711935,
  limegreen: 852308735,
  linen: 4210091775,
  magenta: 4278255615,
  maroon: 2147483903,
  mediumaquamarine: 1724754687,
  mediumblue: 52735,
  mediumorchid: 3126187007,
  mediumpurple: 2473647103,
  mediumseagreen: 1018393087,
  mediumslateblue: 2070474495,
  mediumspringgreen: 16423679,
  mediumturquoise: 1221709055,
  mediumvioletred: 3340076543,
  midnightblue: 421097727,
  mintcream: 4127193855,
  mistyrose: 4293190143,
  moccasin: 4293178879,
  navajowhite: 4292783615,
  navy: 33023,
  oldlace: 4260751103,
  olive: 2155872511,
  olivedrab: 1804477439,
  orange: 4289003775,
  orangered: 4282712319,
  orchid: 3664828159,
  palegoldenrod: 4008225535,
  palegreen: 2566625535,
  paleturquoise: 2951671551,
  palevioletred: 3681588223,
  papayawhip: 4293907967,
  peachpuff: 4292524543,
  peru: 3448061951,
  pink: 4290825215,
  plum: 3718307327,
  powderblue: 2967529215,
  purple: 2147516671,
  rebeccapurple: 1714657791,
  red: 4278190335,
  rosybrown: 3163525119,
  royalblue: 1097458175,
  saddlebrown: 2336560127,
  salmon: 4202722047,
  sandybrown: 4104413439,
  seagreen: 780883967,
  seashell: 4294307583,
  sienna: 2689740287,
  silver: 3233857791,
  skyblue: 2278484991,
  slateblue: 1784335871,
  slategray: 1887473919,
  slategrey: 1887473919,
  snow: 4294638335,
  springgreen: 16744447,
  steelblue: 1182971135,
  tan: 3535047935,
  teal: 8421631,
  thistle: 3636451583,
  tomato: 4284696575,
  turquoise: 1088475391,
  violet: 4001558271,
  wheat: 4125012991,
  white: 4294967295,
  whitesmoke: 4126537215,
  yellow: 4294902015,
  yellowgreen: 2597139199
};
function normalizeColor(color) {
  const matchers = getMatchers();
  let match;
  if (matchers.hex6) {
    if (match = matchers.hex6.exec(color)) {
      return Number.parseInt(match[1] + "ff", 16) >>> 0;
    }
  }
  if (colorNames[color] !== undefined) {
    return colorNames[color];
  }
  if (matchers.rgb) {
    if (match = matchers.rgb.exec(color)) {
      return (parse255(match[1]) << 24 | parse255(match[2]) << 16 | parse255(match[3]) << 8 | 255) >>> 0;
    }
  }
  if (matchers.rgba) {
    if (match = matchers.rgba.exec(color)) {
      return (parse255(match[1]) << 24 | parse255(match[2]) << 16 | parse255(match[3]) << 8 | parse1(match[4])) >>> 0;
    }
  }
  if (matchers.hex3) {
    if (match = matchers.hex3.exec(color)) {
      return Number.parseInt(match[1] + match[1] + match[2] + match[2] + match[3] + match[3] + "ff", 16) >>> 0;
    }
  }
  if (matchers.hex8) {
    if (match = matchers.hex8.exec(color)) {
      return Number.parseInt(match[1], 16) >>> 0;
    }
  }
  if (matchers.hex4) {
    if (match = matchers.hex4.exec(color)) {
      return Number.parseInt(match[1] + match[1] + match[2] + match[2] + match[3] + match[3] + match[4] + match[4], 16) >>> 0;
    }
  }
  if (matchers.hsl) {
    if (match = matchers.hsl.exec(color)) {
      return (hslToRgb(parse360(match[1]), parsePercentage(match[2]), parsePercentage(match[3])) | 255) >>> 0;
    }
  }
  if (matchers.hsla) {
    if (match = matchers.hsla.exec(color)) {
      return (hslToRgb(parse360(match[1]), parsePercentage(match[2]), parsePercentage(match[3])) | parse1(match[4])) >>> 0;
    }
  }
  if (matchers.oklch) {
    if (match = matchers.oklch.exec(color)) {
      const L = parseModernComponent(match[1], 1);
      const C = parseModernComponent(match[2], 0.4);
      const H = parseHueAngle(match[3]);
      const alpha = parseModernAlpha(match[4]);
      const hRad = H * Math.PI / 180;
      const [r, g, b2] = oklabToSrgb(L, C * Math.cos(hRad), C * Math.sin(hRad));
      return rgbFloatToInt(r, g, b2, alpha);
    }
  }
  if (matchers.oklab) {
    if (match = matchers.oklab.exec(color)) {
      const L = parseModernComponent(match[1], 1);
      const a2 = parseModernComponent(match[2], 0.4);
      const b2 = parseModernComponent(match[3], 0.4);
      const alpha = parseModernAlpha(match[4]);
      const [r, g, bl] = oklabToSrgb(L, a2, b2);
      return rgbFloatToInt(r, g, bl, alpha);
    }
  }
  if (matchers.lab) {
    if (match = matchers.lab.exec(color)) {
      const L = parseModernComponent(match[1], 100);
      const a2 = parseModernComponent(match[2], 125);
      const b2 = parseModernComponent(match[3], 125);
      const alpha = parseModernAlpha(match[4]);
      const [r, g, bl] = labToSrgb(L, a2, b2);
      return rgbFloatToInt(r, g, bl, alpha);
    }
  }
  if (matchers.lch) {
    if (match = matchers.lch.exec(color)) {
      const L = parseModernComponent(match[1], 100);
      const C = parseModernComponent(match[2], 150);
      const H = parseHueAngle(match[3]);
      const alpha = parseModernAlpha(match[4]);
      const hRad = H * Math.PI / 180;
      const [r, g, bl] = labToSrgb(L, C * Math.cos(hRad), C * Math.sin(hRad));
      return rgbFloatToInt(r, g, bl, alpha);
    }
  }
  if (matchers.hwb) {
    if (match = matchers.hwb.exec(color)) {
      const H = parseHueAngle(match[1]);
      const W = parseModernComponent(match[2], 1);
      const B = parseModernComponent(match[3], 1);
      const alpha = parseModernAlpha(match[4]);
      const [r, g, bl] = hwbToSrgb(H / 360, W, B);
      return rgbFloatToInt(r, g, bl, alpha);
    }
  }
  throw new Error(`invalid color string ${color} provided`);
}
var opacity = (c2) => {
  return (c2 >> 24 & 255) / 255;
};
var red = (c2) => {
  return c2 >> 16 & 255;
};
var green = (c2) => {
  return c2 >> 8 & 255;
};
var blue = (c2) => {
  return c2 & 255;
};
var rgbaColor = (r, g, b2, alpha) => {
  return `rgba(${r}, ${g}, ${b2}, ${alpha})`;
};
function processColor(color) {
  const normalizedColor = normalizeColor(color);
  return (normalizedColor << 24 | normalizedColor >>> 8) >>> 0;
}
var interpolateColorsRGB = (value, inputRange, colors, options) => {
  const [r, g, b2, a2] = [red, green, blue, opacity].map((f) => {
    const unrounded = interpolate(value, inputRange, colors.map((c2) => f(c2)), {
      easing: options?.easing,
      extrapolateLeft: "clamp",
      extrapolateRight: "clamp",
      posterize: options?.posterize
    });
    if (f === opacity) {
      return Number(unrounded.toFixed(3));
    }
    return Math.round(unrounded);
  });
  return rgbaColor(r, g, b2, a2);
};
var interpolateColors = (input, inputRange, outputRange, options) => {
  if (typeof input === "undefined") {
    throw new TypeError("input can not be undefined");
  }
  if (typeof inputRange === "undefined") {
    throw new TypeError("inputRange can not be undefined");
  }
  if (typeof outputRange === "undefined") {
    throw new TypeError("outputRange can not be undefined");
  }
  if (inputRange.length !== outputRange.length) {
    throw new TypeError("inputRange (" + inputRange.length + " values provided) and outputRange (" + outputRange.length + " values provided) must have the same length");
  }
  const processedOutputRange = outputRange.map((c2) => processColor(c2));
  return interpolateColorsRGB(input, inputRange, processedOutputRange, options);
};

// src/interpolate-keyframed-status.ts
var easingToFn = ({
  easing,
  forceSpringAllowTail
}) => {
  switch (easing.type) {
    case "linear":
      return Easing.linear;
    case "step1":
      return Easing.step1;
    case "spring":
      return Easing.spring({
        allowTail: forceSpringAllowTail ?? easing.allowTail ?? undefined,
        damping: easing.damping,
        durationRestThreshold: easing.durationRestThreshold ?? undefined,
        mass: easing.mass,
        overshootClamping: easing.overshootClamping,
        stiffness: easing.stiffness
      });
    case "bezier":
      return bezier(easing.x1, easing.y1, easing.x2, easing.y2);
    default:
      throw new TypeError(`Unsupported easing: ${JSON.stringify(easing)}`);
  }
};
var interpolateKeyframedStatus = ({
  frame,
  forceSpringAllowTail,
  status
}) => {
  const { keyframes, easing, clamping, interpolationFunction } = status;
  if (keyframes.length === 0) {
    return null;
  }
  const sortedKeyframes = [...keyframes].sort((a2, b2) => a2.frame - b2.frame);
  const inputRange = sortedKeyframes.map((k) => k.frame);
  const outputs = sortedKeyframes.map((k) => k.value);
  if (interpolationFunction === "interpolateColors") {
    if (!outputs.every((v) => typeof v === "string")) {
      return null;
    }
    if (keyframes.length === 1) {
      return outputs[0];
    }
    try {
      return interpolateColors(frame, inputRange, outputs, {
        easing: easing.map((e) => easingToFn({ easing: e, forceSpringAllowTail })),
        posterize: status.posterize
      });
    } catch {
      return null;
    }
  }
  if (interpolationFunction !== "interpolate") {
    return null;
  }
  try {
    return interpolate(frame, inputRange, outputs, {
      easing: easing.map((e) => easingToFn({ easing: e, forceSpringAllowTail })),
      extrapolateLeft: clamping.left,
      extrapolateRight: clamping.right,
      output: status.output,
      posterize: status.posterize
    });
  } catch {
    return null;
  }
};

// src/get-effective-visual-mode-value.ts
var getFrameInKeyframedStatusClock = ({
  frame,
  status
}) => frame - (status.keyframeDisplayOffsetAdjustment ?? 0);
var resolveDragOverrideValue = ({
  dragOverrideValue,
  frame
}) => {
  if (dragOverrideValue === undefined) {
    return { type: "none" };
  }
  if (dragOverrideValue.type === "static") {
    return { type: "resolved", value: dragOverrideValue.value };
  }
  if (frame === null) {
    return { type: "none" };
  }
  const interpolated = interpolateKeyframedStatus({
    forceSpringAllowTail: null,
    frame: getFrameInKeyframedStatusClock({
      frame,
      status: dragOverrideValue.status
    }),
    status: dragOverrideValue.status
  });
  if (interpolated === null) {
    return { type: "none" };
  }
  return { type: "resolved", value: interpolated };
};
var getEffectiveVisualModeValue = ({
  propStatus,
  dragOverrideValue,
  defaultValue,
  frame = null,
  shouldResortToDefaultValueIfUndefined = false
}) => {
  const dragOverride = resolveDragOverrideValue({
    dragOverrideValue,
    frame
  });
  if (dragOverride.type === "resolved" && dragOverride.value !== undefined) {
    return dragOverride.value;
  }
  if (propStatus.status === "keyframed") {
    if (frame !== null) {
      return interpolateKeyframedStatus({
        forceSpringAllowTail: null,
        frame: getFrameInKeyframedStatusClock({ frame, status: propStatus }),
        status: propStatus
      });
    }
    return shouldResortToDefaultValueIfUndefined ? defaultValue : undefined;
  }
  if (propStatus.codeValue === undefined && shouldResortToDefaultValueIfUndefined) {
    return defaultValue;
  }
  return propStatus.codeValue;
};

// src/sequence-node-path.tsx
import { createContext as createContext16 } from "react";
var OverrideIdsToNodePathsGettersContext = createContext16({
  overrideIdToNodePathMappings: {}
});
var OverrideIdsToNodePathsSettersContext = createContext16({
  setOverrideIdToNodePath: () => {
    throw new Error("OverrideIdsToNodePathsSettersContext not initialized");
  }
});

// src/effects/use-memoized-effects.ts
var mergeOverrides = ({
  descriptor,
  propStatusOverrides,
  dragOverrides,
  frame
}) => {
  if (!propStatusOverrides && !dragOverrides) {
    return { params: descriptor.params, effectKey: descriptor.effectKey };
  }
  const merged = {
    ...descriptor.params
  };
  if (propStatusOverrides) {
    for (const [key, value] of Object.entries(propStatusOverrides)) {
      if (value !== undefined) {
        merged[key] = value;
      }
    }
  }
  if (dragOverrides) {
    for (const [key, value] of Object.entries(dragOverrides)) {
      const resolved = resolveDragOverrideValue({
        dragOverrideValue: value,
        frame
      });
      if (resolved.type === "resolved") {
        merged[key] = resolved.value;
      }
    }
  }
  return {
    params: merged,
    effectKey: descriptor.definition.calculateKey(merged)
  };
};
var resolvePropStatusOverrides = (propStatus, frame) => {
  if (!propStatus) {
    return null;
  }
  const out = {};
  let hasAny = false;
  for (const [key, status] of Object.entries(propStatus)) {
    if (status.status === "static") {
      out[key] = status.codeValue;
      hasAny = true;
      continue;
    }
    if (status.status === "keyframed") {
      const value = interpolateKeyframedStatus({
        forceSpringAllowTail: null,
        frame,
        status
      });
      if (value !== null) {
        out[key] = value;
        hasAny = true;
      }
    }
  }
  return hasAny ? out : null;
};
var useMemoizedEffectDefinitions = (effects) => {
  const previousRef = useRef5(null);
  const definitions = effects.map((descriptor) => descriptor.definition);
  const previous = previousRef.current;
  const isSame = previous !== null && previous.definitions.length === definitions.length && previous.definitions.every((definition, i) => definition === definitions[i]);
  const controllers = isSame ? previous.controllers : effects.map((effect) => createRuntimeValueStore(effect.params));
  const stableDefinitions = isSame ? previous.definitions : definitions;
  useLayoutEffect3(() => {
    stableDefinitions.forEach((_definition, index) => {
      const snapshot = effects[index]?.params;
      controllers[index].setSnapshot(snapshot);
    });
  }, [controllers, effects, stableDefinitions]);
  previousRef.current = { definitions: stableDefinitions, controllers };
  return Object.assign(stableDefinitions, {
    runtimeValues: controllers.map((controller) => controller.store)
  });
};
var getEffectPropStatusesCtx = ({
  propStatuses,
  nodePath,
  effectIndex
}) => {
  const status = propStatuses[makeSequencePropsSubscriptionKey(nodePath)];
  if (!status) {
    return { type: "cannot-update-sequence", reason: "not-found" };
  }
  if (!status.canUpdate) {
    return { type: "cannot-update-sequence", reason: status.reason };
  }
  const effect = status.effects.find((e) => e.effectIndex === effectIndex);
  if (!effect) {
    return { type: "cannot-update-effect", reason: "not-found" };
  }
  if (!effect.canUpdate) {
    return { type: "cannot-update-effect", reason: effect.reason };
  }
  return { type: "can-update-effect", props: effect.props };
};
var getPropStatusesCtx = (propStatuses, nodePath) => {
  const status = propStatuses[makeSequencePropsSubscriptionKey(nodePath)];
  if (!status) {
    return;
  }
  if (!status.canUpdate) {
    return;
  }
  return status.props;
};
var useMemoizedEffects = ({
  effects,
  overrideId
}) => {
  const previousRef = useRef5(null);
  const { propStatuses } = useContext18(VisualModePropStatusesContext);
  const { getEffectDragOverrides } = useContext18(VisualModeDragOverridesContext);
  const frame = useCurrentFrame();
  const { overrideIdToNodePathMappings } = useContext18(OverrideIdsToNodePathsGettersContext);
  const previous = previousRef.current;
  const nodePath = overrideId ? overrideIdToNodePathMappings[overrideId] ?? null : null;
  const resolved = effects.map((descriptor, index) => {
    if (nodePath === null) {
      return {
        descriptor,
        params: descriptor.params,
        effectKey: descriptor.effectKey
      };
    }
    const effectStatus = getEffectPropStatusesCtx({
      propStatuses,
      nodePath,
      effectIndex: index
    });
    const propStatusOverrides = effectStatus.type === "can-update-effect" ? resolvePropStatusOverrides(effectStatus.props, frame) : null;
    const dragOverridesMap = getEffectDragOverrides(nodePath, index);
    const dragOverrides = Object.keys(dragOverridesMap).length === 0 ? null : dragOverridesMap;
    const { params, effectKey } = mergeOverrides({
      descriptor,
      propStatusOverrides,
      dragOverrides,
      frame
    });
    return { descriptor, params, effectKey };
  });
  const isSame = previous !== null && previous.length === resolved.length && previous.every((p, i) => p.definition === resolved[i].descriptor.definition && p.effectKey === resolved[i].effectKey);
  if (isSame) {
    return previous;
  }
  const next = resolved.map(({ descriptor, params, effectKey }) => ({
    definition: descriptor.definition,
    effectKey,
    params,
    memoized: true
  }));
  previousRef.current = next;
  return next;
};

// src/flatten-schema.ts
var flattenActiveSchema = (schema, resolve) => {
  const out = {};
  for (const key of Object.keys(schema)) {
    const field = schema[key];
    if (field.type === "hidden") {
      continue;
    } else if (field.type === "enum") {
      out[key] = field;
      const current = resolve(key) ?? field.default;
      const variant = field.variants[current];
      if (variant) {
        Object.assign(out, flattenActiveSchema(variant, resolve));
      }
    } else {
      out[key] = field;
    }
  }
  return out;
};
var getFlatSchemaWithAllKeys = (schema) => {
  const out = {};
  const addKey = (key, field) => {
    if (key in out) {
      return;
    }
    out[key] = field;
  };
  for (const key of Object.keys(schema)) {
    const field = schema[key];
    addKey(key, field);
    if (field.type === "enum") {
      for (const variant of Object.values(field.variants)) {
        const flatVariant = getFlatSchemaWithAllKeys(variant);
        for (const variantKey of Object.keys(flatVariant)) {
          addKey(variantKey, flatVariant[variantKey]);
        }
      }
    }
  }
  return out;
};

// src/find-props-to-delete.ts
var findPropsToDelete = ({
  schema,
  key,
  value
}) => {
  const fieldSchema = schema[key];
  if (!fieldSchema) {
    throw new Error("Key " + JSON.stringify(key) + " not found in schema");
  }
  if (typeof value !== "string") {
    throw new Error("Value must be a string, but is " + JSON.stringify(value));
  }
  if (fieldSchema.type !== "enum") {
    throw new Error("Key " + JSON.stringify(key) + " is not an enum");
  }
  const currentVariant = fieldSchema.variants[value];
  if (!currentVariant) {
    throw new Error("Value for " + JSON.stringify(key) + " must be one of " + Object.keys(fieldSchema.variants).map((v) => JSON.stringify(v)).join(", ") + ", got " + JSON.stringify(value));
  }
  const otherVariants = Object.keys(fieldSchema.variants).filter((v) => v !== value);
  const otherKeys = new Set;
  for (const variant of otherVariants) {
    const otherVariant = fieldSchema.variants[variant];
    const keys = Object.keys(otherVariant);
    for (const k of keys) {
      otherKeys.add(k);
    }
  }
  return [...otherKeys];
};

// src/use-schema.ts
var DEFAULT_LINEAR_EASING = {
  type: "linear"
};
var getEasingIndexToDuplicate = ({
  insertedKeyframeIndex,
  easingLength,
  keyframeCount
}) => {
  const isSplittingExistingSegment = insertedKeyframeIndex > 0 && insertedKeyframeIndex < keyframeCount - 1;
  if (!isSplittingExistingSegment || easingLength === 0) {
    return null;
  }
  return Math.min(insertedKeyframeIndex - 1, easingLength - 1);
};
var makeStaticDragOverride = (value) => {
  return { type: "static", value };
};
var makeKeyframedDragOverride = ({
  status,
  frame,
  value,
  defaultEasing: defaultEasing2 = DEFAULT_LINEAR_EASING
}) => {
  const existingIndex = status.keyframes.findIndex((keyframe) => keyframe.frame === frame);
  const keyframes = existingIndex === -1 ? [...status.keyframes, { frame, value }].sort((first, second) => first.frame - second.frame) : status.keyframes.map((keyframe, index) => index === existingIndex ? { frame, value } : keyframe);
  const easing = [...status.easing];
  if (existingIndex === -1) {
    const insertedKeyframeIndex = keyframes.findIndex((keyframe) => keyframe.frame === frame);
    const easingIndexToDuplicate = getEasingIndexToDuplicate({
      insertedKeyframeIndex,
      easingLength: easing.length,
      keyframeCount: keyframes.length
    });
    const easingToDuplicate = easingIndexToDuplicate === null ? defaultEasing2 : easing[easingIndexToDuplicate];
    easing.splice(insertedKeyframeIndex, 0, easingToDuplicate);
  }
  while (easing.length < keyframes.length - 1) {
    easing.push(defaultEasing2);
  }
  if (easing.length > keyframes.length - 1) {
    easing.length = keyframes.length - 1;
  }
  return {
    type: "keyframed",
    status: {
      ...status,
      keyframes,
      easing
    }
  };
};
var getStaticDragOverrideValue = (dragOverrideValue) => {
  if (dragOverrideValue?.type !== "static") {
    return;
  }
  return dragOverrideValue.value;
};
var isKeyframedStatus = (status) => {
  return status !== null && status.status === "keyframed";
};
var findFieldInSchema = (schema, key) => {
  if (key in schema) {
    return schema[key];
  }
  for (const field of Object.values(schema)) {
    if (field.type !== "enum") {
      continue;
    }
    for (const variant of Object.values(field.variants)) {
      const found = findFieldInSchema(variant, key);
      if (found) {
        return found;
      }
    }
  }
  return;
};
var computeEffectiveSchemaValuesDotNotation = ({
  schema,
  currentValue,
  overrideValues,
  propStatus,
  frame
}) => {
  const merged = {};
  const propsToDelete = new Set;
  for (const key of Object.keys(currentValue)) {
    const status = propStatus?.[key] ?? null;
    const field = findFieldInSchema(schema, key);
    if (field?.type === "hidden") {
      continue;
    }
    let value;
    if (status === null) {
      value = currentValue[key];
    } else if (isKeyframedStatus(status)) {
      if (field?.type === "array" || field?.keyframable === false) {
        value = currentValue[key];
      } else {
        const dragOverride = resolveDragOverrideValue({
          dragOverrideValue: overrideValues[key],
          frame
        });
        if (dragOverride.type === "resolved") {
          value = dragOverride.value;
        } else if (frame !== null) {
          const interpolated = interpolateKeyframedStatus({
            forceSpringAllowTail: null,
            frame: getFrameInKeyframedStatusClock({ frame, status }),
            status
          });
          value = interpolated ?? currentValue[key];
        } else {
          value = currentValue[key];
        }
      }
    } else if (status.status === "computed") {
      value = currentValue[key];
    } else {
      value = getEffectiveVisualModeValue({
        propStatus: status,
        dragOverrideValue: overrideValues[key],
        defaultValue: field?.default,
        frame,
        shouldResortToDefaultValueIfUndefined: false
      });
    }
    if (field?.type === "asset" && typeof value === "string" && value.startsWith(FILE_TOKEN)) {
      value = resolveFileTokenToUrl(value);
    }
    if (value === undefined) {
      propsToDelete.add(key);
    }
    merged[key] = value;
  }
  for (const key of Object.keys(overrideValues)) {
    if (schema[key]?.type === "enum") {
      const propsToDeleteForKey = findPropsToDelete({
        schema,
        key,
        value: merged[key]
      });
      for (const propToDelete of propsToDeleteForKey) {
        propsToDelete.add(propToDelete);
      }
    }
  }
  return { merged, propsToDelete };
};

// src/with-interactivity-schema.ts
var getNestedValue = (obj, key) => {
  const parts = key.split(".");
  let current = obj;
  for (const part of parts) {
    if (current === null || current === undefined || typeof current !== "object")
      return;
    current = current[part];
  }
  return current;
};
var getRuntimeValueForSchemaKey = ({
  flatSchema,
  key,
  props
}) => {
  const value = getNestedValue(props, key);
  if (flatSchema[key]?.type === "text-content" && typeof value !== "string") {
    return;
  }
  return value;
};
var readValuesFromProps = (props, keys, flatSchema) => {
  const out = {};
  for (const key of keys) {
    out[key] = flatSchema ? getRuntimeValueForSchemaKey({ flatSchema, key, props }) : getNestedValue(props, key);
  }
  return out;
};
var selectActiveKeys = (schema, values) => {
  return Object.keys(flattenActiveSchema(schema, (key) => values[key]));
};
var mergeValues = ({
  flatSchema,
  props,
  valuesDotNotation,
  schemaKeys,
  propsToDelete
}) => {
  const merged = { ...props };
  for (const key of schemaKeys) {
    const value = valuesDotNotation[key];
    if (flatSchema[key]?.type === "text-content" && value === undefined) {
      continue;
    }
    const parts = key.split(".");
    if (parts.length === 1) {
      merged[key] = value;
      continue;
    }
    let current = merged;
    for (let i = 0;i < parts.length - 1; i++) {
      const part = parts[i];
      if (typeof current[part] === "object" && current[part] !== null) {
        current[part] = { ...current[part] };
      } else {
        current[part] = {};
      }
      current = current[part];
    }
    current[parts[parts.length - 1]] = value;
  }
  const propsToDeleteWithoutTextContent = new Set([...propsToDelete].filter((key) => !(flatSchema[key]?.type === "text-content" && valuesDotNotation[key] === undefined)));
  deleteNestedKey(merged, propsToDeleteWithoutTextContent);
  return merged;
};
var stackToOverrideMap = {};
var DisableInteractivityContext = createContext17(false);
var DisableInteractivityProvider = ({ children }) => {
  return React16.createElement(DisableInteractivityContext.Provider, { value: true }, children);
};
var withInteractivitySchema = ({
  Component,
  componentName,
  componentIdentity = null,
  schema,
  supportsEffects
}) => {
  const schemaWithSequenceName = extendSchemaWithSequenceName(schema);
  const flatSchema = getFlatSchemaWithAllKeys(schemaWithSequenceName);
  const flatKeys = Object.keys(flatSchema);
  const Wrapped = forwardRef2((props, ref) => {
    const {
      _remotionInternalStack: internalStack,
      ...propsWithoutInternalStack
    } = props;
    const cleanProps = propsWithoutInternalStack;
    const env = useRemotionEnvironment();
    const canUseRemotionHooks = useContext19(CanUseRemotionHooks);
    const disableInteractivity = useContext19(DisableInteractivityContext);
    if (!env.isStudio || env.isRendering || !canUseRemotionHooks || disableInteractivity) {
      return React16.createElement(Component, {
        ...cleanProps,
        controls: null,
        ref
      });
    }
    const { propStatuses } = useContext19(VisualModePropStatusesContext);
    const { getDragOverrides } = useContext19(VisualModeDragOverridesContext);
    const nodePathMapping = useContext19(OverrideIdsToNodePathsGettersContext);
    const frame = useCurrentFrame();
    const videoConfig = useUnsafeVideoConfig();
    const durationInFrames = videoConfig?.durationInFrames;
    const fps = videoConfig?.fps;
    const height = videoConfig?.height;
    const width = videoConfig?.width;
    const videoConfigValues = useMemo12(() => durationInFrames === undefined || fps === undefined || height === undefined || width === undefined ? null : {
      durationInFrames,
      fps,
      height,
      width
    }, [durationInFrames, fps, height, width]);
    if (cleanProps.controls) {
      const passedControls = cleanProps.controls;
      if (getStackForControls(passedControls) === null) {
        setStackForControls(passedControls, internalStack);
      }
      return React16.createElement(Component, {
        ...cleanProps,
        ref
      });
    }
    const [overrideId] = useState5(() => {
      if (!internalStack) {
        return String(Math.random());
      }
      const existingOverrideId = stackToOverrideMap[internalStack];
      if (existingOverrideId) {
        return existingOverrideId;
      }
      const newOverrideId = String(Math.random());
      stackToOverrideMap[internalStack] = newOverrideId;
      return newOverrideId;
    });
    const nodePath = env.isReadOnlyStudio ? null : nodePathMapping.overrideIdToNodePathMappings[overrideId] ?? null;
    const runtimeValues = flatKeys.map((key) => getRuntimeValueForSchemaKey({
      flatSchema,
      key,
      props: cleanProps
    }));
    const currentRuntimeValueDotNotation = useMemo12(() => readValuesFromProps(cleanProps, flatKeys, flatSchema), runtimeValues);
    const [runtimeValueStore] = useState5(() => createRuntimeValueStore(currentRuntimeValueDotNotation));
    useLayoutEffect4(() => {
      runtimeValueStore.setSnapshot(currentRuntimeValueDotNotation);
    }, [currentRuntimeValueDotNotation, runtimeValueStore]);
    const controls = useMemo12(() => {
      return {
        schema: schemaWithSequenceName,
        currentRuntimeValueDotNotation,
        runtimeValues: runtimeValueStore.store,
        videoConfigValues,
        overrideId,
        supportsEffects,
        componentIdentity,
        componentName
      };
    }, [
      currentRuntimeValueDotNotation,
      overrideId,
      runtimeValueStore.store,
      videoConfigValues
    ]);
    setStackForControls(controls, internalStack);
    const { merged: valuesDotNotation, propsToDelete } = useMemo12(() => {
      return computeEffectiveSchemaValuesDotNotation({
        schema: schemaWithSequenceName,
        currentValue: currentRuntimeValueDotNotation,
        overrideValues: nodePath === null ? {} : getDragOverrides(nodePath),
        propStatus: nodePath === null ? undefined : getPropStatusesCtx(propStatuses, nodePath),
        frame
      });
    }, [
      currentRuntimeValueDotNotation,
      getDragOverrides,
      nodePath,
      propStatuses,
      frame
    ]);
    const activeKeys = selectActiveKeys(schemaWithSequenceName, valuesDotNotation);
    const mergedProps = mergeValues({
      flatSchema,
      props: cleanProps,
      valuesDotNotation,
      schemaKeys: activeKeys,
      propsToDelete
    });
    return React16.createElement(Component, {
      ...mergedProps,
      controls,
      ref
    });
  });
  Wrapped.displayName = `withInteractivitySchema(${Component.displayName || Component.name || "Component"})`;
  return Wrapped;
};

// src/Sequence.tsx
import { jsx as jsx12 } from "react/jsx-runtime";
var EMPTY_EFFECTS = [];
var RegularSequenceRefForwardingFunction = ({
  from = 0,
  trimBefore = 0,
  freeze,
  durationInFrames = Infinity,
  children,
  name,
  height,
  width,
  showInTimeline = true,
  hidden = false,
  controls,
  _remotionInternalEffects,
  _remotionInternalLoopDisplay: loopDisplay,
  _remotionInternalStack: stack,
  _remotionInternalDocumentationLink: documentationLink,
  _remotionInternalSingleChildComponent: singleChildComponent,
  _remotionInternalPremountDisplay: premountDisplay,
  _remotionInternalPostmountDisplay: postmountDisplay,
  _remotionInternalIsMedia: isMedia,
  outlineRef: passedRefForOutline,
  cropLeft,
  cropRight,
  cropTop,
  cropBottom,
  ...other
}, ref) => {
  const { layout = "absolute-fill" } = other;
  const [id] = useState6(() => String(Math.random()));
  const parentSequence = useContext20(SequenceContext);
  const cumulatedFrom = parentSequence ? parentSequence.cumulatedFrom + parentSequence.relativeFrom : 0;
  if (layout !== "absolute-fill" && layout !== "none") {
    throw new TypeError(`The layout prop of <Sequence /> expects either "absolute-fill" or "none", but you passed: ${layout}`);
  }
  const cropProps = { cropLeft, cropRight, cropTop, cropBottom };
  const hasCropProp = Object.values(cropProps).some((value) => value !== undefined);
  if (layout === "none" && hasCropProp) {
    throw new TypeError('The cropLeft, cropRight, cropTop and cropBottom props of <Sequence /> are only supported with layout="absolute-fill".');
  }
  validateSequenceCrop(cropProps);
  const {
    left: resolvedCropLeft,
    right: resolvedCropRight,
    top: resolvedCropTop,
    bottom: resolvedCropBottom
  } = resolveSequenceCrop(cropProps);
  if (layout === "none" && typeof other.style !== "undefined") {
    throw new TypeError('If layout="none", you may not pass a style. Passed: ' + JSON.stringify(other.style));
  }
  if (typeof durationInFrames !== "number") {
    throw new TypeError(`You passed to durationInFrames an argument of type ${typeof durationInFrames}, but it must be a number.`);
  }
  if (durationInFrames <= 0) {
    throw new TypeError(`durationInFrames must be positive, but got ${durationInFrames}`);
  }
  if (typeof from !== "number") {
    throw new TypeError(`You passed to the "from" props of your <Sequence> an argument of type ${typeof from}, but it must be a number.`);
  }
  if (!Number.isFinite(from)) {
    throw new TypeError(`The "from" prop of a sequence must be finite, but got ${from}.`);
  }
  if (typeof trimBefore !== "number") {
    throw new TypeError(`You passed to the "trimBefore" prop of your <Sequence> an argument of type ${typeof trimBefore}, but it must be a number.`);
  }
  if (trimBefore < 0) {
    throw new TypeError(`The "trimBefore" prop of <Sequence /> must be greater than or equal to 0, but got ${trimBefore}.`);
  }
  if (Number.isNaN(trimBefore)) {
    throw new TypeError('The "trimBefore" prop of <Sequence /> must be a real number, but it is NaN.');
  }
  if (!Number.isFinite(trimBefore)) {
    throw new TypeError(`The "trimBefore" prop of <Sequence /> must be finite, but it is ${trimBefore}.`);
  }
  if (typeof freeze !== "undefined" && freeze !== null) {
    if (typeof freeze !== "number") {
      throw new TypeError(`The "freeze" prop of <Sequence /> must be a number, but is of type ${typeof freeze}.`);
    }
    if (Number.isNaN(freeze)) {
      throw new TypeError(`The "freeze" prop of <Sequence /> must be a real number, but it is NaN.`);
    }
    if (!Number.isFinite(freeze)) {
      throw new TypeError(`The "freeze" prop of <Sequence /> must be finite, but it is ${freeze}.`);
    }
  }
  const absoluteFrame = useTimelinePosition();
  const videoConfig = useVideoConfig();
  const effectiveRelativeFrom = from - trimBefore;
  const absoluteFrom = (parentSequence?.absoluteFrom ?? 0) + effectiveRelativeFrom;
  const parentSequenceDuration = parentSequence ? Math.min(parentSequence.durationInFrames - effectiveRelativeFrom, durationInFrames) : durationInFrames;
  const actualDurationInFrames = Math.max(0, Math.min(videoConfig.durationInFrames - from, parentSequenceDuration));
  const sequenceRegistrationEnabled = useContext20(SequenceRegistrationContext);
  const wrapperRefForOutline = useRef6(null);
  const refForOutline = other.layout === "none" ? passedRefForOutline ?? null : passedRefForOutline ?? wrapperRefForOutline;
  const premounting = useMemo13(() => {
    return parentSequence?.premounting || Boolean(other._remotionInternalIsPremounting);
  }, [other._remotionInternalIsPremounting, parentSequence?.premounting]);
  const postmounting = useMemo13(() => {
    return parentSequence?.postmounting || Boolean(other._remotionInternalIsPostmounting);
  }, [other._remotionInternalIsPostmounting, parentSequence?.postmounting]);
  const currentSequenceStart = cumulatedFrom + effectiveRelativeFrom;
  const parentSequenceStart = parentSequence ? parentSequence.cumulatedFrom + parentSequence.relativeFrom : 0;
  const parentFirstFrame = parentSequence ? parentSequenceStart - parentSequence.cumulatedNegativeFrom : 0;
  const firstFrame = Math.max(0, parentFirstFrame, currentSequenceStart);
  const cumulatedNegativeFrom = currentSequenceStart - firstFrame;
  const contextValue = useMemo13(() => {
    return {
      absoluteFrom,
      cumulatedFrom,
      relativeFrom: effectiveRelativeFrom,
      cumulatedNegativeFrom,
      durationInFrames: actualDurationInFrames,
      parentFrom: parentSequence?.relativeFrom ?? 0,
      id,
      height: height ?? parentSequence?.height ?? null,
      width: width ?? parentSequence?.width ?? null,
      premounting,
      postmounting,
      premountDisplay: premountDisplay ?? null,
      postmountDisplay: postmountDisplay ?? null
    };
  }, [
    cumulatedFrom,
    absoluteFrom,
    effectiveRelativeFrom,
    actualDurationInFrames,
    parentSequence,
    id,
    height,
    width,
    premounting,
    postmounting,
    premountDisplay,
    postmountDisplay,
    cumulatedNegativeFrom
  ]);
  const timelineClipName = useMemo13(() => {
    return name ?? "";
  }, [name]);
  const resolvedDocumentationLink = documentationLink ?? "https://www.remotion.dev/docs/sequence";
  const env = useRemotionEnvironment();
  const isInsideSeries = useContext20(IsInsideSeriesContext);
  const stackRef = useRef6(null);
  stackRef.current = controls ? getStackForControls(controls) ?? stack ?? null : stack ?? null;
  const registeredFrozenFrame = typeof freeze === "number" ? freeze : null;
  const registeredTrimBefore = trimBefore === 0 ? null : trimBefore;
  const parentCumulatedNegativeFrom = parentSequence?.cumulatedNegativeFrom ?? 0;
  const startMediaFrom = isMedia && isMedia.type !== "image" ? isMedia.data.startMediaFrom + parentCumulatedNegativeFrom - cumulatedNegativeFrom : null;
  const mediaFrameAtSequenceZero = isMedia && isMedia.type !== "image" ? isMedia.data.startMediaFrom + parentCumulatedNegativeFrom : null;
  const frozenMediaFrame = isMedia && isMedia.type !== "image" && mediaFrameAtSequenceZero !== null ? registeredFrozenFrame === null ? null : mediaFrameAtSequenceZero + (loopDisplay ? registeredFrozenFrame % loopDisplay.durationInFrames : registeredFrozenFrame) * isMedia.data.playbackRate : null;
  const controlsSchema = controls?.schema;
  const controlsRuntimeValues = controls?.runtimeValues;
  const controlsOverrideId = controls?.overrideId;
  const controlsSupportsEffects = controls?.supportsEffects;
  const controlsComponentIdentity = controls?.componentIdentity;
  const controlsComponentName = controls?.componentName;
  const controlsVideoConfigValues = controls?.videoConfigValues;
  const effectRuntimeValues = useMemo13(() => _remotionInternalEffects?.runtimeValues ?? null, [_remotionInternalEffects]);
  const registrationControls = useMemo13(() => {
    if (controlsSchema === undefined || controlsRuntimeValues === undefined || controlsOverrideId === undefined || controlsSupportsEffects === undefined || controlsComponentIdentity === undefined || controlsComponentName === undefined || controlsVideoConfigValues === undefined) {
      return null;
    }
    return {
      schema: controlsSchema,
      runtimeValues: controlsRuntimeValues,
      overrideId: controlsOverrideId,
      supportsEffects: controlsSupportsEffects,
      componentIdentity: controlsComponentIdentity,
      componentName: controlsComponentName,
      videoConfigValues: controlsVideoConfigValues
    };
  }, [
    controlsComponentIdentity,
    controlsComponentName,
    controlsVideoConfigValues,
    controlsOverrideId,
    controlsRuntimeValues,
    controlsSchema,
    controlsSupportsEffects
  ]);
  const getSequenceForRegistration = useCallback6(() => {
    if (isMedia) {
      if (isMedia.type === "image") {
        return {
          type: "image",
          controls: registrationControls,
          effects: _remotionInternalEffects ?? EMPTY_EFFECTS,
          effectRuntimeValues,
          displayName: timelineClipName,
          documentationLink: resolvedDocumentationLink,
          duration: actualDurationInFrames,
          from,
          trimBefore: registeredTrimBefore,
          id,
          loopDisplay,
          parent: parentSequence?.id ?? null,
          postmountDisplay: postmountDisplay ?? null,
          premountDisplay: premountDisplay ?? null,
          showInTimeline,
          timelineOrder: null,
          src: isMedia.src,
          getStack: () => stackRef.current,
          refForOutline: refForOutline ?? null,
          isInsideSeries,
          frozenFrame: registeredFrozenFrame,
          singleChildComponent: singleChildComponent ?? null
        };
      }
      return {
        type: isMedia.type,
        controls: registrationControls,
        effects: _remotionInternalEffects ?? EMPTY_EFFECTS,
        effectRuntimeValues,
        displayName: timelineClipName,
        documentationLink: resolvedDocumentationLink,
        doesVolumeChange: isMedia.data.doesVolumeChange,
        duration: actualDurationInFrames,
        from,
        trimBefore: registeredTrimBefore,
        id,
        loopDisplay,
        parent: parentSequence?.id ?? null,
        playbackRate: isMedia.data.playbackRate,
        postmountDisplay: postmountDisplay ?? null,
        premountDisplay: premountDisplay ?? null,
        showInTimeline,
        timelineOrder: null,
        src: isMedia.data.src,
        getStack: () => stackRef.current,
        startMediaFrom: startMediaFrom ?? isMedia.data.startMediaFrom,
        mediaFrameAtSequenceZero,
        volume: isMedia.data.volumes,
        muted: isMedia.data.muted,
        refForOutline: refForOutline ?? null,
        isInsideSeries,
        frozenFrame: registeredFrozenFrame,
        frozenMediaFrame,
        singleChildComponent: singleChildComponent ?? null
      };
    }
    return {
      from,
      trimBefore: registeredTrimBefore,
      duration: actualDurationInFrames,
      id,
      displayName: timelineClipName,
      documentationLink: resolvedDocumentationLink,
      parent: parentSequence?.id ?? null,
      type: "sequence",
      showInTimeline,
      timelineOrder: null,
      loopDisplay,
      getStack: () => stackRef.current,
      premountDisplay: premountDisplay ?? null,
      postmountDisplay: postmountDisplay ?? null,
      controls: registrationControls,
      effects: _remotionInternalEffects ?? EMPTY_EFFECTS,
      effectRuntimeValues,
      refForOutline: refForOutline ?? null,
      isInsideSeries,
      frozenFrame: registeredFrozenFrame,
      singleChildComponent: singleChildComponent ?? null
    };
  }, [
    id,
    timelineClipName,
    parentSequence?.id,
    actualDurationInFrames,
    from,
    registeredTrimBefore,
    showInTimeline,
    loopDisplay,
    premountDisplay,
    postmountDisplay,
    registrationControls,
    _remotionInternalEffects,
    effectRuntimeValues,
    isMedia,
    resolvedDocumentationLink,
    refForOutline,
    isInsideSeries,
    registeredFrozenFrame,
    startMediaFrom,
    mediaFrameAtSequenceZero,
    frozenMediaFrame,
    singleChildComponent
  ]);
  useSequenceRegistration({
    getSequence: env.isStudio || sequenceRegistrationEnabled ? getSequenceForRegistration : null,
    id
  });
  const endThreshold = Math.ceil(cumulatedFrom + from + durationInFrames - 1);
  const content2 = absoluteFrame < cumulatedFrom + from ? null : absoluteFrame > endThreshold ? null : children;
  const frozenContent = content2 === null || typeof freeze === "undefined" || freeze === null ? content2 : /* @__PURE__ */ jsx12(Freeze, {
    frame: freeze,
    children: content2
  });
  const styleIfThere = other.layout === "none" ? undefined : other.style;
  const cropClipPath = getSequenceCropClipPath({
    left: resolvedCropLeft,
    right: resolvedCropRight,
    top: resolvedCropTop,
    bottom: resolvedCropBottom,
    style: styleIfThere
  });
  const sequenceRef = useCallback6((node) => {
    wrapperRefForOutline.current = node;
    if (typeof ref === "function") {
      ref(node);
    } else if (ref) {
      ref.current = node;
    }
  }, [ref]);
  const defaultStyle = useMemo13(() => {
    return {
      flexDirection: undefined,
      ...width ? { width } : {},
      ...height ? { height } : {},
      ...styleIfThere ?? {},
      ...cropClipPath ? {
        clipPath: cropClipPath
      } : {}
    };
  }, [cropClipPath, height, styleIfThere, width]);
  if (ref !== null && layout === "none") {
    throw new TypeError('It is not supported to pass both a `ref` and `layout="none"` to <Sequence />.');
  }
  if (hidden) {
    return env.isStudio ? /* @__PURE__ */ jsx12(SequenceOrderMarker, {
      sequenceId: id,
      children: null
    }) : null;
  }
  const sequence = /* @__PURE__ */ jsx12(SequenceContext.Provider, {
    value: contextValue,
    children: frozenContent === null ? null : other.layout === "none" ? frozenContent : /* @__PURE__ */ jsx12(AbsoluteFillElement, {
      ref: sequenceRef,
      style: defaultStyle,
      className: other.className,
      children: frozenContent
    })
  });
  return env.isStudio ? /* @__PURE__ */ jsx12(SequenceOrderMarker, {
    sequenceId: id,
    children: sequence
  }) : sequence;
};
var RegularSequence = forwardRef3(RegularSequenceRefForwardingFunction);
var PremountedPostmountedSequenceRefForwardingFunction = (props, ref) => {
  if (props.layout === "none") {
    throw new Error('`<Sequence>` with `premountFor` and `postmountFor` props does not support layout="none"');
  }
  const {
    style: passedStyle,
    from = 0,
    durationInFrames = Infinity,
    premountFor = 0,
    postmountFor = 0,
    styleWhilePremounted,
    styleWhilePostmounted,
    ...otherProps
  } = props;
  const {
    freezeFrame,
    isPremountingOrPostmounting,
    postmountingActive,
    premountingActive,
    premountingStyle
  } = usePremounting({
    from,
    durationInFrames,
    premountFor,
    postmountFor,
    style: passedStyle ?? null,
    styleWhilePremounted: styleWhilePremounted ?? null,
    styleWhilePostmounted: styleWhilePostmounted ?? null,
    hideWhilePremounted: "opacity"
  });
  return /* @__PURE__ */ jsx12(Freeze, {
    frame: freezeFrame,
    active: isPremountingOrPostmounting,
    children: /* @__PURE__ */ jsx12(SequenceInner, {
      ref,
      from,
      durationInFrames,
      style: premountingStyle ?? undefined,
      _remotionInternalPremountDisplay: premountFor,
      _remotionInternalPostmountDisplay: postmountFor,
      _remotionInternalIsPremounting: premountingActive,
      _remotionInternalIsPostmounting: postmountingActive,
      ...otherProps
    })
  });
};
var PremountedPostmountedSequence = forwardRef3(PremountedPostmountedSequenceRefForwardingFunction);
var SequenceRefForwardingFunction = (props, ref) => {
  const env = useRemotionEnvironment();
  const { fps } = useVideoConfig();
  if (props.layout !== "none" && !env.isRendering) {
    const effectivePremountFor = ENABLE_V5_BREAKING_CHANGES ? props.premountFor ?? fps : props.premountFor;
    if (effectivePremountFor || props.postmountFor) {
      return /* @__PURE__ */ jsx12(PremountedPostmountedSequence, {
        ref,
        ...props,
        premountFor: effectivePremountFor
      });
    }
  }
  return /* @__PURE__ */ jsx12(RegularSequence, {
    ...props,
    ref
  });
};
var SequenceInner = forwardRef3(SequenceRefForwardingFunction);
var SequenceWithoutSchema = SequenceInner;
var Sequence = withInteractivitySchema({
  Component: SequenceInner,
  componentName: "<Sequence>",
  componentIdentity: "dev.remotion.remotion.Sequence",
  schema: sequenceSchema,
  supportsEffects: false
});
var SequenceWithoutFrom = withInteractivitySchema({
  Component: SequenceInner,
  componentName: "<Sequence>",
  componentIdentity: null,
  schema: sequenceSchemaWithoutFrom,
  supportsEffects: false
});

// src/AbsoluteFill.tsx
import { useCallback as useCallback7, useRef as useRef7 } from "react";
import { jsx as jsx13 } from "react/jsx-runtime";
var absoluteFillSchema = {
  ...baseSchema,
  ...transformSchema,
  ...backgroundSchema,
  ...borderSchema,
  ...borderRadiusSchema,
  ...textSchema,
  ...textContentSchema
};
var setRef = (ref, value) => {
  if (typeof ref === "function") {
    ref(value);
  } else if (ref) {
    ref.current = value;
  }
};
var AbsoluteFillInner = ({
  ref,
  from,
  trimBefore,
  freeze,
  durationInFrames,
  hidden,
  name,
  showInTimeline,
  stack,
  controls,
  children,
  ...divProps
}) => {
  const videoConfig = useUnsafeVideoConfig();
  const refForOutline = useRef7(null);
  const callbackRef = useCallback7((element) => {
    refForOutline.current = element;
    setRef(ref, element);
  }, [ref]);
  if (videoConfig === null) {
    return hidden ? null : /* @__PURE__ */ jsx13(AbsoluteFillElement, {
      ref: callbackRef,
      ...divProps,
      children
    });
  }
  return /* @__PURE__ */ jsx13(Sequence, {
    layout: "none",
    from: from ?? 0,
    trimBefore,
    freeze,
    durationInFrames: durationInFrames ?? Infinity,
    hidden,
    name: name ?? "<AbsoluteFill>",
    showInTimeline: showInTimeline ?? true,
    controls,
    _remotionInternalStack: stack,
    _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/absolute-fill",
    outlineRef: refForOutline,
    children: /* @__PURE__ */ jsx13(AbsoluteFillElement, {
      ref: callbackRef,
      ...divProps,
      children
    })
  });
};
var AbsoluteFill = withInteractivitySchema({
  Component: AbsoluteFillInner,
  componentName: "<AbsoluteFill>",
  componentIdentity: "dev.remotion.remotion.AbsoluteFill",
  schema: absoluteFillSchema,
  supportsEffects: false
});
addSequenceStackTraces(AbsoluteFill);
// src/animated-image/AnimatedImage.tsx
import {
  forwardRef as forwardRef4,
  useEffect as useEffect6,
  useImperativeHandle as useImperativeHandle2,
  useLayoutEffect as useLayoutEffect5,
  useRef as useRef10,
  useState as useState7
} from "react";

// src/use-crop-style.ts
import { useMemo as useMemo14 } from "react";
var useCropStyle = ({
  cropLeft,
  cropRight,
  cropTop,
  cropBottom,
  style,
  componentName
}) => {
  validateSequenceCrop({ cropLeft, cropRight, cropTop, cropBottom }, componentName);
  return useMemo14(() => {
    const cropClipPath = getSequenceCropClipPath({
      ...resolveSequenceCrop({ cropLeft, cropRight, cropTop, cropBottom }),
      style
    });
    if (cropClipPath === null) {
      return style;
    }
    return { ...style, clipPath: cropClipPath };
  }, [cropBottom, cropLeft, cropRight, cropTop, style]);
};

// src/animated-image/canvas.tsx
import React19, { useCallback as useCallback8, useImperativeHandle, useMemo as useMemo16, useRef as useRef9 } from "react";

// src/calculate-image-fit.ts
var calculateImageFit = (fit, imageSize, canvasSize) => {
  switch (fit) {
    case "fill": {
      return [
        0,
        0,
        imageSize.width,
        imageSize.height,
        0,
        0,
        canvasSize.width,
        canvasSize.height
      ];
    }
    case "contain": {
      const ratio = Math.min(canvasSize.width / imageSize.width, canvasSize.height / imageSize.height);
      const centerX = (canvasSize.width - imageSize.width * ratio) / 2;
      const centerY = (canvasSize.height - imageSize.height * ratio) / 2;
      return [
        0,
        0,
        imageSize.width,
        imageSize.height,
        centerX,
        centerY,
        imageSize.width * ratio,
        imageSize.height * ratio
      ];
    }
    case "cover": {
      const ratio = Math.max(canvasSize.width / imageSize.width, canvasSize.height / imageSize.height);
      const centerX = (canvasSize.width - imageSize.width * ratio) / 2;
      const centerY = (canvasSize.height - imageSize.height * ratio) / 2;
      return [
        0,
        0,
        imageSize.width,
        imageSize.height,
        centerX,
        centerY,
        imageSize.width * ratio,
        imageSize.height * ratio
      ];
    }
    default:
      throw new Error("Unknown fit: " + fit);
  }
};

// src/effects/webgl2-context-error.ts
var WEBGL_CONTEXT_DOCS_URL = "https://remotion.dev/docs/troubleshooting/webgl2-context";
var webGlContextErrorMessage = (versionLabel, effectName) => `Failed to acquire ${versionLabel} context for ${effectName}. ` + 'Pass --gl=angle when using the CLI, set chromiumOptions: { gl: "angle" } when using SSR APIs, ' + 'or set "OpenGL render backend" to "angle" in the Advanced section when rendering in the Studio. ' + `See ${WEBGL_CONTEXT_DOCS_URL}`;
var createWebGLContextError = (effectName) => new Error(webGlContextErrorMessage("WebGL", effectName));
var createWebGL2ContextError = (effectName) => new Error(webGlContextErrorMessage("WebGL2", effectName));

// src/effects/canvas-pool.ts
class CanvasPool {
  width;
  height;
  pairs = new Map;
  lostContexts = new Set;
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }
  getPair(backend) {
    const existing = this.pairs.get(backend);
    if (existing) {
      return existing;
    }
    const pair = [
      this.allocateCanvas(backend),
      this.allocateCanvas(backend)
    ];
    this.pairs.set(backend, pair);
    return pair;
  }
  assertContextNotLost(canvas) {
    if (this.lostContexts.has(canvas)) {
      throw new Error("WebGL context was lost during canvas effect rendering. " + "This typically happens in headless or memory-constrained environments (e.g. Remotion Lambda). " + "Try reducing concurrency or increasing the Lambda function memory.");
    }
  }
  allocateCanvas(backend) {
    const canvas = document.createElement("canvas");
    canvas.width = this.width;
    canvas.height = this.height;
    switch (backend) {
      case "2d": {
        const ctx = canvas.getContext("2d", {
          colorSpace: "srgb"
        });
        if (!ctx) {
          throw new Error("Failed to acquire 2D context for canvas effect");
        }
        return canvas;
      }
      case "webgl2": {
        const ctx = canvas.getContext("webgl2", {
          premultipliedAlpha: true,
          alpha: true,
          preserveDrawingBuffer: true
        });
        if (!ctx) {
          throw createWebGL2ContextError("canvas effect");
        }
        canvas.addEventListener("webglcontextlost", (e) => {
          e.preventDefault();
          this.lostContexts.add(canvas);
        });
        canvas.addEventListener("webglcontextrestored", () => {
          this.lostContexts.delete(canvas);
        });
        ctx.pixelStorei(ctx.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
        return canvas;
      }
      case "webgpu": {
        if (typeof navigator === "undefined" || !("gpu" in navigator)) {
          throw new Error("WebGPU is not available in this environment for canvas effect");
        }
        return canvas;
      }
      default: {
        const exhaustive = backend;
        throw new Error(`Unknown effect backend: ${exhaustive}`);
      }
    }
  }
}

// src/effects/effect-internals.ts
var groupByBackend = (effects) => {
  const runs = [];
  let current = [];
  let currentBackend = null;
  for (const eff of effects) {
    const { backend } = eff.definition;
    if (currentBackend === null || backend === currentBackend) {
      current.push(eff);
      currentBackend = backend;
    } else {
      runs.push({ backend: currentBackend, effects: current });
      current = [eff];
      currentBackend = backend;
    }
  }
  if (currentBackend !== null && current.length > 0) {
    runs.push({ backend: currentBackend, effects: current });
  }
  return runs;
};

// src/effects/gpu-device.ts
var devicePromise = null;
var getGpuDevice = () => {
  if (devicePromise) {
    return devicePromise;
  }
  devicePromise = (async () => {
    if (typeof navigator === "undefined" || !("gpu" in navigator)) {
      throw new Error("WebGPU is not available in this environment");
    }
    const { gpu } = navigator;
    const adapter = await gpu.requestAdapter();
    if (!adapter) {
      throw new Error("No WebGPU adapter available");
    }
    return adapter.requestDevice();
  })();
  return devicePromise;
};

// src/effects/run-effect-chain.ts
var createEffectChainState = (width, height) => ({
  pool: new CanvasPool(width, height),
  setupCache: new WeakMap,
  cleanupRegistry: [],
  currentRunId: 0
});
var cleanupEffectChainState = (state) => {
  state.currentRunId++;
  for (const entry of state.cleanupRegistry) {
    entry.definition.cleanup(entry.state);
  }
};
var ensureSetup = (state, def, target) => {
  const widened = def;
  let cacheForDefinition = state.setupCache.get(widened);
  if (!cacheForDefinition) {
    cacheForDefinition = new WeakMap;
    state.setupCache.set(widened, cacheForDefinition);
  }
  if (cacheForDefinition.has(target)) {
    return cacheForDefinition.get(target);
  }
  const setupState = def.setup(target);
  cacheForDefinition.set(target, setupState);
  state.cleanupRegistry.push({ definition: widened, state: setupState });
  return setupState;
};
var runEffectChain = async ({
  state,
  source,
  effects,
  output,
  width,
  height
}) => {
  const runId = ++state.currentRunId;
  const isCancelled = () => state.currentRunId !== runId;
  const enabledEffects = effects.filter((e) => !e.params.disabled);
  const runs = groupByBackend(enabledEffects);
  let currentImage = source;
  let lastTarget = null;
  if (runs.length === 0) {
    if (source === output) {
      return true;
    }
    const ctx = output.getContext("2d");
    if (!ctx) {
      throw new Error("Failed to acquire 2D context for output canvas");
    }
    ctx.clearRect(0, 0, width, height);
    ctx.drawImage(currentImage, 0, 0, width, height);
    return true;
  }
  let needsGpuDevice = false;
  for (const run of runs) {
    if (run.backend === "webgpu") {
      needsGpuDevice = true;
      break;
    }
  }
  const gpuDevice = needsGpuDevice ? await getGpuDevice() : null;
  if (isCancelled()) {
    return false;
  }
  let flipWebGLSourceY = true;
  for (let runIndex = 0;runIndex < runs.length; runIndex++) {
    const run = runs[runIndex];
    const [a2, b2] = state.pool.getPair(run.backend);
    let dst = a2;
    for (const eff of run.effects) {
      const def = eff.definition;
      const setupState = ensureSetup(state, def, dst);
      def.apply({
        source: currentImage,
        target: dst,
        state: setupState,
        params: eff.params,
        width,
        height,
        gpuDevice,
        flipSourceY: run.backend === "webgl2" ? flipWebGLSourceY : false
      });
      if (run.backend === "webgl2") {
        flipWebGLSourceY = true;
        state.pool.assertContextNotLost(dst);
      }
      currentImage = dst;
      dst = dst === a2 ? b2 : a2;
    }
    lastTarget = currentImage ?? lastTarget;
    const nextRun = runs[runIndex + 1];
    if (nextRun && nextRun.backend !== run.backend && lastTarget) {
      if (run.backend === "2d" && nextRun.backend === "webgl2") {
        currentImage = lastTarget;
        flipWebGLSourceY = true;
      } else {
        const bitmap = await createImageBitmap(lastTarget);
        if (isCancelled()) {
          bitmap.close();
          return false;
        }
        currentImage = bitmap;
        if (nextRun.backend === "webgl2") {
          flipWebGLSourceY = false;
        }
      }
    }
  }
  if (!lastTarget) {
    return true;
  }
  const outCtx = output.getContext("2d");
  if (!outCtx) {
    throw new Error("Failed to acquire 2D context for output canvas");
  }
  outCtx.clearRect(0, 0, width, height);
  outCtx.drawImage(lastTarget, 0, 0, width, height);
  return true;
};

// src/effects/use-effect-chain-state.ts
import { useEffect as useEffect5, useMemo as useMemo15, useRef as useRef8 } from "react";
var useEffectChainState = () => {
  const chainStateRef = useRef8(null);
  const sizeRef = useRef8(null);
  useEffect5(() => {
    return () => {
      if (chainStateRef.current) {
        cleanupEffectChainState(chainStateRef.current);
      }
    };
  }, []);
  return useMemo15(() => ({
    get: (width, height) => {
      if (!sizeRef.current || sizeRef.current.width !== width || sizeRef.current.height !== height) {
        if (chainStateRef.current) {
          cleanupEffectChainState(chainStateRef.current);
        }
        chainStateRef.current = createEffectChainState(width, height);
        sizeRef.current = { width, height };
      }
      return chainStateRef.current;
    }
  }), []);
};

// src/animated-image/canvas.tsx
import { jsx as jsx14 } from "react/jsx-runtime";
var CanvasRefForwardingFunction = ({ width, height, fit, className, style, effects, ...props }, ref) => {
  const canvasRef = useRef9(null);
  const chainState = useEffectChainState();
  const sourceCanvas = useMemo16(() => {
    if (typeof document === "undefined") {
      return null;
    }
    return document.createElement("canvas");
  }, []);
  const draw = useCallback8((imageData) => {
    const canvas = canvasRef.current;
    const canvasWidth = width ?? imageData.displayWidth;
    const canvasHeight = height ?? imageData.displayHeight;
    if (!canvas) {
      throw new Error("Canvas ref is not set");
    }
    if (!sourceCanvas) {
      throw new Error("Source canvas is not available");
    }
    sourceCanvas.width = canvasWidth;
    sourceCanvas.height = canvasHeight;
    const sourceCtx = sourceCanvas.getContext("2d");
    if (!sourceCtx) {
      throw new Error("Could not get 2d context for source canvas");
    }
    sourceCtx.drawImage(imageData, ...calculateImageFit(fit, {
      height: imageData.displayHeight,
      width: imageData.displayWidth
    }, {
      width: canvasWidth,
      height: canvasHeight
    }));
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;
    return runEffectChain({
      state: chainState.get(canvasWidth, canvasHeight),
      source: sourceCanvas,
      effects,
      output: canvas,
      width: canvasWidth,
      height: canvasHeight
    });
  }, [chainState, effects, fit, height, sourceCanvas, width]);
  useImperativeHandle(ref, () => {
    return {
      draw,
      getCanvas: () => {
        if (!canvasRef.current) {
          throw new Error("Canvas ref is not set");
        }
        return canvasRef.current;
      },
      clear: () => {
        const ctx = canvasRef.current?.getContext("2d");
        if (!ctx) {
          throw new Error("Could not get 2d context");
        }
        ctx.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height);
      }
    };
  }, [draw]);
  return /* @__PURE__ */ jsx14("canvas", {
    ref: canvasRef,
    className,
    style,
    ...props
  });
};
var Canvas = React19.forwardRef(CanvasRefForwardingFunction);

// src/animated-image/create-image-decoder.ts
var createImageDecoder = async ({
  resolvedSrc,
  signal,
  requestInit,
  contentType
}) => {
  if (typeof ImageDecoder === "undefined") {
    throw new Error("Your browser does not support the WebCodecs ImageDecoder API.");
  }
  const response = await fetch(resolvedSrc, { ...requestInit, signal });
  const { body } = response;
  if (!body) {
    throw new Error("Got no body");
  }
  const decoder = new ImageDecoder({
    data: body,
    type: contentType ?? response.headers.get("Content-Type") ?? "image/gif"
  });
  await Promise.all([decoder.completed, decoder.tracks.ready]);
  const { selectedTrack } = decoder.tracks;
  if (!selectedTrack) {
    decoder.close();
    throw new Error("No selected track");
  }
  return { decoder, selectedTrack };
};

// src/animated-image/decode-image.ts
var CACHE_SIZE = 5;
var getActualTime = ({
  loopBehavior,
  durationFound,
  timeInSec
}) => {
  return loopBehavior === "loop" ? durationFound ? timeInSec % durationFound : timeInSec : Math.min(timeInSec, durationFound || Infinity);
};
var decodeImage = async ({
  resolvedSrc,
  signal,
  requestInit,
  currentTime,
  initialLoopBehavior
}) => {
  const { decoder, selectedTrack } = await createImageDecoder({
    resolvedSrc,
    signal,
    requestInit,
    contentType: null
  });
  const cache2 = [];
  let durationFound = null;
  const getFrameByIndex = async (frameIndex) => {
    const foundInCache = cache2.find((c2) => c2.frameIndex === frameIndex);
    if (foundInCache && foundInCache.frame) {
      return foundInCache;
    }
    const frame = await decoder.decode({
      frameIndex,
      completeFramesOnly: true
    });
    if (foundInCache) {
      foundInCache.frame = frame.image;
    } else {
      cache2.push({
        frame: frame.image,
        frameIndex,
        timeInSeconds: frame.image.timestamp / 1e6
      });
    }
    return {
      frame: frame.image,
      frameIndex,
      timeInSeconds: frame.image.timestamp / 1e6
    };
  };
  const clearCache = (closeToTimeInSec) => {
    const itemsInCache = cache2.filter((c2) => c2.frame);
    const sortByClosestToCurrentTime = itemsInCache.sort((a2, b2) => {
      const aDiff = Math.abs(a2.timeInSeconds - closeToTimeInSec);
      const bDiff = Math.abs(b2.timeInSeconds - closeToTimeInSec);
      return aDiff - bDiff;
    });
    for (let i = 0;i < sortByClosestToCurrentTime.length; i++) {
      if (i < CACHE_SIZE) {
        continue;
      }
      const item = sortByClosestToCurrentTime[i];
      item.frame = null;
    }
  };
  const ensureFrameBeforeAndAfter = async ({
    timeInSec,
    loopBehavior
  }) => {
    const actualTimeInSec = getActualTime({
      durationFound,
      loopBehavior,
      timeInSec
    });
    const framesBefore = cache2.filter((c2) => c2.timeInSeconds <= actualTimeInSec);
    const biggestIndex = framesBefore.map((c2) => c2.frameIndex).reduce((a2, b2) => Math.max(a2, b2), 0);
    let i = biggestIndex;
    while (true) {
      const f = await getFrameByIndex(i);
      i++;
      if (!f.frame) {
        throw new Error("No frame found");
      }
      if (!f.frame.duration) {
        break;
      }
      if (i === selectedTrack.frameCount && durationFound === null) {
        const duration = (f.frame.timestamp + f.frame.duration) / 1e6;
        durationFound = duration;
      }
      if (f.timeInSeconds > actualTimeInSec || i === selectedTrack.frameCount) {
        break;
      }
    }
    if (selectedTrack.frameCount - biggestIndex < 3 && loopBehavior === "loop") {
      await getFrameByIndex(0);
    }
    clearCache(actualTimeInSec);
  };
  await ensureFrameBeforeAndAfter({
    timeInSec: currentTime,
    loopBehavior: initialLoopBehavior
  });
  await ensureFrameBeforeAndAfter({
    timeInSec: currentTime,
    loopBehavior: initialLoopBehavior
  });
  const getFrame = async (timeInSec, loopBehavior) => {
    if (durationFound !== null && timeInSec > durationFound && loopBehavior === "clear-after-finish") {
      return null;
    }
    const actualTimeInSec = getActualTime({
      loopBehavior,
      durationFound,
      timeInSec
    });
    await ensureFrameBeforeAndAfter({ timeInSec: actualTimeInSec, loopBehavior });
    const itemsInCache = cache2.filter((c2) => c2.frame);
    const closest = itemsInCache.reduce((a2, b2) => {
      const aDiff = Math.abs(a2.timeInSeconds - actualTimeInSec);
      const bDiff = Math.abs(b2.timeInSeconds - actualTimeInSec);
      return aDiff < bDiff ? a2 : b2;
    });
    if (!closest.frame) {
      throw new Error("No frame found");
    }
    return closest;
  };
  return {
    close: () => {
      for (const item of cache2) {
        item.frame?.close();
        item.frame = null;
      }
      decoder.close();
    },
    getFrame,
    frameCount: selectedTrack.frameCount
  };
};

// src/animated-image/get-current-time.ts
var getCurrentTime = ({
  frame,
  playbackRate,
  fps
}) => {
  return frame * playbackRate / fps;
};

// src/animated-image/request-init.ts
var serializeRequestInit = (requestInit) => {
  if (!requestInit) {
    return null;
  }
  const requestInitWithoutSignal = { ...requestInit };
  delete requestInitWithoutSignal.signal;
  const { headers, ...rest } = requestInitWithoutSignal;
  return JSON.stringify({
    ...rest,
    headers: headers ? Array.from(new Headers(headers).entries()) : null
  });
};

// src/animated-image/resolve-image-source.tsx
var resolveAnimatedImageSource = (src) => {
  if (typeof window === "undefined") {
    return src;
  }
  return new URL(src, document.baseURI).href;
};

// src/animated-image/AnimatedImage.tsx
import { jsx as jsx15 } from "react/jsx-runtime";
var animatedImageSchema = {
  src: {
    type: "asset",
    assetType: "image",
    default: undefined,
    description: "Source",
    keyframable: false
  },
  ...baseSchema,
  ...cropSchema,
  ...premountSchema,
  playbackRate: {
    type: "number",
    min: 0,
    max: 10,
    step: 0.1,
    default: 1,
    description: "Playback rate",
    hiddenFromList: false,
    keyframable: false
  },
  ...transformSchema,
  ...backgroundSchema,
  ...borderSchema,
  ...borderRadiusSchema
};
var getCanvasPropsFromSequenceProps = (props) => {
  const canvasProps = {};
  const mutableCanvasProps = canvasProps;
  for (const key in props) {
    if (Object.prototype.hasOwnProperty.call(props, key) && (key.startsWith("data-") || key.startsWith("aria-"))) {
      mutableCanvasProps[key] = props[key];
    }
  }
  return canvasProps;
};
var AnimatedImageContent = forwardRef4(({
  src,
  width,
  height,
  onError,
  loopBehavior = "loop",
  playbackRate = 1,
  fit = "fill",
  requestInit,
  effects,
  controls,
  ...props
}, canvasRef) => {
  const resolvedSrc = resolveAnimatedImageSource(src);
  const [imageDecoder, setImageDecoder] = useState7(null);
  const { delayRender: delayRender2, continueRender: continueRender2 } = useDelayRender();
  const [decodeHandle] = useState7(() => delayRender2(`Rendering <AnimatedImage/> with src="${resolvedSrc}"`));
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const currentTime = getCurrentTime({ frame, playbackRate, fps });
  const currentTimeRef = useRef10(currentTime);
  currentTimeRef.current = currentTime;
  const requestInitKey = serializeRequestInit(requestInit);
  const requestInitRef = useRef10(requestInit);
  requestInitRef.current = requestInit;
  const ref = useRef10(null);
  const memoizedEffects = useMemoizedEffects({
    effects,
    overrideId: controls?.overrideId ?? null
  });
  useImperativeHandle2(canvasRef, () => {
    const c2 = ref.current?.getCanvas();
    if (!c2) {
      throw new Error("Canvas ref is not set");
    }
    return c2;
  }, []);
  const [initialLoopBehavior] = useState7(() => loopBehavior);
  useEffect6(() => {
    const controller = new AbortController;
    let cancelled = false;
    let continued = false;
    const continueRenderOnce = () => {
      if (continued) {
        return;
      }
      continued = true;
      continueRender2(decodeHandle);
    };
    decodeImage({
      resolvedSrc,
      signal: controller.signal,
      requestInit: requestInitRef.current,
      currentTime: currentTimeRef.current,
      initialLoopBehavior
    }).then((d) => {
      if (cancelled) {
        d.close();
        return;
      }
      setImageDecoder(d);
      continueRenderOnce();
    }).catch((err) => {
      if (cancelled) {
        return;
      }
      if (err.name === "AbortError") {
        continueRenderOnce();
        return;
      }
      if (onError) {
        onError?.(err);
        continueRenderOnce();
      } else {
        cancelRender(err);
      }
    });
    return () => {
      cancelled = true;
      controller.abort();
      continueRenderOnce();
    };
  }, [
    resolvedSrc,
    decodeHandle,
    onError,
    requestInitKey,
    initialLoopBehavior,
    continueRender2
  ]);
  useEffect6(() => {
    return () => {
      imageDecoder?.close();
    };
  }, [imageDecoder]);
  useLayoutEffect5(() => {
    if (!imageDecoder) {
      return;
    }
    const delay = delayRender2(`Rendering frame at ${currentTime} of <AnimatedImage src="${src}"/>`);
    let cancelled = false;
    imageDecoder.getFrame(currentTime, loopBehavior).then(async (videoFrame) => {
      if (cancelled) {
        return;
      }
      if (videoFrame === null) {
        ref.current?.clear();
        continueRender2(delay);
        return;
      }
      const completed = await ref.current?.draw(videoFrame.frame);
      if (completed && !cancelled) {
        continueRender2(delay);
      }
    }).catch((err) => {
      if (cancelled) {
        return;
      }
      if (onError) {
        onError(err);
        continueRender2(delay);
      } else {
        cancelRender(err);
      }
    });
    return () => {
      cancelled = true;
      continueRender2(delay);
    };
  }, [
    currentTime,
    imageDecoder,
    loopBehavior,
    onError,
    src,
    continueRender2,
    delayRender2,
    memoizedEffects,
    fit,
    width,
    height
  ]);
  return /* @__PURE__ */ jsx15(Canvas, {
    ref,
    width,
    height,
    fit,
    effects: memoizedEffects,
    ...props
  });
});
AnimatedImageContent.displayName = "AnimatedImageContent";
var AnimatedImageInner = ({
  src,
  width,
  height,
  onError,
  fit,
  playbackRate,
  loopBehavior,
  id,
  className,
  style,
  durationInFrames,
  from,
  premountFor,
  postmountFor,
  styleWhilePremounted,
  styleWhilePostmounted,
  cropLeft,
  cropRight,
  cropTop,
  cropBottom,
  requestInit,
  effects = [],
  controls,
  ref,
  ...sequenceProps
}) => {
  const actualRef = useRef10(null);
  const memoizedEffectDefinitions = useMemoizedEffectDefinitions(effects);
  useImperativeHandle2(ref, () => {
    return actualRef.current;
  }, []);
  const {
    effectivePostmountFor,
    effectivePremountFor,
    freezeFrame,
    isPremountingOrPostmounting,
    postmountingActive,
    premountingActive,
    premountingStyle
  } = usePremounting({
    from: from ?? 0,
    durationInFrames: durationInFrames ?? Infinity,
    premountFor: premountFor ?? null,
    postmountFor: postmountFor ?? null,
    style: style ?? null,
    styleWhilePremounted: styleWhilePremounted ?? null,
    styleWhilePostmounted: styleWhilePostmounted ?? null,
    hideWhilePremounted: "display-none"
  });
  const croppedStyle = useCropStyle({
    cropLeft,
    cropRight,
    cropTop,
    cropBottom,
    style: premountingStyle,
    componentName: "<AnimatedImage />"
  });
  const canvasProps = getCanvasPropsFromSequenceProps(sequenceProps);
  const animatedImageProps = {
    src,
    width,
    height,
    onError,
    fit,
    playbackRate,
    loopBehavior,
    id,
    className,
    style: croppedStyle ?? undefined,
    requestInit,
    ...canvasProps
  };
  return /* @__PURE__ */ jsx15(Freeze, {
    frame: freezeFrame,
    active: isPremountingOrPostmounting,
    children: /* @__PURE__ */ jsx15(Sequence, {
      layout: "none",
      from: from ?? 0,
      durationInFrames: durationInFrames ?? Infinity,
      name: "<AnimatedImage>",
      _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/animatedimage",
      controls,
      _remotionInternalEffects: memoizedEffectDefinitions,
      _remotionInternalPremountDisplay: effectivePremountFor || null,
      _remotionInternalPostmountDisplay: effectivePostmountFor || null,
      _remotionInternalIsPremounting: premountingActive,
      _remotionInternalIsPostmounting: postmountingActive,
      ...sequenceProps,
      outlineRef: actualRef,
      children: /* @__PURE__ */ jsx15(AnimatedImageContent, {
        ...animatedImageProps,
        ref: actualRef,
        effects,
        controls
      })
    })
  });
};
var AnimatedImage = withInteractivitySchema({
  Component: AnimatedImageInner,
  componentName: "<AnimatedImage>",
  componentIdentity: "dev.remotion.remotion.AnimatedImage",
  schema: animatedImageSchema,
  supportsEffects: true
});
AnimatedImage.displayName = "AnimatedImage";
addSequenceStackTraces(AnimatedImage);
// src/effects/create-effect.ts
var disabledEffectField = {
  type: "boolean",
  default: false,
  description: "Disabled"
};
var createEffect = (definition) => {
  const { calculateKey: userCalculateKey, validateParams } = definition;
  const widened = {
    ...definition,
    documentationLink: definition.documentationLink ?? null,
    calculateKey: (params) => {
      const disabled = params.disabled ?? false;
      return `${userCalculateKey(params)}-disabled-${disabled}`;
    },
    schema: {
      disabled: disabledEffectField,
      ...definition.schema
    }
  };
  const factory = (params = {}) => {
    validateParams(params);
    return {
      definition: widened,
      params,
      effectKey: widened.calculateKey(params),
      memoized: false
    };
  };
  return factory;
};
// src/Artifact.tsx
import { useContext as useContext21, useLayoutEffect as useLayoutEffect7, useState as useState9 } from "react";

// src/RenderAssetManager.tsx
import {
  createContext as createContext18,
  useCallback as useCallback9,
  useImperativeHandle as useImperativeHandle3,
  useLayoutEffect as useLayoutEffect6,
  useMemo as useMemo17,
  useRef as useRef11,
  useState as useState8
} from "react";

// src/validation/validate-artifact.ts
var validateArtifactFilename = (filename) => {
  if (typeof filename !== "string") {
    throw new TypeError(`The "filename" must be a string, but you passed a value of type ${typeof filename}`);
  }
  if (filename.trim() === "") {
    throw new Error("The `filename` must not be empty");
  }
  if (!filename.match(/^([0-9a-zA-Z-!_.*'()/:&$@=;+,?]+)/g)) {
    throw new Error('The `filename` must match "/^([0-9a-zA-Z-!_.*\'()/:&$@=;+,?]+)/g". Use forward slashes only, even on Windows.');
  }
};
var validateContent = (content2) => {
  if (typeof content2 !== "string" && !(content2 instanceof Uint8Array)) {
    throw new TypeError(`The "content" must be a string or Uint8Array, but you passed a value of type ${typeof content2}`);
  }
  if (typeof content2 === "string" && content2.trim() === "") {
    throw new Error("The `content` must not be empty");
  }
};
var validateRenderAsset = (artifact) => {
  if (artifact.type !== "artifact") {
    return;
  }
  validateArtifactFilename(artifact.filename);
  if (artifact.contentType === "thumbnail") {
    return;
  }
  validateContent(artifact.content);
};

// src/RenderAssetManager.tsx
import { jsx as jsx16 } from "react/jsx-runtime";
var RenderAssetManager = createContext18({
  registerRenderAsset: () => {
    return;
  },
  unregisterRenderAsset: () => {
    return;
  },
  renderAssets: []
});
var RenderAssetManagerProvider = ({ children, collectAssets }) => {
  const [renderAssets, setRenderAssets] = useState8([]);
  const renderAssetsRef = useRef11([]);
  const registerRenderAsset = useCallback9((renderAsset) => {
    validateRenderAsset(renderAsset);
    renderAssetsRef.current = [...renderAssetsRef.current, renderAsset];
    setRenderAssets(renderAssetsRef.current);
  }, []);
  if (collectAssets) {
    useImperativeHandle3(collectAssets, () => {
      return {
        collectAssets: () => {
          const assets = renderAssetsRef.current;
          renderAssetsRef.current = [];
          setRenderAssets([]);
          return assets;
        }
      };
    }, []);
  }
  const unregisterRenderAsset = useCallback9((id) => {
    renderAssetsRef.current = renderAssetsRef.current.filter((a2) => a2.id !== id);
    setRenderAssets(renderAssetsRef.current);
  }, []);
  useLayoutEffect6(() => {
    if (typeof window !== "undefined") {
      window.remotion_collectAssets = () => {
        const assets = renderAssetsRef.current;
        renderAssetsRef.current = [];
        setRenderAssets([]);
        return assets;
      };
    }
  }, []);
  const contextValue = useMemo17(() => {
    return {
      registerRenderAsset,
      unregisterRenderAsset,
      renderAssets
    };
  }, [renderAssets, registerRenderAsset, unregisterRenderAsset]);
  return /* @__PURE__ */ jsx16(RenderAssetManager.Provider, {
    value: contextValue,
    children
  });
};

// src/Artifact.tsx
var ArtifactThumbnail = Symbol("Thumbnail");
var Artifact = ({ filename, content: content2, downloadBehavior }) => {
  const { registerRenderAsset, unregisterRenderAsset } = useContext21(RenderAssetManager);
  const env = useRemotionEnvironment();
  const frame = useCurrentFrame();
  const [id] = useState9(() => {
    return String(Math.random());
  });
  useLayoutEffect7(() => {
    if (!env.isRendering) {
      return;
    }
    if (content2 instanceof Uint8Array) {
      registerRenderAsset({
        type: "artifact",
        id,
        content: btoa(new TextDecoder("utf8").decode(content2)),
        filename,
        frame,
        contentType: "binary",
        downloadBehavior: downloadBehavior ?? null
      });
    } else if (content2 === ArtifactThumbnail) {
      registerRenderAsset({
        type: "artifact",
        id,
        filename,
        frame,
        contentType: "thumbnail",
        downloadBehavior: downloadBehavior ?? null
      });
    } else {
      registerRenderAsset({
        type: "artifact",
        id,
        content: content2,
        filename,
        frame,
        contentType: "text",
        downloadBehavior: downloadBehavior ?? null
      });
    }
    return () => {
      return unregisterRenderAsset(id);
    };
  }, [
    content2,
    env.isRendering,
    filename,
    frame,
    id,
    registerRenderAsset,
    unregisterRenderAsset,
    downloadBehavior
  ]);
  return null;
};
Artifact.Thumbnail = ArtifactThumbnail;
// src/audio/html5-audio.tsx
import { forwardRef as forwardRef7, useCallback as useCallback16, useContext as useContext34 } from "react";

// src/absolute-src.ts
var getAbsoluteSrc = (relativeSrc) => {
  if (typeof window === "undefined") {
    return relativeSrc;
  }
  if (relativeSrc.startsWith("http://") || relativeSrc.startsWith("https://") || relativeSrc.startsWith("file://") || relativeSrc.startsWith("blob:") || relativeSrc.startsWith("data:")) {
    return relativeSrc;
  }
  return new URL(relativeSrc, document.baseURI).href;
};

// src/calculate-media-duration.ts
var calculateMediaDuration = ({
  trimAfter,
  mediaDurationInFrames,
  playbackRate,
  trimBefore
}) => {
  let duration = mediaDurationInFrames;
  if (typeof trimAfter !== "undefined") {
    duration = trimAfter;
  }
  if (typeof trimBefore !== "undefined") {
    duration -= trimBefore;
  }
  const actualDuration = duration / playbackRate;
  return Number(actualDuration.toFixed(10));
};

// src/loop/index.tsx
import React20, { createContext as createContext19, useMemo as useMemo18 } from "react";
import { jsx as jsx17 } from "react/jsx-runtime";
var LoopContext = createContext19(null);
var useLoop = () => {
  return React20.useContext(LoopContext);
};
var Loop = ({
  durationInFrames,
  times = Infinity,
  children,
  name,
  showInTimeline,
  ...props
}) => {
  const currentFrame = useCurrentFrame();
  const { durationInFrames: compDuration } = useVideoConfig();
  validateDurationInFrames(durationInFrames, {
    component: "of the <Loop /> component",
    allowFloats: true
  });
  if (typeof times !== "number") {
    throw new TypeError(`You passed to "times" an argument of type ${typeof times}, but it must be a number.`);
  }
  if (times !== Infinity && times % 1 !== 0) {
    throw new TypeError(`The "times" prop of a loop must be an integer, but got ${times}.`);
  }
  if (times < 0) {
    throw new TypeError(`The "times" prop of a loop must be at least 0, but got ${times}`);
  }
  const maxTimes = Math.ceil(compDuration / durationInFrames);
  const actualTimes = Math.min(maxTimes, times);
  const style = props.layout === "none" ? undefined : props.style;
  const maxFrame = durationInFrames * (actualTimes - 1);
  const iteration = Math.floor(currentFrame / durationInFrames);
  const start = iteration * durationInFrames;
  const from = Math.min(start, maxFrame);
  const loopDisplay = useMemo18(() => {
    return {
      numberOfTimes: Math.min(compDuration / durationInFrames, times),
      startOffset: -from,
      durationInFrames
    };
  }, [compDuration, durationInFrames, from, times]);
  const loopContext = useMemo18(() => {
    return {
      iteration: Math.floor(currentFrame / durationInFrames),
      durationInFrames
    };
  }, [currentFrame, durationInFrames]);
  return /* @__PURE__ */ jsx17(LoopContext.Provider, {
    value: loopContext,
    children: /* @__PURE__ */ jsx17(Sequence, {
      durationInFrames,
      from,
      name: name ?? "<Loop>",
      _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/loop",
      _remotionInternalLoopDisplay: loopDisplay,
      layout: props.layout,
      style,
      showInTimeline,
      children
    })
  });
};
Loop.useLoop = useLoop;

// src/prefetch.ts
import { useContext as useContext22 } from "react";

// src/playback-logging.ts
var playbackLogging = ({
  logLevel,
  tag,
  message,
  mountTime
}) => {
  const tags = [mountTime ? Date.now() - mountTime + "ms " : null, tag].filter(Boolean).join(" ");
  Log.trace({ logLevel, tag: null }, `[${tags}]`, message);
};

// src/prefetch-state.tsx
import { createContext as createContext20, useEffect as useEffect7, useState as useState10 } from "react";
import { jsx as jsx18 } from "react/jsx-runtime";
var PreloadContext = createContext20({});
var preloads = {};
var updaters = [];
var setPreloads = (updater) => {
  preloads = updater(preloads);
  updaters.forEach((u) => u());
};
var PrefetchProvider = ({ children }) => {
  const [_preloads, _setPreloads] = useState10(() => preloads);
  useEffect7(() => {
    const updaterFunction = () => {
      _setPreloads(preloads);
    };
    updaters.push(updaterFunction);
    return () => {
      updaters = updaters.filter((u) => u !== updaterFunction);
    };
  }, []);
  return /* @__PURE__ */ jsx18(PreloadContext.Provider, {
    value: _preloads,
    children
  });
};

// src/prefetch.ts
var removeAndGetHashFragment = (src) => {
  const hashIndex = src.indexOf("#");
  if (hashIndex === -1) {
    return null;
  }
  return hashIndex;
};
var getSrcWithoutHash = (src) => {
  const hashIndex = removeAndGetHashFragment(src);
  if (hashIndex === null) {
    return src;
  }
  return src.slice(0, hashIndex);
};
var usePreload = (src) => {
  const preloads2 = useContext22(PreloadContext);
  const hashFragmentIndex = removeAndGetHashFragment(src);
  const withoutHashFragment = getSrcWithoutHash(src);
  if (!preloads2[withoutHashFragment]) {
    return src;
  }
  if (hashFragmentIndex !== null) {
    return preloads2[withoutHashFragment] + src.slice(hashFragmentIndex);
  }
  return preloads2[withoutHashFragment];
};
var blobToBase64 = function(blob) {
  const reader = new FileReader;
  return new Promise((resolve, reject) => {
    reader.onload = function() {
      const dataUrl = reader.result;
      resolve(dataUrl);
    };
    reader.onerror = (err) => {
      return reject(err);
    };
    reader.readAsDataURL(blob);
  });
};
var getBlobFromReader = async ({
  reader,
  contentType,
  contentLength,
  onProgress
}) => {
  let receivedLength = 0;
  const chunks = [];
  while (true) {
    const { done, value } = await reader.read();
    if (done) {
      break;
    }
    chunks.push(value);
    receivedLength += value.length;
    if (onProgress) {
      onProgress({ loadedBytes: receivedLength, totalBytes: contentLength });
    }
  }
  const chunksAll = new Uint8Array(receivedLength);
  let position = 0;
  for (const chunk of chunks) {
    chunksAll.set(chunk, position);
    position += chunk.length;
  }
  return new Blob([chunksAll], {
    type: contentType ?? undefined
  });
};
var prefetch = (src, options) => {
  const method = options?.method ?? "blob-url";
  const logLevel = options?.logLevel ?? "info";
  const srcWithoutHash = getSrcWithoutHash(src);
  if (getRemotionEnvironment().isRendering) {
    return {
      free: () => {
        return;
      },
      waitUntilDone: () => Promise.resolve(srcWithoutHash)
    };
  }
  Log.verbose({ logLevel, tag: "prefetch" }, `Starting prefetch ${srcWithoutHash}`);
  let canceled = false;
  let objectUrl = null;
  let resolve = () => {
    return;
  };
  let reject = () => {
    return;
  };
  const waitUntilDone = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  waitUntilDone.catch(() => {
    return;
  });
  const controller = new AbortController;
  let reader = null;
  fetch(srcWithoutHash, {
    signal: controller.signal,
    credentials: options?.credentials ?? undefined
  }).then((res) => {
    if (canceled) {
      return null;
    }
    if (!res.ok) {
      throw new Error(`HTTP error, status = ${res.status}`);
    }
    const headerContentType = res.headers.get("Content-Type");
    const contentType = options?.contentType ?? headerContentType;
    const hasProperContentType = contentType && (contentType.startsWith("video/") || contentType.startsWith("audio/") || contentType.startsWith("image/"));
    if (!hasProperContentType) {
      console.warn(`Called prefetch() on ${srcWithoutHash} which returned a "Content-Type" of ${headerContentType}. Prefetched content should have a proper content type (video/... or audio/...) or a contentType passed the options of prefetch(). Otherwise, prefetching will not work properly in all browsers.`);
    }
    if (!res.body) {
      throw new Error(`HTTP response of ${srcWithoutHash} has no body`);
    }
    const responseReader = res.body.getReader();
    reader = responseReader;
    return getBlobFromReader({
      reader: responseReader,
      contentType: options?.contentType ?? headerContentType ?? null,
      contentLength: res.headers.get("Content-Length") ? parseInt(res.headers.get("Content-Length"), 10) : null,
      onProgress: options?.onProgress
    });
  }).then((buf) => {
    if (!buf || canceled) {
      return;
    }
    const actualBlob = options?.contentType ? new Blob([buf], { type: options.contentType }) : buf;
    if (method === "base64") {
      return blobToBase64(actualBlob);
    }
    return URL.createObjectURL(actualBlob);
  }).then((url) => {
    if (canceled) {
      return;
    }
    playbackLogging({
      logLevel,
      tag: "prefetch",
      message: `Finished prefetch ${srcWithoutHash} with method ${method}`,
      mountTime: null
    });
    objectUrl = url;
    setPreloads((p) => ({
      ...p,
      [srcWithoutHash]: objectUrl
    }));
    resolve(objectUrl);
  }).catch((err) => {
    if (err?.message.includes("free() called")) {
      return;
    }
    reject(err);
  });
  return {
    free: () => {
      playbackLogging({
        logLevel,
        tag: "prefetch",
        message: `Freeing ${srcWithoutHash}`,
        mountTime: null
      });
      if (objectUrl) {
        if (method === "blob-url") {
          URL.revokeObjectURL(objectUrl);
        }
        setPreloads((p) => {
          const copy = { ...p };
          delete copy[srcWithoutHash];
          return copy;
        });
      } else {
        if (canceled) {
          return;
        }
        canceled = true;
        const cancellationError = new Error("free() called");
        reject(cancellationError);
        try {
          controller.abort(cancellationError);
        } catch {}
        reader?.cancel(cancellationError).catch(() => {
          return;
        });
      }
    },
    waitUntilDone: () => {
      return waitUntilDone;
    }
  };
};

// src/validate-media-props.ts
var validateMediaProps = (props, component) => {
  if (typeof props.volume !== "number" && typeof props.volume !== "function" && typeof props.volume !== "undefined") {
    throw new TypeError(`You have passed a volume of type ${typeof props.volume} to your <${component} /> component. Volume must be a number or a function with the signature '(frame: number) => number' undefined.`);
  }
  if (typeof props.volume === "number" && props.volume < 0) {
    throw new TypeError(`You have passed a volume below 0 to your <${component} /> component. Volume must be between 0 and 1`);
  }
  if (typeof props.playbackRate !== "number" && typeof props.playbackRate !== "undefined") {
    throw new TypeError(`You have passed a playbackRate of type ${typeof props.playbackRate} to your <${component} /> component. Playback rate must a real number or undefined.`);
  }
  if (typeof props.playbackRate === "number" && (isNaN(props.playbackRate) || !Number.isFinite(props.playbackRate) || props.playbackRate <= 0)) {
    throw new TypeError(`You have passed a playbackRate of ${props.playbackRate} to your <${component} /> component. Playback rate must be a real number above 0.`);
  }
  if (typeof props.preservePitch !== "boolean" && typeof props.preservePitch !== "undefined") {
    throw new TypeError(`'preservePitch' must be a boolean or undefined but got '${typeof props.preservePitch}' instead`);
  }
};

// src/validate-start-from-props.ts
var validateStartFromProps = (startFrom, endAt) => {
  if (typeof startFrom !== "undefined") {
    if (typeof startFrom !== "number") {
      throw new TypeError(`type of startFrom prop must be a number, instead got type ${typeof startFrom}.`);
    }
    if (isNaN(startFrom) || startFrom === Infinity) {
      throw new TypeError("startFrom prop can not be NaN or Infinity.");
    }
    if (startFrom < 0) {
      throw new TypeError(`startFrom must be greater than equal to 0 instead got ${startFrom}.`);
    }
  }
  if (typeof endAt !== "undefined") {
    if (typeof endAt !== "number") {
      throw new TypeError(`type of endAt prop must be a number, instead got type ${typeof endAt}.`);
    }
    if (isNaN(endAt)) {
      throw new TypeError("endAt prop can not be NaN.");
    }
    if (endAt <= 0) {
      throw new TypeError(`endAt must be a positive number, instead got ${endAt}.`);
    }
  }
  if (endAt < startFrom) {
    throw new TypeError("endAt prop must be greater than startFrom prop.");
  }
};
var validateTrimProps = (trimBefore, trimAfter) => {
  if (typeof trimBefore !== "undefined") {
    if (typeof trimBefore !== "number") {
      throw new TypeError(`type of trimBefore prop must be a number, instead got type ${typeof trimBefore}.`);
    }
    if (isNaN(trimBefore) || trimBefore === Infinity) {
      throw new TypeError("trimBefore prop can not be NaN or Infinity.");
    }
    if (trimBefore < 0) {
      throw new TypeError(`trimBefore must be greater than equal to 0 instead got ${trimBefore}.`);
    }
  }
  if (typeof trimAfter !== "undefined") {
    if (typeof trimAfter !== "number") {
      throw new TypeError(`type of trimAfter prop must be a number, instead got type ${typeof trimAfter}.`);
    }
    if (isNaN(trimAfter)) {
      throw new TypeError("trimAfter prop can not be NaN.");
    }
    if (trimAfter <= 0) {
      throw new TypeError(`trimAfter must be a positive number, instead got ${trimAfter}.`);
    }
  }
  if (trimAfter <= trimBefore) {
    throw new TypeError("trimAfter prop must be greater than trimBefore prop.");
  }
};
var validateMediaTrimProps = ({
  startFrom,
  endAt,
  trimBefore,
  trimAfter
}) => {
  if (typeof startFrom !== "undefined" && typeof trimBefore !== "undefined") {
    throw new TypeError("Cannot use both startFrom and trimBefore props. Use trimBefore instead as startFrom is deprecated.");
  }
  if (typeof endAt !== "undefined" && typeof trimAfter !== "undefined") {
    throw new TypeError("Cannot use both endAt and trimAfter props. Use trimAfter instead as endAt is deprecated.");
  }
  const hasNewProps = typeof trimBefore !== "undefined" || typeof trimAfter !== "undefined";
  const hasOldProps = typeof startFrom !== "undefined" || typeof endAt !== "undefined";
  if (hasNewProps) {
    validateTrimProps(trimBefore, trimAfter);
  } else if (hasOldProps) {
    validateStartFromProps(startFrom, endAt);
  }
};
var resolveTrimProps = ({
  startFrom,
  endAt,
  trimBefore,
  trimAfter
}) => {
  const trimBeforeValue = trimBefore ?? startFrom ?? undefined;
  const trimAfterValue = trimAfter ?? endAt ?? undefined;
  return { trimBeforeValue, trimAfterValue };
};

// src/video/duration-state.tsx
import { createContext as createContext21, useMemo as useMemo19, useReducer } from "react";
import { jsx as jsx19 } from "react/jsx-runtime";
var durationReducer = (state, action) => {
  switch (action.type) {
    case "got-duration": {
      const absoluteSrc = getAbsoluteSrc(action.src);
      if (state[absoluteSrc] === action.durationInSeconds) {
        return state;
      }
      return {
        ...state,
        [absoluteSrc]: action.durationInSeconds
      };
    }
    default:
      return state;
  }
};
var DurationsContext = createContext21({
  durations: {},
  setDurations: () => {
    throw new Error("context missing");
  }
});
var DurationsContextProvider = ({ children }) => {
  const [durations, setDurations] = useReducer(durationReducer, {});
  const value = useMemo19(() => {
    return {
      durations,
      setDurations
    };
  }, [durations]);
  return /* @__PURE__ */ jsx19(DurationsContext.Provider, {
    value,
    children
  });
};

// src/audio/AudioForPreview.tsx
import { useCallback as useCallback15 } from "react";
import React26, {
  forwardRef as forwardRef5,
  useContext as useContext31,
  useEffect as useEffect15,
  useImperativeHandle as useImperativeHandle4,
  useMemo as useMemo27,
  useRef as useRef20,
  useState as useState15
} from "react";

// src/get-cross-origin-value.ts
var getCrossOriginValue = ({
  crossOrigin,
  requestsVideoFrame,
  isClientSideRendering
}) => {
  if (crossOrigin !== undefined && crossOrigin !== null) {
    return crossOrigin;
  }
  if (isClientSideRendering) {
    return "anonymous";
  }
  if (requestsVideoFrame) {
    return "anonymous";
  }
  return;
};

// src/random.ts
function mulberry32(a2) {
  let t = a2 + 1831565813;
  t = Math.imul(t ^ t >>> 15, t | 1);
  t ^= t + Math.imul(t ^ t >>> 7, t | 61);
  return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
function hashCode(str) {
  let i = 0;
  let chr = 0;
  let hash = 0;
  for (i = 0;i < str.length; i++) {
    chr = str.charCodeAt(i);
    hash = (hash << 5) - hash + chr;
    hash |= 0;
  }
  return hash;
}
var random = (seed, dummy) => {
  if (dummy !== undefined) {
    throw new TypeError("random() takes only one argument");
  }
  if (seed === null) {
    return Math.random();
  }
  if (typeof seed === "string") {
    return mulberry32(hashCode(seed));
  }
  if (typeof seed === "number") {
    return mulberry32(seed * 10000000000);
  }
  throw new Error("random() argument must be a number or a string");
};

// src/use-amplification.ts
import { useContext as useContext24, useLayoutEffect as useLayoutEffect8, useRef as useRef15 } from "react";

// src/audio/shared-audio-tags.tsx
import React23, {
  createContext as createContext22,
  createRef as createRef2,
  useCallback as useCallback10,
  useContext as useContext23,
  useEffect as useEffect8,
  useMemo as useMemo21,
  useRef as useRef13,
  useState as useState11
} from "react";

// src/play-and-handle-not-allowed-error.ts
var playAndHandleNotAllowedError = ({
  mediaRef,
  mediaType,
  onAutoPlayError,
  logLevel,
  mountTime,
  reason,
  isPlayer
}) => {
  const { current } = mediaRef;
  if (!current) {
    return;
  }
  playbackLogging({
    logLevel,
    tag: "play",
    message: `Attempting to play ${current.src}. Reason: ${reason}`,
    mountTime
  });
  const prom = current.play();
  if (!prom.catch) {
    return;
  }
  prom.catch((err) => {
    if (!current) {
      return;
    }
    if (err.message.includes("request was interrupted by a call to pause")) {
      return;
    }
    if (err.message.includes("The operation was aborted.")) {
      return;
    }
    if (err.message.includes("The fetching process for the media resource was aborted by the user agent")) {
      return;
    }
    if (err.message.includes("request was interrupted by a new load request")) {
      return;
    }
    if (err.message.includes("because the media was removed from the document")) {
      return;
    }
    if (err.message.includes("user didn't interact with the document") && current.muted) {
      return;
    }
    console.log(`Could not play ${mediaType} due to following error: `, err);
    if (!current.muted) {
      if (onAutoPlayError) {
        onAutoPlayError();
        return;
      }
      if (mediaType === "video" && isPlayer) {
        Log.info({ logLevel, tag: "<" + mediaType + ">" }, `The video will be muted and we'll retry playing it.`);
        Log.info({ logLevel, tag: "<" + mediaType + ">" }, "Use onAutoPlayError() to handle this error yourself.");
        current.muted = true;
        current.play();
      }
    }
  });
};

// src/audio/shared-element-source-node.ts
var makeSharedElementSourceNode = ({
  audioContext,
  ref
}) => {
  let connected = null;
  let disposed = false;
  let currentAudioContext = audioContext;
  return {
    setAudioContext: (newAudioContext) => {
      currentAudioContext = newAudioContext;
    },
    attemptToConnect: () => {
      if (disposed) {
        throw new Error("SharedElementSourceNode has been disposed");
      }
      if (!connected && ref.current && currentAudioContext) {
        const mediaElementSourceNode = currentAudioContext.createMediaElementSource(ref.current);
        connected = mediaElementSourceNode;
      }
    },
    get: () => {
      if (!connected) {
        throw new Error("Audio element not connected");
      }
      return connected;
    },
    cleanup: () => {
      if (connected) {
        connected.disconnect();
        connected = null;
      }
      disposed = true;
    }
  };
};

// src/audio/use-audio-context.ts
import { useMemo as useMemo20, useRef as useRef12 } from "react";
var warned = false;
var warnOnce = (logLevel) => {
  if (warned) {
    return;
  }
  warned = true;
  if (typeof window !== "undefined") {
    Log.warn({ logLevel, tag: null }, "AudioContext is not supported in this browser");
  }
};
var useSingletonAudioContext = ({
  logLevel,
  latencyHint,
  audioEnabled,
  sampleRate
}) => {
  const env = useRemotionEnvironment();
  const initialSampleRate = useRef12(sampleRate);
  if (sampleRate !== initialSampleRate.current) {
    throw new Error(`Changing the AudioContext sample rate dynamically is not supported. The sample rate was initialized with ${initialSampleRate.current} Hz, but ${sampleRate} Hz was passed later.`);
  }
  const context = useMemo20(() => {
    if (env.isRendering) {
      return null;
    }
    if (!audioEnabled) {
      return null;
    }
    if (typeof AudioContext === "undefined") {
      warnOnce(logLevel);
      return null;
    }
    const audioContext = new AudioContext({
      latencyHint,
      sampleRate
    });
    const gainNode = audioContext.createGain();
    gainNode.connect(audioContext.destination);
    Log.trace({ logLevel, tag: "audio" }, "Creating new audio context");
    audioContext.suspend();
    let transitionTarget = null;
    const getState = () => {
      const nativeState = audioContext.state;
      if (transitionTarget === "running" && nativeState !== "running") {
        return "suspended-to-running";
      }
      if (transitionTarget === "suspended" && nativeState !== "suspended") {
        return "running-to-suspended";
      }
      return nativeState;
    };
    const resume = () => {
      transitionTarget = "running";
      const promise = audioContext.resume();
      promise.finally(() => {
        if (transitionTarget === "running") {
          transitionTarget = null;
        }
      });
      return promise;
    };
    const suspend = () => {
      transitionTarget = "suspended";
      const promise = audioContext.suspend();
      promise.finally(() => {
        if (transitionTarget === "suspended") {
          transitionTarget = null;
        }
      });
      return promise;
    };
    return {
      audioContext,
      gainNode,
      getState,
      resume,
      suspend
    };
  }, [logLevel, latencyHint, env.isRendering, audioEnabled, sampleRate]);
  return context;
};

// src/audio/wait-until-actually-resumed.ts
var RESUME_WAIT_TIMEOUT = 1000;
var waitUntilActuallyResumed = (audioContext, logLevel, signal, isAutoPlayAttempt) => {
  return new Promise((resolve) => {
    const startCurrentTime = audioContext.currentTime;
    const start = audioContext.getOutputTimestamp();
    const startOutputPerformanceTime = start.performanceTime;
    const startWallClock = performance.now();
    let animationFrame = null;
    let timeout = null;
    let settled = false;
    let onAbort = () => {
      return;
    };
    const finish = (result) => {
      if (settled) {
        return;
      }
      settled = true;
      if (animationFrame !== null) {
        cancelAnimationFrame(animationFrame);
      }
      if (timeout !== null) {
        clearTimeout(timeout);
      }
      signal.removeEventListener("abort", onAbort);
      resolve(result);
    };
    onAbort = () => finish("cancelled");
    const hasAudiblyStarted = (startPerformanceTime) => {
      const outputTimestamp = audioContext.getOutputTimestamp();
      return startPerformanceTime !== undefined && outputTimestamp.performanceTime !== undefined && outputTimestamp.performanceTime > startPerformanceTime && outputTimestamp.contextTime !== undefined && outputTimestamp.contextTime > startCurrentTime;
    };
    const check = () => {
      animationFrame = null;
      const { currentTime } = audioContext;
      const outputTimestamp = audioContext.getOutputTimestamp();
      const elapsedWallClock = performance.now() - startWallClock;
      if (hasAudiblyStarted(startOutputPerformanceTime)) {
        Log.verbose({ logLevel, tag: "audio" }, `waitUntilActuallyResumed: getOutputTimestamp.performanceTime advanced from ${startOutputPerformanceTime.toFixed(6)} to ${outputTimestamp.performanceTime?.toFixed(6)} after ${elapsedWallClock.toFixed(1)}ms. currentTime=${currentTime.toFixed(6)} (advanced by ${(currentTime - startCurrentTime).toFixed(6)}), getOutputTimestamp.performanceTime=${outputTimestamp.performanceTime?.toFixed(1) ?? "undefined"}`);
        finish("resumed");
        return;
      }
      animationFrame = requestAnimationFrame(check);
    };
    if (signal.aborted) {
      finish("cancelled");
      return;
    }
    signal.addEventListener("abort", onAbort, { once: true });
    if (isAutoPlayAttempt) {
      timeout = setTimeout(() => {
        if (hasAudiblyStarted(startOutputPerformanceTime)) {
          finish("resumed");
          return;
        }
        Log.warn({ logLevel, tag: "audio" }, "WARNING: You enabled autoPlay on an unmuted <Player /> and the browser did not allow the video to be started. Remotion muted the <Player /> so it can play. To properly handle this, either set the `muted` prop or remove the `autoPlay` prop");
        finish("failed");
      }, RESUME_WAIT_TIMEOUT);
    }
    animationFrame = requestAnimationFrame(check);
  });
};

// src/audio/shared-audio-tags.tsx
import { jsx as jsx20, jsxs as jsxs2 } from "react/jsx-runtime";
var EMPTY_AUDIO = "data:audio/mp3;base64,/+MYxAAJcAV8AAgAABn//////+/gQ5BAMA+D4Pg+BAQBAEAwD4Pg+D4EBAEAQDAPg++hYBH///hUFQVBUFREDQNHmf///////+MYxBUGkAGIMAAAAP/29Xt6lUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxDUAAANIAAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV";
var compareProps = (obj1, obj2) => {
  const keysA = Object.keys(obj1).sort();
  const keysB = Object.keys(obj2).sort();
  if (keysA.length !== keysB.length) {
    return false;
  }
  for (let i = 0;i < keysA.length; i++) {
    if (keysA[i] !== keysB[i]) {
      return false;
    }
    if (obj1[keysA[i]] !== obj2[keysB[i]]) {
      return false;
    }
  }
  return true;
};
var didPropChange = (key, newProp, prevProp) => {
  if (key === "src" && !prevProp.startsWith("data:") && !newProp.startsWith("data:")) {
    return new URL(prevProp, document.baseURI).toString() !== new URL(newProp, document.baseURI).toString();
  }
  if (prevProp === newProp) {
    return false;
  }
  return true;
};
var SharedAudioContext = createContext22(null);
var SharedAudioTagsContext = createContext22(null);
var shouldSaveForLater = (state) => {
  if (state === "suspended" || state === "running-to-suspended" || state === "interrupted") {
    return true;
  }
  if (state === "running" || state === "suspended-to-running") {
    return false;
  }
  throw new Error(`Unexpected audio context state: ${state}`);
};
var SharedAudioContextProvider = ({
  children,
  audioLatencyHint,
  audioEnabled,
  previewSampleRate,
  _experimentalKeepAudioContextAlive
}) => {
  const logLevel = useLogLevel();
  const sampleRate = previewSampleRate ?? 48000;
  const ctxAndGain = useSingletonAudioContext({
    logLevel,
    latencyHint: audioLatencyHint,
    audioEnabled,
    sampleRate
  });
  const audioContextIsPlayingEventually = useRef13(false);
  const initialExperimentalKeepAudioContextAlive = useRef13(_experimentalKeepAudioContextAlive);
  if (initialExperimentalKeepAudioContextAlive.current !== _experimentalKeepAudioContextAlive) {
    throw new Error("`_experimentalKeepAudioContextAlive` cannot be changed dynamically.");
  }
  const isResuming = useRef13(null);
  const nextResumeAttemptId = useRef13(0);
  const nextResumeIsAutoPlayAttempt = useRef13(false);
  const audioSyncAnchor = useMemo21(() => ({ value: 0 }), []);
  const audioSyncAnchorListeners = useRef13([]);
  const audioSyncAnchorEmitter = useMemo21(() => {
    return {
      dispatch: (event) => {
        audioSyncAnchorListeners.current.forEach((l) => l(event));
      },
      subscribe: (listener) => {
        audioSyncAnchorListeners.current.push(listener);
        return {
          remove: () => {
            audioSyncAnchorListeners.current = audioSyncAnchorListeners.current.filter((l) => l !== listener);
          }
        };
      }
    };
  }, []);
  const prevEndTimes = useRef13({ scheduledEndTime: null, mediaEndTime: null });
  const nodesToResume = useRef13(new Map);
  const unscheduleAudioNode = useCallback10((node) => {
    nodesToResume.current.delete(node);
  }, []);
  const scheduleAudioNode = useMemo21(() => {
    return ({
      node,
      mediaTimestamp,
      sourceOffset,
      scheduledTime,
      duration,
      offset,
      originalUnloopedMediaTimestamp
    }) => {
      if (!ctxAndGain) {
        throw new Error("Audio context not found");
      }
      const currentState = ctxAndGain.getState();
      if (currentState === "closed") {
        return {
          type: "not-started",
          reason: "audio context is closed"
        };
      }
      const saveForLater = shouldSaveForLater(currentState) || _experimentalKeepAudioContextAlive && !audioContextIsPlayingEventually.current;
      if (duration > 0) {
        if (saveForLater) {
          nodesToResume.current.set(node, {
            scheduledTime,
            offset,
            duration
          });
        } else {
          node.start(scheduledTime, offset, duration);
        }
      }
      const scheduledEndTime = scheduledTime + duration / node.playbackRate.value;
      const mediaTime = mediaTimestamp + offset - sourceOffset;
      const mediaEndTime = mediaTime + duration;
      const latency = ctxAndGain.audioContext.baseLatency + ctxAndGain.audioContext.outputLatency;
      const timeDiff = scheduledTime - ctxAndGain.audioContext.currentTime;
      const prev = prevEndTimes.current;
      const scheduledMismatch = prev.scheduledEndTime !== null && Math.abs(scheduledTime - prev.scheduledEndTime) > 0.001;
      const mediaMismatch = prev.mediaEndTime !== null && Math.abs(mediaTime - prev.mediaEndTime) > 0.001;
      Log.verbose({ logLevel, tag: "audio-scheduling" }, "scheduled %c%s%c %s %c%s%c %s %c%s%c %s %s %s %s %s", scheduledMismatch ? "color: red; font-weight: bold" : "", scheduledTime.toFixed(4), "", scheduledEndTime.toFixed(4), mediaMismatch ? "color: red; font-weight: bold" : "", mediaTime.toFixed(4), "", mediaEndTime.toFixed(4), duration < 0 ? "color: red; font-weight: bold" : timeDiff < 0 ? "color: red; font-weight: bold" : "color: blue; font-weight: bold", duration < 0 ? "missed " + Math.abs(offset).toFixed(2) + "s" : Math.abs(timeDiff).toFixed(2) + (timeDiff < 0 ? " delay" : " ahead"), "", "current=" + ctxAndGain.audioContext.currentTime.toFixed(4), "offset=" + offset.toFixed(4), "latency=" + latency.toFixed(4), "state=" + ctxAndGain.audioContext.state, originalUnloopedMediaTimestamp !== mediaTime ? "original_ts=" + originalUnloopedMediaTimestamp.toFixed(4) : "", "action=" + (saveForLater ? "schedule" : "start"), "");
      prev.scheduledEndTime = scheduledEndTime;
      prev.mediaEndTime = mediaEndTime;
      return duration > 0 ? {
        type: "started",
        scheduledTime
      } : {
        type: "not-started",
        reason: "missed " + Math.abs(offset).toFixed(2) + "s"
      };
    };
  }, [ctxAndGain, _experimentalKeepAudioContextAlive, logLevel]);
  const resume = useCallback10(() => {
    const isAutoPlayAttempt = nextResumeIsAutoPlayAttempt.current;
    nextResumeIsAutoPlayAttempt.current = false;
    if (!ctxAndGain) {
      return Promise.resolve();
    }
    if (audioContextIsPlayingEventually.current) {
      return Promise.resolve();
    }
    audioContextIsPlayingEventually.current = true;
    ctxAndGain.gainNode.gain.cancelScheduledValues(ctxAndGain.audioContext.currentTime);
    ctxAndGain.gainNode.gain.setValueAtTime(0, ctxAndGain.audioContext.currentTime);
    ctxAndGain.gainNode.gain.linearRampToValueAtTime(1, ctxAndGain.audioContext.currentTime + 0.03);
    nodesToResume.current.forEach((r, node) => {
      node.start(r.scheduledTime, r.offset, r.duration);
    });
    nodesToResume.current.clear();
    if (_experimentalKeepAudioContextAlive && ctxAndGain.audioContext.state === "running") {
      return Promise.resolve();
    }
    const resumePromise = ctxAndGain.resume();
    const abortController = new AbortController;
    const resumeAttemptId = nextResumeAttemptId.current++;
    const waitPromise = new Promise((resolve) => {
      waitUntilActuallyResumed(ctxAndGain.audioContext, logLevel, abortController.signal, isAutoPlayAttempt).then(resolve);
      resumePromise.catch((err) => {
        Log.warn({ logLevel, tag: "audio" }, "AudioContext resume rejected, muting playback and continuing without audio", err);
        abortController.abort();
        resolve("failed");
      });
    }).finally(() => {
      if (isResuming.current?.id === resumeAttemptId) {
        isResuming.current = null;
      }
    });
    isResuming.current = {
      abortController,
      id: resumeAttemptId,
      promise: waitPromise
    };
    return resumePromise.catch(() => {});
  }, [ctxAndGain, _experimentalKeepAudioContextAlive, logLevel]);
  const resumeAsAutoPlay = useCallback10(() => {
    nextResumeIsAutoPlayAttempt.current = true;
    return resume();
  }, [resume]);
  const getIsResumingAudioContext = useCallback10(() => {
    return isResuming.current?.promise ?? null;
  }, []);
  const suspend = useCallback10(() => {
    isResuming.current?.abortController.abort();
    if (!ctxAndGain) {
      return Promise.resolve();
    }
    if (!audioContextIsPlayingEventually.current) {
      return Promise.resolve();
    }
    audioContextIsPlayingEventually.current = false;
    if (_experimentalKeepAudioContextAlive) {
      ctxAndGain.gainNode.gain.cancelScheduledValues(ctxAndGain.audioContext.currentTime);
      ctxAndGain.gainNode.gain.setValueAtTime(0, ctxAndGain.audioContext.currentTime);
      return Promise.resolve();
    }
    return ctxAndGain.suspend();
  }, [ctxAndGain, _experimentalKeepAudioContextAlive]);
  useEffect8(() => {
    if (!_experimentalKeepAudioContextAlive) {
      return;
    }
    if (!ctxAndGain) {
      return;
    }
    if (typeof window === "undefined") {
      return;
    }
    const wake = () => {
      if (ctxAndGain.audioContext.state === "running") {
        return;
      }
      ctxAndGain.resume().catch(() => {});
    };
    wake();
    window.addEventListener("pointerdown", wake, {
      capture: true,
      passive: true
    });
    window.addEventListener("keydown", wake, { capture: true, passive: true });
    return () => {
      window.removeEventListener("pointerdown", wake, { capture: true });
      window.removeEventListener("keydown", wake, { capture: true });
      ctxAndGain.suspend().catch(() => {});
    };
  }, [ctxAndGain, _experimentalKeepAudioContextAlive]);
  const audioContextValue = useMemo21(() => {
    return {
      sampleRate,
      audioContext: ctxAndGain?.audioContext ?? null,
      getAudioContextState: () => ctxAndGain?.getState() ?? null,
      gainNode: ctxAndGain?.gainNode ?? null,
      audioSyncAnchor,
      audioSyncAnchorEmitter,
      scheduleAudioNode,
      resume,
      resumeAsAutoPlay,
      suspend,
      getIsResumingAudioContext,
      unscheduleAudioNode,
      _experimentalKeepAudioContextAlive
    };
  }, [
    sampleRate,
    ctxAndGain,
    audioSyncAnchor,
    audioSyncAnchorEmitter,
    scheduleAudioNode,
    resume,
    resumeAsAutoPlay,
    suspend,
    getIsResumingAudioContext,
    unscheduleAudioNode,
    _experimentalKeepAudioContextAlive
  ]);
  return /* @__PURE__ */ jsx20(SharedAudioContext.Provider, {
    value: audioContextValue,
    children
  });
};
var SharedAudioTagsContextProvider = ({ children, numberOfAudioTags }) => {
  const audios = useRef13([]);
  const [initialNumberOfAudioTags] = useState11(numberOfAudioTags);
  if (numberOfAudioTags !== initialNumberOfAudioTags) {
    throw new Error("The number of shared audio tags has changed dynamically. Once you have set this property, you cannot change it afterwards.");
  }
  const logLevel = useLogLevel();
  const mountTime = useMountTime();
  const env = useRemotionEnvironment();
  const audioCtx = useContext23(SharedAudioContext);
  const audioContext = audioCtx?.audioContext ?? null;
  const resume = audioCtx?.resume;
  const [refs] = useState11(() => {
    return new Array(numberOfAudioTags).fill(true).map(() => {
      const ref = createRef2();
      return {
        id: Math.random(),
        ref,
        mediaElementSourceNode: makeSharedElementSourceNode({
          audioContext,
          ref
        })
      };
    });
  });
  for (const { mediaElementSourceNode } of refs) {
    mediaElementSourceNode?.setAudioContext(audioContext);
  }
  const effectToUse = React23.useInsertionEffect ?? React23.useLayoutEffect;
  effectToUse(() => {
    return () => {
      requestAnimationFrame(() => {
        refs.forEach(({ mediaElementSourceNode }) => {
          mediaElementSourceNode?.cleanup();
        });
      });
    };
  }, [refs]);
  const takenAudios = useRef13(new Array(numberOfAudioTags).fill(false));
  const rerenderAudios = useCallback10(() => {
    refs.forEach(({ ref, id }) => {
      const data = audios.current?.find((a2) => a2.id === id);
      const { current } = ref;
      if (!current) {
        return;
      }
      if (data === undefined) {
        if (current.src !== EMPTY_AUDIO) {
          current.src = EMPTY_AUDIO;
        }
        return;
      }
      if (!data) {
        throw new TypeError("Expected audio data to be there");
      }
      Object.keys(data.props).forEach((key) => {
        if (didPropChange(key, data.props[key], current[key])) {
          current[key] = data.props[key];
        }
      });
    });
  }, [refs]);
  const registerAudio = useCallback10((options) => {
    const { aud, audioId, premounting, postmounting } = options;
    const found = audios.current?.find((a2) => a2.audioId === audioId);
    if (found) {
      return found;
    }
    const firstFreeAudio = takenAudios.current.findIndex((a2) => a2 === false);
    if (firstFreeAudio === -1) {
      throw new Error(`Tried to simultaneously mount ${numberOfAudioTags + 1} <Html5Audio /> tags at the same time. With the current settings, the maximum amount of <Html5Audio /> tags is limited to ${numberOfAudioTags} at the same time. Remotion pre-mounts silent audio tags to help avoid browser autoplay restrictions. See https://remotion.dev/docs/player/autoplay#using-the-numberofsharedaudiotags-prop for more information on how to increase this limit.`);
    }
    const { id, ref, mediaElementSourceNode } = refs[firstFreeAudio];
    const cloned = [...takenAudios.current];
    cloned[firstFreeAudio] = id;
    takenAudios.current = cloned;
    const newElem = {
      props: aud,
      id,
      el: ref,
      audioId,
      mediaElementSourceNode,
      premounting,
      audioMounted: Boolean(ref.current),
      postmounting,
      cleanupOnMediaTagUnmount: () => {}
    };
    audios.current?.push(newElem);
    rerenderAudios();
    return newElem;
  }, [numberOfAudioTags, refs, rerenderAudios]);
  const unregisterAudio = useCallback10((id) => {
    const cloned = [...takenAudios.current];
    const index = refs.findIndex((r) => r.id === id);
    if (index === -1) {
      throw new TypeError(`Unknown audio ref ${id}; refs: ${refs.map((r) => r.id).join(", ")}`);
    }
    cloned[index] = false;
    takenAudios.current = cloned;
    audios.current = audios.current?.filter((a2) => a2.id !== id);
    rerenderAudios();
  }, [refs, rerenderAudios]);
  const updateAudio = useCallback10(({
    aud,
    audioId,
    id,
    premounting,
    postmounting
  }) => {
    let changed = false;
    audios.current = audios.current?.map((prevA) => {
      const audioMounted = Boolean(prevA.el.current);
      if (prevA.audioMounted !== audioMounted) {
        changed = true;
      }
      if (prevA.id === id) {
        const isTheSame = compareProps(aud, prevA.props) && prevA.premounting === premounting && prevA.postmounting === postmounting;
        if (isTheSame) {
          return prevA.audioMounted === audioMounted ? prevA : { ...prevA, audioMounted };
        }
        changed = true;
        return {
          ...prevA,
          props: aud,
          premounting,
          postmounting,
          audioId,
          audioMounted
        };
      }
      return prevA.audioMounted === audioMounted ? prevA : { ...prevA, audioMounted };
    });
    if (changed) {
      rerenderAudios();
    }
  }, [rerenderAudios]);
  const playAllAudios = useCallback10(() => {
    refs.forEach((ref) => {
      const audio = audios.current.find((a2) => a2.el === ref.ref);
      if (audio?.premounting) {
        return;
      }
      playAndHandleNotAllowedError({
        mediaRef: ref.ref,
        mediaType: "audio",
        onAutoPlayError: null,
        logLevel,
        mountTime,
        reason: "playing all audios",
        isPlayer: env.isPlayer
      });
    });
    resume?.();
  }, [logLevel, mountTime, refs, env.isPlayer, resume]);
  const audioTagsValue = useMemo21(() => {
    return {
      registerAudio,
      unregisterAudio,
      updateAudio,
      playAllAudios,
      numberOfAudioTags
    };
  }, [
    numberOfAudioTags,
    playAllAudios,
    registerAudio,
    unregisterAudio,
    updateAudio
  ]);
  const sharedAudioTagElements = useMemo21(() => {
    return refs.map(({ id, ref }) => {
      return /* @__PURE__ */ jsx20("audio", {
        ref,
        preload: "metadata",
        src: EMPTY_AUDIO
      }, id);
    });
  }, [refs]);
  return /* @__PURE__ */ jsxs2(SharedAudioTagsContext.Provider, {
    value: audioTagsValue,
    children: [
      sharedAudioTagElements,
      children
    ]
  });
};
var useSharedAudio = ({
  aud,
  audioId,
  premounting,
  postmounting
}) => {
  const audioCtx = useContext23(SharedAudioContext);
  const tagsCtx = useContext23(SharedAudioTagsContext);
  const [elem] = useState11(() => {
    if (tagsCtx && tagsCtx.numberOfAudioTags > 0) {
      return tagsCtx.registerAudio({ aud, audioId, premounting, postmounting });
    }
    const el = React23.createRef();
    const mediaElementSourceNode = makeSharedElementSourceNode({
      audioContext: audioCtx?.audioContext ?? null,
      ref: el
    });
    return {
      el,
      id: Math.random(),
      props: aud,
      audioId,
      mediaElementSourceNode,
      premounting,
      audioMounted: Boolean(el.current),
      postmounting,
      cleanupOnMediaTagUnmount: () => {
        mediaElementSourceNode?.cleanup();
      }
    };
  });
  elem.mediaElementSourceNode?.setAudioContext(audioCtx?.audioContext ?? null);
  const effectToUse = React23.useInsertionEffect ?? React23.useLayoutEffect;
  if (typeof document !== "undefined") {
    effectToUse(() => {
      if (tagsCtx && tagsCtx.numberOfAudioTags > 0) {
        tagsCtx.updateAudio({
          id: elem.id,
          aud,
          audioId,
          premounting,
          postmounting
        });
      }
    }, [aud, tagsCtx, elem.id, audioId, premounting, postmounting]);
    effectToUse(() => {
      return () => {
        if (tagsCtx && tagsCtx.numberOfAudioTags > 0) {
          tagsCtx.unregisterAudio(elem.id);
        }
      };
    }, [tagsCtx, elem.id]);
  }
  return elem;
};

// src/is-approximately-the-same.ts
var FLOATING_POINT_ERROR_THRESHOLD = 0.00001;
var isApproximatelyTheSame = (num1, num2) => {
  return Math.abs(num1 - num2) < FLOATING_POINT_ERROR_THRESHOLD;
};

// src/video/video-fragment.ts
import { useRef as useRef14 } from "react";
var toSeconds = (time, fps) => {
  return Math.round(time / fps * 100) / 100;
};
var isSafari = () => {
  if (typeof window === "undefined") {
    return false;
  }
  const isAppleWebKit = /AppleWebKit/.test(window.navigator.userAgent);
  if (!isAppleWebKit) {
    return false;
  }
  const isNotChrome = !window.navigator.userAgent.includes("Chrome/");
  return isNotChrome;
};
var isIosSafari = () => {
  if (typeof window === "undefined") {
    return false;
  }
  const { userAgent, platform, maxTouchPoints } = window.navigator;
  const isIpadIPodIPhone = /iP(ad|od|hone)/i.test(userAgent);
  const isIpadOsDesktopMode = platform === "MacIntel" && maxTouchPoints > 1;
  return (isIpadIPodIPhone || isIpadOsDesktopMode) && isSafari();
};
var isIOSSafariAndBlob = (actualSrc) => {
  return isIosSafari() && actualSrc.startsWith("blob:");
};
var getVideoFragmentStart = ({
  actualFrom,
  fps
}) => {
  return toSeconds(Math.max(0, -actualFrom), fps);
};
var getVideoFragmentEnd = ({
  duration,
  fps
}) => {
  return toSeconds(duration, fps);
};
var appendVideoFragment = ({
  actualSrc,
  actualFrom,
  duration,
  fps
}) => {
  if (isIOSSafariAndBlob(actualSrc)) {
    return actualSrc;
  }
  if (actualSrc.startsWith("data:")) {
    return actualSrc;
  }
  const existingHash = Boolean(new URL(actualSrc, (typeof window === "undefined" ? null : window.location.href) ?? "http://localhost:3000").hash);
  if (existingHash) {
    return actualSrc;
  }
  if (!Number.isFinite(actualFrom)) {
    return actualSrc;
  }
  const withStartHash = `${actualSrc}#t=${getVideoFragmentStart({ actualFrom, fps })}`;
  if (!Number.isFinite(duration)) {
    return withStartHash;
  }
  return `${withStartHash},${getVideoFragmentEnd({ duration, fps })}`;
};
var isSubsetOfDuration = ({
  prevStartFrom,
  newStartFrom,
  prevDuration,
  newDuration,
  fps
}) => {
  const previousFrom = getVideoFragmentStart({ actualFrom: prevStartFrom, fps });
  const newFrom = getVideoFragmentStart({ actualFrom: newStartFrom, fps });
  const previousEnd = getVideoFragmentEnd({ duration: prevDuration, fps });
  const newEnd = getVideoFragmentEnd({ duration: newDuration, fps });
  if (newFrom < previousFrom) {
    return false;
  }
  if (newEnd > previousEnd) {
    return false;
  }
  return true;
};
var useAppendVideoFragment = ({
  actualSrc: initialActualSrc,
  actualFrom: initialActualFrom,
  duration: initialDuration,
  fps
}) => {
  const actualFromRef = useRef14(initialActualFrom);
  const actualDuration = useRef14(initialDuration);
  const actualSrc = useRef14(initialActualSrc);
  if (!isSubsetOfDuration({
    prevStartFrom: actualFromRef.current,
    newStartFrom: initialActualFrom,
    prevDuration: actualDuration.current,
    newDuration: initialDuration,
    fps
  }) || initialActualSrc !== actualSrc.current) {
    actualFromRef.current = initialActualFrom;
    actualDuration.current = initialDuration;
    actualSrc.current = initialActualSrc;
  }
  const appended = appendVideoFragment({
    actualSrc: actualSrc.current,
    actualFrom: actualFromRef.current,
    duration: actualDuration.current,
    fps
  });
  return appended;
};

// src/use-amplification.ts
var warned2 = false;
var warnSafariOnce = (logLevel) => {
  if (warned2) {
    return;
  }
  warned2 = true;
  Log.warn({ logLevel, tag: null }, "In Safari, setting a volume and a playback rate at the same time is buggy.");
  Log.warn({ logLevel, tag: null }, "In Desktop Safari, only volumes <= 1 will be applied.");
  Log.warn({ logLevel, tag: null }, logLevel, "In Mobile Safari, the volume will be ignored and set to 1 if a playbackRate is set.");
};
var useVolume = ({
  mediaRef,
  volume,
  logLevel,
  source,
  shouldUseWebAudioApi
}) => {
  const audioStuffRef = useRef15(null);
  const currentVolumeRef = useRef15(volume);
  currentVolumeRef.current = volume;
  const sharedAudioContext = useContext24(SharedAudioContext);
  if (!sharedAudioContext) {
    throw new Error("useAmplification must be used within a SharedAudioContext");
  }
  const { audioContext, gainNode: masterGainNode } = sharedAudioContext;
  if (typeof window !== "undefined") {
    useLayoutEffect8(() => {
      if (!audioContext) {
        return;
      }
      if (!mediaRef.current) {
        return;
      }
      if (!shouldUseWebAudioApi) {
        return;
      }
      if (mediaRef.current.playbackRate !== 1 && isSafari()) {
        warnSafariOnce(logLevel);
        return;
      }
      if (!source) {
        return;
      }
      if (!masterGainNode) {
        return;
      }
      const gainNode = new GainNode(audioContext, {
        gain: currentVolumeRef.current
      });
      source.attemptToConnect();
      source.get().connect(gainNode);
      gainNode.connect(masterGainNode);
      audioStuffRef.current = {
        gainNode
      };
      Log.trace({ logLevel, tag: null }, `Starting to amplify ${mediaRef.current?.src}. Gain = ${currentVolumeRef.current}, playbackRate = ${mediaRef.current?.playbackRate}`);
      return () => {
        audioStuffRef.current = null;
        gainNode.disconnect();
        source.get().disconnect();
      };
    }, [
      logLevel,
      mediaRef,
      audioContext,
      source,
      shouldUseWebAudioApi,
      masterGainNode
    ]);
  }
  if (audioStuffRef.current) {
    const valueToSet = volume;
    if (!isApproximatelyTheSame(audioStuffRef.current.gainNode.gain.value, valueToSet)) {
      audioStuffRef.current.gainNode.gain.value = valueToSet;
      Log.trace({ logLevel, tag: null }, `Setting gain to ${valueToSet} for ${mediaRef.current?.src}`);
    }
  }
  const safariCase = isSafari() && mediaRef.current && mediaRef.current?.playbackRate !== 1;
  const shouldUseTraditionalVolume = safariCase || !shouldUseWebAudioApi;
  if (shouldUseTraditionalVolume && mediaRef.current && !isApproximatelyTheSame(volume, mediaRef.current?.volume)) {
    mediaRef.current.volume = Math.min(volume, 1);
  }
  return audioStuffRef;
};

// src/use-media-in-timeline.ts
import { useCallback as useCallback11, useContext as useContext26, useEffect as useEffect9, useMemo as useMemo22, useState as useState12 } from "react";

// src/audio/use-audio-frame.ts
import { useContext as useContext25 } from "react";
var useMediaStartsAt = () => {
  const parentSequence = useContext25(SequenceContext);
  return parentSequence?.cumulatedNegativeFrom ?? 0;
};
var useFrameForVolumeProp = (behavior) => {
  const loop = Loop.useLoop();
  const frame = useCurrentFrame();
  const startsAt = useMediaStartsAt();
  if (behavior === "repeat" || loop === null) {
    return frame + startsAt;
  }
  return frame + startsAt + loop.durationInFrames * loop.iteration;
};

// src/get-asset-file-name.ts
var getAssetDisplayName = (filename) => {
  if (filename.startsWith("data:")) {
    return "Data URL";
  }
  if (filename.startsWith("blob:")) {
    const staticFile = typeof window === "undefined" ? undefined : window.remotion_staticFiles?.find((file) => file.src === filename);
    return staticFile ? getAssetDisplayName(staticFile.name) : "Blob URL";
  }
  const splitted = filename.split("/").map((s) => s.split("\\")).flat(1);
  return splitted[splitted.length - 1];
};

// src/get-timeline-duration.ts
var getTimelineDuration = ({
  compositionDurationInFrames,
  playbackRate,
  trimBefore,
  trimAfter,
  parentSequenceDurationInFrames,
  loop
}) => {
  if (loop) {
    return compositionDurationInFrames;
  }
  const mediaDuration = calculateMediaDuration({
    mediaDurationInFrames: compositionDurationInFrames * playbackRate + (trimBefore ?? 0),
    playbackRate,
    trimBefore,
    trimAfter
  });
  if (parentSequenceDurationInFrames !== null) {
    const cappedDuration = Math.min(parentSequenceDurationInFrames, mediaDuration);
    return Number(cappedDuration.toFixed(10));
  }
  return mediaDuration;
};

// src/volume-prop.ts
var evaluateVolume = ({
  frame,
  volume,
  mediaVolume = 1
}) => {
  if (typeof volume === "number") {
    return volume * mediaVolume;
  }
  if (typeof volume === "undefined") {
    return Number(mediaVolume);
  }
  const evaluated = volume(frame) * mediaVolume;
  if (typeof evaluated !== "number") {
    throw new TypeError(`You passed in a a function to the volume prop but it did not return a number but a value of type ${typeof evaluated} for frame ${frame}`);
  }
  if (Number.isNaN(evaluated)) {
    throw new TypeError(`You passed in a function to the volume prop but it returned NaN for frame ${frame}.`);
  }
  if (!Number.isFinite(evaluated)) {
    throw new TypeError(`You passed in a function to the volume prop but it returned a non-finite number for frame ${frame}.`);
  }
  return Math.max(0, evaluated);
};

// src/use-media-in-timeline.ts
var didWarn = {};
var warnOnce2 = (message) => {
  if (didWarn[message]) {
    return;
  }
  console.warn(message);
  didWarn[message] = true;
};
var useBasicMediaInTimeline = ({
  volume,
  mediaVolume,
  mediaType,
  src,
  displayName,
  trimBefore,
  trimAfter,
  playbackRate,
  sequenceDurationInFrames,
  mediaStartsAt,
  loop,
  muted
}) => {
  if (!src) {
    throw new Error("No src passed");
  }
  const parentSequence = useContext26(SequenceContext);
  const [initialVolume] = useState12(() => volume);
  const duration = getTimelineDuration({
    compositionDurationInFrames: sequenceDurationInFrames,
    playbackRate,
    trimBefore,
    trimAfter,
    parentSequenceDurationInFrames: parentSequence?.durationInFrames ?? null,
    loop
  });
  const volumes = useMemo22(() => {
    if (typeof volume === "number") {
      return volume;
    }
    if (typeof volume !== "function") {
      return evaluateVolume({
        frame: 0,
        volume,
        mediaVolume
      });
    }
    return new Array(Math.floor(Math.max(0, duration + mediaStartsAt))).fill(true).map((_, i) => {
      return evaluateVolume({
        frame: i + mediaStartsAt,
        volume,
        mediaVolume
      });
    }).join(",");
  }, [duration, mediaStartsAt, volume, mediaVolume]);
  useEffect9(() => {
    if (typeof volume === "number" && volume !== initialVolume) {
      warnOnce2(`Remotion: The ${mediaType} with src ${src} has changed it's volume. Prefer the callback syntax for setting volume to get better timeline display: https://www.remotion.dev/docs/audio/volume`);
    }
  }, [initialVolume, mediaType, src, volume]);
  const doesVolumeChange = typeof volume === "function";
  const startMediaFrom = 0 - mediaStartsAt + (trimBefore ?? 0);
  const memoizedResult = useMemo22(() => {
    return {
      volumes,
      duration,
      doesVolumeChange,
      finalDisplayName: displayName ?? getAssetDisplayName(src),
      startMediaFrom,
      src,
      playbackRate,
      muted
    };
  }, [
    volumes,
    duration,
    doesVolumeChange,
    displayName,
    src,
    startMediaFrom,
    playbackRate,
    muted
  ]);
  return memoizedResult;
};
var useMediaInTimeline = ({
  volume,
  mediaVolume,
  src,
  mediaType,
  playbackRate,
  displayName,
  id,
  getStack,
  showInTimeline,
  premountDisplay,
  postmountDisplay,
  loopDisplay,
  documentationLink,
  refForOutline,
  muted
}) => {
  const parentSequence = useContext26(SequenceContext);
  const startsAt = useMediaStartsAt();
  const sequenceRegistrationEnabled = useContext26(SequenceRegistrationContext);
  const { durationInFrames } = useVideoConfig();
  const mediaStartsAt = useMediaStartsAt();
  const { volumes, duration, doesVolumeChange, finalDisplayName } = useBasicMediaInTimeline({
    volume,
    mediaVolume,
    mediaType,
    src,
    displayName,
    trimAfter: undefined,
    trimBefore: undefined,
    playbackRate,
    sequenceDurationInFrames: durationInFrames,
    mediaStartsAt,
    loop: false,
    muted
  });
  const { isStudio } = useRemotionEnvironment();
  const getSequenceForRegistration = useCallback11(() => {
    if (!src) {
      throw new Error("No src passed");
    }
    return {
      effectRuntimeValues: null,
      type: mediaType,
      src,
      id,
      duration,
      from: 0,
      trimBefore: null,
      parent: parentSequence?.id ?? null,
      displayName: finalDisplayName,
      documentationLink,
      volume: volumes,
      muted,
      showInTimeline: true,
      timelineOrder: null,
      startMediaFrom: 0 - startsAt,
      mediaFrameAtSequenceZero: null,
      doesVolumeChange,
      loopDisplay,
      playbackRate,
      getStack,
      premountDisplay,
      postmountDisplay,
      controls: null,
      effects: [],
      refForOutline,
      isInsideSeries: false,
      frozenFrame: null,
      frozenMediaFrame: null
    };
  }, [
    duration,
    id,
    parentSequence,
    src,
    volumes,
    doesVolumeChange,
    mediaType,
    startsAt,
    playbackRate,
    getStack,
    premountDisplay,
    postmountDisplay,
    loopDisplay,
    documentationLink,
    finalDisplayName,
    refForOutline,
    muted
  ]);
  const registrationEnabled = isStudio || sequenceRegistrationEnabled || typeof window !== "undefined" && window.process?.env?.NODE_ENV === "test";
  useSequenceRegistration({
    getSequence: registrationEnabled && showInTimeline ? getSequenceForRegistration : null,
    id
  });
};

// src/use-media-playback.ts
import { useCallback as useCallback14, useEffect as useEffect13, useLayoutEffect as useLayoutEffect10, useRef as useRef18 } from "react";

// src/buffer-until-first-frame.ts
import { useCallback as useCallback13, useMemo as useMemo25, useRef as useRef16 } from "react";

// src/use-buffer-state.ts
import { useContext as useContext28, useMemo as useMemo24 } from "react";

// src/buffering.tsx
import React24, {
  useCallback as useCallback12,
  useContext as useContext27,
  useEffect as useEffect10,
  useLayoutEffect as useLayoutEffect9,
  useMemo as useMemo23,
  useState as useState13
} from "react";
import { jsx as jsx21 } from "react/jsx-runtime";
var useBufferManager = (logLevel, mountTime, setBuffering, isBuffering) => {
  const [blockCount, setBlockCount] = useState13(0);
  const env = useRemotionEnvironment();
  const rendering = env.isRendering;
  const addBlock = useCallback12(() => {
    if (rendering) {
      return {
        unblock: () => {
          return;
        }
      };
    }
    let unblocked = false;
    setBlockCount((count) => count + 1);
    return {
      unblock: () => {
        if (unblocked) {
          return;
        }
        unblocked = true;
        setBlockCount((count) => count - 1);
      }
    };
  }, [rendering]);
  useEffect10(() => {
    if (rendering) {
      return;
    }
    if (blockCount > 0 && !isBuffering()) {
      setBuffering(true);
      playbackLogging({
        logLevel,
        message: "Player is entering buffer state",
        mountTime,
        tag: "player"
      });
    }
  }, [blockCount]);
  if (typeof window !== "undefined") {
    useLayoutEffect9(() => {
      if (rendering) {
        return;
      }
      if (blockCount === 0 && isBuffering()) {
        setBuffering(false);
        playbackLogging({
          logLevel,
          message: "Player is exiting buffer state",
          mountTime,
          tag: "player"
        });
      }
    }, [blockCount]);
  }
  return useMemo23(() => ({ addBlock }), [addBlock]);
};
var BufferingContextReact = React24.createContext(null);
var BufferingProvider = ({ children }) => {
  const { logLevel, mountTime } = useContext27(LogLevelContext);
  const { isBuffering, setBuffering } = useContext27(SetTimelineContext);
  const bufferManager = useBufferManager(logLevel ?? "info", mountTime, setBuffering, isBuffering);
  return /* @__PURE__ */ jsx21(BufferingContextReact.Provider, {
    value: bufferManager,
    children
  });
};

// src/use-buffer-state.ts
var useBufferState = () => {
  const buffer = useContext28(BufferingContextReact);
  const logLevel = useLogLevel();
  const addBlock = buffer ? buffer.addBlock : null;
  return useMemo24(() => ({
    delayPlayback: () => {
      if (!addBlock) {
        throw new Error("Tried to enable the buffering state, but a Remotion context was not found. This API can only be called in a component that was passed to the Remotion Player or a <Composition>. Or you might have experienced a version mismatch - run `npx remotion versions` and ensure all packages have the same version. This error is thrown by the buffer state https://remotion.dev/docs/player/buffer-state");
      }
      Log.trace({ logLevel, tag: "[buffer-state]" }, "Adding buffer handle", new Error().stack);
      const { unblock } = addBlock();
      let unblocked = false;
      return {
        unblock: () => {
          if (unblocked) {
            return;
          }
          unblocked = true;
          Log.trace({ logLevel, tag: "[buffer-state]" }, "Removing buffer handle");
          unblock();
        }
      };
    }
  }), [addBlock, logLevel]);
};

// src/buffer-until-first-frame.ts
var isSafariWebkit = () => {
  const isSafari2 = /^((?!chrome|android).)*safari/i.test(window.navigator.userAgent);
  return isSafari2;
};
var useBufferUntilFirstFrame = ({
  mediaRef,
  mediaType,
  onVariableFpsVideoDetected,
  pauseWhenBuffering,
  logLevel,
  mountTime
}) => {
  const bufferingRef = useRef16(false);
  const { delayPlayback } = useBufferState();
  const bufferUntilFirstFrame = useCallback13((requestedTime) => {
    if (mediaType !== "video") {
      return;
    }
    if (!pauseWhenBuffering) {
      return;
    }
    const current = mediaRef.current;
    if (!current) {
      return;
    }
    if (current.readyState >= current.HAVE_FUTURE_DATA && !isSafariWebkit()) {
      playbackLogging({
        logLevel,
        message: `Not using buffer until first frame, because readyState is ${current.readyState} and is not Safari or Desktop Chrome`,
        mountTime,
        tag: "buffer"
      });
      return;
    }
    if (!current.requestVideoFrameCallback) {
      playbackLogging({
        logLevel,
        message: `Not using buffer until first frame, because requestVideoFrameCallback is not supported`,
        mountTime,
        tag: "buffer"
      });
      return;
    }
    bufferingRef.current = true;
    playbackLogging({
      logLevel,
      message: `Buffering ${mediaRef.current?.src} until the first frame is received`,
      mountTime,
      tag: "buffer"
    });
    const playback = delayPlayback();
    const unblock = () => {
      playback.unblock();
      current.removeEventListener("ended", unblock, {
        once: true
      });
      current.removeEventListener("pause", unblock, {
        once: true
      });
      bufferingRef.current = false;
    };
    const onEndedOrPauseOrCanPlay = () => {
      unblock();
    };
    current.requestVideoFrameCallback((_, info2) => {
      const differenceFromRequested = Math.abs(info2.mediaTime - requestedTime);
      if (differenceFromRequested > 0.5) {
        onVariableFpsVideoDetected();
      }
      unblock();
    });
    current.addEventListener("ended", onEndedOrPauseOrCanPlay, { once: true });
    current.addEventListener("pause", onEndedOrPauseOrCanPlay, { once: true });
    current.addEventListener("canplay", onEndedOrPauseOrCanPlay, {
      once: true
    });
  }, [
    delayPlayback,
    logLevel,
    mediaRef,
    mediaType,
    mountTime,
    onVariableFpsVideoDetected,
    pauseWhenBuffering
  ]);
  return useMemo25(() => {
    return {
      isBuffering: () => bufferingRef.current,
      bufferUntilFirstFrame
    };
  }, [bufferUntilFirstFrame]);
};

// src/get-media-sync-action.ts
var getMediaSyncAction = (input) => {
  const {
    duration,
    currentTime,
    paused,
    ended,
    desiredUnclampedTime,
    mediaTagTime,
    mediaTagLastUpdate,
    rvcTime,
    rvcLastUpdate,
    isVariableFpsVideo,
    acceptableTimeShift,
    lastSeekDueToShift,
    playing,
    playbackRate,
    mediaTagBufferingOrStalled,
    playerBuffering,
    absoluteFrame,
    onlyWarnForMediaSeekingError,
    isPremounting,
    isPostmounting,
    pauseWhenBuffering
  } = input;
  const shouldBeTime = !Number.isNaN(duration) && Number.isFinite(duration) ? Math.min(duration, desiredUnclampedTime) : desiredUnclampedTime;
  const timeShiftMediaTag = Math.abs(shouldBeTime - mediaTagTime);
  const timeShiftRvcTag = rvcTime ? Math.abs(shouldBeTime - rvcTime) : null;
  const mostRecentTimeshift = rvcLastUpdate && rvcTime > mediaTagLastUpdate ? timeShiftRvcTag : timeShiftMediaTag;
  const timeShift = timeShiftRvcTag && !isVariableFpsVideo ? mostRecentTimeshift : timeShiftMediaTag;
  if (timeShift > acceptableTimeShift && lastSeekDueToShift !== shouldBeTime) {
    return {
      type: "seek-due-to-shift",
      shouldBeTime,
      why: `because time shift is too big. shouldBeTime = ${shouldBeTime}, isTime = ${mediaTagTime}, requestVideoCallbackTime = ${rvcTime}, timeShift = ${timeShift}${isVariableFpsVideo ? ", isVariableFpsVideo = true" : ""}, isPremounting = ${isPremounting}, isPostmounting = ${isPostmounting}, pauseWhenBuffering = ${pauseWhenBuffering}`,
      bufferUntilFirstFrame: playing && playbackRate > 0,
      playReason: playing && paused ? "player is playing but media tag is paused, and just seeked" : null,
      warnAboutNonSeekable: !onlyWarnForMediaSeekingError
    };
  }
  const seekThreshold = playing ? 0.15 : 0.01;
  const makesSenseToSeek = Math.abs(currentTime - shouldBeTime) > seekThreshold;
  const isSomethingElseBuffering = playerBuffering && !mediaTagBufferingOrStalled;
  if (!playing || isSomethingElseBuffering) {
    return {
      type: "seek-if-not-playing",
      shouldBeTime,
      why: makesSenseToSeek ? `not playing or something else is buffering. time offset is over seek threshold (${seekThreshold})` : null
    };
  }
  if (!playing || playerBuffering) {
    return { type: "none" };
  }
  const pausedCondition = paused && !ended;
  const firstFrameCondition = absoluteFrame === 0;
  if (pausedCondition || firstFrameCondition) {
    const reason = pausedCondition ? "media tag is paused" : "absolute frame is 0";
    return {
      type: "play-and-seek",
      shouldBeTime,
      why: makesSenseToSeek ? `is over timeshift threshold (threshold = ${seekThreshold}) and ${reason}` : null,
      playReason: `player is playing and ${reason}`,
      bufferUntilFirstFrame: !isVariableFpsVideo && playbackRate > 0
    };
  }
  return { type: "none" };
};

// src/media-tag-current-time-timestamp.ts
import React25 from "react";
var useCurrentTimeOfMediaTagWithUpdateTimeStamp = (mediaRef) => {
  const lastUpdate = React25.useRef({
    time: mediaRef.current?.currentTime ?? 0,
    lastUpdate: performance.now()
  });
  const nowCurrentTime = mediaRef.current?.currentTime ?? null;
  if (nowCurrentTime !== null) {
    if (lastUpdate.current.time !== nowCurrentTime) {
      lastUpdate.current.time = nowCurrentTime;
      lastUpdate.current.lastUpdate = performance.now();
    }
  }
  return lastUpdate;
};

// src/seek.ts
var seek = ({
  mediaRef,
  time,
  logLevel,
  why,
  mountTime
}) => {
  const timeToSet = isIosSafari() ? Number(time.toFixed(1)) : time;
  playbackLogging({
    logLevel,
    tag: "seek",
    message: `Seeking from ${mediaRef.currentTime} to ${timeToSet}. src= ${mediaRef.src} Reason: ${why}`,
    mountTime
  });
  mediaRef.currentTime = timeToSet;
  return timeToSet;
};

// src/use-media-buffering.ts
import { useEffect as useEffect11, useState as useState14 } from "react";
var useMediaBuffering = ({
  element,
  shouldBuffer,
  isPremounting,
  isPostmounting,
  logLevel,
  mountTime,
  src
}) => {
  const buffer = useBufferState();
  const [isBuffering, setIsBuffering] = useState14(false);
  useEffect11(() => {
    let cleanupFns = [];
    const { current } = element;
    if (!current) {
      return;
    }
    if (!shouldBuffer) {
      return;
    }
    if (isPremounting || isPostmounting) {
      if ((isPremounting || isPostmounting) && current.readyState < current.HAVE_FUTURE_DATA) {
        if (!navigator.userAgent.includes("Firefox/")) {
          playbackLogging({
            logLevel,
            message: `Calling .load() on ${current.src} because readyState is ${current.readyState} and it is not Firefox. Element is premounted ${current.playbackRate}`,
            tag: "load",
            mountTime
          });
          const previousPlaybackRate = current.playbackRate;
          current.load();
          current.playbackRate = previousPlaybackRate;
        }
      }
      return;
    }
    const cleanup = (reason) => {
      let didDoSomething = false;
      cleanupFns.forEach((fn) => {
        fn(reason);
        didDoSomething = true;
      });
      cleanupFns = [];
      setIsBuffering((previous) => {
        if (previous) {
          didDoSomething = true;
        }
        return false;
      });
      if (didDoSomething) {
        playbackLogging({
          logLevel,
          message: `Unmarking as buffering: ${current.src}. Reason: ${reason}`,
          tag: "buffer",
          mountTime
        });
      }
    };
    const blockMedia = (reason) => {
      setIsBuffering(true);
      playbackLogging({
        logLevel,
        message: `Marking as buffering: ${current.src}. Reason: ${reason}`,
        tag: "buffer",
        mountTime
      });
      const { unblock } = buffer.delayPlayback();
      const onCanPlay = () => {
        cleanup('"canplay" was fired');
        init();
      };
      const onError = () => {
        cleanup('"error" event was occurred');
        init();
      };
      current.addEventListener("canplay", onCanPlay, {
        once: true
      });
      cleanupFns.push(() => {
        current.removeEventListener("canplay", onCanPlay);
      });
      current.addEventListener("error", onError, {
        once: true
      });
      cleanupFns.push(() => {
        current.removeEventListener("error", onError);
      });
      cleanupFns.push((cleanupReason) => {
        playbackLogging({
          logLevel,
          message: `Unblocking ${current.src} from buffer. Reason: ${cleanupReason}`,
          tag: "buffer",
          mountTime
        });
        unblock();
      });
    };
    const init = () => {
      if (current.readyState < current.HAVE_FUTURE_DATA) {
        blockMedia(`readyState is ${current.readyState}, which is less than HAVE_FUTURE_DATA`);
        if (!navigator.userAgent.includes("Firefox/")) {
          playbackLogging({
            logLevel,
            message: `Calling .load() on ${src} because readyState is ${current.readyState} and it is not Firefox. ${current.playbackRate}`,
            tag: "load",
            mountTime
          });
          const previousPlaybackRate = current.playbackRate;
          current.load();
          current.playbackRate = previousPlaybackRate;
        }
      } else {
        const onWaiting = () => {
          blockMedia('"waiting" event was fired');
        };
        current.addEventListener("waiting", onWaiting);
        cleanupFns.push(() => {
          current.removeEventListener("waiting", onWaiting);
        });
      }
    };
    init();
    return () => {
      cleanup("element was unmounted or prop changed");
    };
  }, [
    buffer,
    src,
    element,
    isPremounting,
    isPostmounting,
    logLevel,
    shouldBuffer,
    mountTime
  ]);
  return isBuffering;
};

// src/use-request-video-callback-time.ts
import { useEffect as useEffect12, useRef as useRef17 } from "react";
var useRequestVideoCallbackTime = ({
  mediaRef,
  mediaType,
  lastSeek,
  onVariableFpsVideoDetected
}) => {
  const currentTime = useRef17(null);
  useEffect12(() => {
    const { current } = mediaRef;
    if (current) {
      currentTime.current = {
        time: current.currentTime,
        lastUpdate: performance.now()
      };
    } else {
      currentTime.current = null;
      return;
    }
    if (mediaType !== "video") {
      currentTime.current = null;
      return;
    }
    const videoTag = current;
    if (!videoTag.requestVideoFrameCallback) {
      return;
    }
    let cancel = () => {
      return;
    };
    const request = () => {
      if (!videoTag) {
        return;
      }
      const cb = videoTag.requestVideoFrameCallback((_, info2) => {
        if (currentTime.current !== null) {
          const difference = Math.abs(currentTime.current.time - info2.mediaTime);
          const differenceToLastSeek = Math.abs(lastSeek.current === null ? Infinity : info2.mediaTime - lastSeek.current);
          if (difference > 0.5 && differenceToLastSeek > 0.5 && info2.mediaTime > currentTime.current.time) {
            onVariableFpsVideoDetected();
          }
        }
        currentTime.current = {
          time: info2.mediaTime,
          lastUpdate: performance.now()
        };
        request();
      });
      cancel = () => {
        videoTag.cancelVideoFrameCallback(cb);
        cancel = () => {
          return;
        };
      };
    };
    request();
    return () => {
      cancel();
    };
  }, [lastSeek, mediaRef, mediaType, onVariableFpsVideoDetected]);
  return currentTime;
};

// src/video/get-current-time.ts
var getExpectedMediaFrameUncorrected = ({
  frame,
  playbackRate,
  startFrom
}) => {
  return interpolate(frame, [-1, startFrom, startFrom + 1], [-1, startFrom, startFrom + playbackRate]);
};
var getMediaTime = ({
  fps,
  frame,
  playbackRate,
  startFrom
}) => {
  const expectedFrame = getExpectedMediaFrameUncorrected({
    frame,
    playbackRate,
    startFrom
  });
  const msPerFrame = 1000 / fps;
  return expectedFrame * msPerFrame / 1000;
};

// src/warn-about-non-seekable-media.ts
var alreadyWarned = {};
var warnAboutNonSeekableMedia = (ref, type) => {
  if (ref === null) {
    return;
  }
  if (ref.seekable.length === 0) {
    return;
  }
  if (ref.seekable.length > 1) {
    return;
  }
  if (alreadyWarned[ref.src]) {
    return;
  }
  const range = { start: ref.seekable.start(0), end: ref.seekable.end(0) };
  if (range.start === 0 && range.end === 0) {
    const msg = [
      `The media ${ref.src} cannot be seeked. This could be one of few reasons:`,
      "1) The media resource was replaced while the video is playing but it was not loaded yet.",
      "2) The media does not support seeking.",
      "3) The media was loaded with security headers prventing it from being included.",
      "Please see https://remotion.dev/docs/non-seekable-media for assistance."
    ].join(`
`);
    if (type === "console-error") {
      console.error(msg);
    } else if (type === "console-warning") {
      console.warn(`The media ${ref.src} does not support seeking. The video will render fine, but may not play correctly in the Remotion Studio and in the <Player>. See https://remotion.dev/docs/non-seekable-media for an explanation.`);
    } else {
      throw new Error(msg);
    }
    alreadyWarned[ref.src] = true;
  }
};

// src/use-media-playback.ts
var DEFAULT_ACCEPTABLE_TIMESHIFT_WITH_AMPLIFICATION = 0.65;
var getPauseReason = ({
  reason,
  isPremounting,
  isPostmounting
}) => {
  if (reason === "buffering") {
    return "player is buffering but media tag is not";
  }
  if (isPremounting) {
    return "media is premounting";
  }
  if (isPostmounting) {
    return "media is postmounting";
  }
  return "Player is not playing";
};
var useMediaPlayback = ({
  mediaRef,
  src,
  mediaType,
  playbackRate: localPlaybackRate,
  preservePitch = true,
  onlyWarnForMediaSeekingError,
  acceptableTimeshift,
  pauseWhenBuffering,
  isPremounting,
  isPostmounting,
  onAutoPlayError
}) => {
  const { playbackRate: globalPlaybackRate } = usePlaybackRate();
  const frame = useCurrentFrame();
  const absoluteFrame = useTimelinePosition();
  const playing = usePlaying();
  const playerBuffering = useBuffering();
  const { fps } = useVideoConfig();
  const mediaStartsAt = useMediaStartsAt();
  const lastSeekDueToShift = useRef18(null);
  const lastSeek = useRef18(null);
  const logLevel = useLogLevel();
  const mountTime = useMountTime();
  const isVariableFpsVideoMap = useRef18({});
  const onVariableFpsVideoDetected = useCallback14(() => {
    if (!src) {
      return;
    }
    if (isVariableFpsVideoMap.current[src]) {
      return;
    }
    Log.verbose({ logLevel, tag: null }, `Detected ${src} as a variable FPS video. Disabling buffering while seeking.`);
    isVariableFpsVideoMap.current[src] = true;
  }, [logLevel, src]);
  const rvcCurrentTime = useRequestVideoCallbackTime({
    mediaRef,
    mediaType,
    lastSeek,
    onVariableFpsVideoDetected
  });
  const mediaTagCurrentTime = useCurrentTimeOfMediaTagWithUpdateTimeStamp(mediaRef);
  const desiredUnclampedTime = getMediaTime({
    frame,
    playbackRate: localPlaybackRate,
    startFrom: -mediaStartsAt,
    fps
  });
  const isMediaTagBuffering = useMediaBuffering({
    element: mediaRef,
    shouldBuffer: pauseWhenBuffering,
    isPremounting,
    isPostmounting,
    logLevel,
    mountTime,
    src: src ?? null
  });
  const { bufferUntilFirstFrame, isBuffering } = useBufferUntilFirstFrame({
    mediaRef,
    mediaType,
    onVariableFpsVideoDetected,
    pauseWhenBuffering,
    logLevel,
    mountTime
  });
  const playbackRate = localPlaybackRate * globalPlaybackRate;
  const acceptableTimeShiftButLessThanDuration = (() => {
    if (mediaRef.current?.duration) {
      return Math.min(mediaRef.current.duration, acceptableTimeshift ?? DEFAULT_ACCEPTABLE_TIMESHIFT_WITH_AMPLIFICATION);
    }
    return acceptableTimeshift ?? DEFAULT_ACCEPTABLE_TIMESHIFT_WITH_AMPLIFICATION;
  })();
  const env = useRemotionEnvironment();
  useLayoutEffect10(() => {
    const playbackRateToSet = Math.max(0, playbackRate);
    if (mediaRef.current && mediaRef.current.defaultPlaybackRate !== playbackRateToSet) {
      mediaRef.current.defaultPlaybackRate = playbackRateToSet;
    }
    if (mediaRef.current && mediaRef.current.playbackRate !== playbackRateToSet) {
      mediaRef.current.playbackRate = playbackRateToSet;
    }
    if (mediaRef.current && mediaRef.current.preservesPitch !== preservePitch) {
      mediaRef.current.preservesPitch = preservePitch;
    }
  }, [mediaRef, playbackRate, preservePitch]);
  useEffect13(() => {
    const tagName = mediaType === "audio" ? "<Html5Audio>" : "<Html5Video>";
    if (!mediaRef.current) {
      throw new Error(`No ${mediaType} ref found`);
    }
    if (!src) {
      throw new Error(`No 'src' attribute was passed to the ${tagName} element.`);
    }
    const { current } = mediaRef;
    const isMediaTagBufferingOrStalled = isMediaTagBuffering || isBuffering();
    let pauseReason = null;
    if (!playing) {
      pauseReason = "not-playing";
    } else if (playerBuffering && !isMediaTagBufferingOrStalled) {
      pauseReason = "buffering";
    }
    if (!current.paused && pauseReason !== null) {
      playbackLogging({
        logLevel,
        tag: "pause",
        message: `Pausing ${current.src} because ${getPauseReason({
          reason: pauseReason,
          isPremounting,
          isPostmounting
        })}`,
        mountTime
      });
      current.pause();
    }
    const action = getMediaSyncAction({
      duration: current.duration,
      currentTime: current.currentTime,
      paused: current.paused,
      ended: current.ended,
      desiredUnclampedTime,
      mediaTagTime: mediaTagCurrentTime.current.time,
      mediaTagLastUpdate: mediaTagCurrentTime.current.lastUpdate,
      rvcTime: rvcCurrentTime.current?.time ?? null,
      rvcLastUpdate: rvcCurrentTime.current?.lastUpdate ?? null,
      isVariableFpsVideo: Boolean(isVariableFpsVideoMap.current[src]),
      acceptableTimeShift: acceptableTimeShiftButLessThanDuration,
      lastSeekDueToShift: lastSeekDueToShift.current,
      playing,
      playbackRate,
      mediaTagBufferingOrStalled: isMediaTagBufferingOrStalled,
      playerBuffering,
      absoluteFrame,
      onlyWarnForMediaSeekingError,
      isPremounting,
      isPostmounting,
      pauseWhenBuffering
    });
    if (action.type === "none") {
      return;
    }
    if (action.type === "seek-due-to-shift") {
      lastSeek.current = seek({
        mediaRef: current,
        time: action.shouldBeTime,
        logLevel,
        why: action.why,
        mountTime
      });
      lastSeekDueToShift.current = lastSeek.current;
      if (action.bufferUntilFirstFrame) {
        bufferUntilFirstFrame(action.shouldBeTime);
      }
      if (action.playReason !== null) {
        playAndHandleNotAllowedError({
          mediaRef,
          mediaType,
          onAutoPlayError,
          logLevel,
          mountTime,
          reason: action.playReason,
          isPlayer: env.isPlayer
        });
      }
      if (action.warnAboutNonSeekable) {
        warnAboutNonSeekableMedia(current, "console-error");
      }
      return;
    }
    if (action.type === "seek-if-not-playing") {
      if (action.why !== null) {
        lastSeek.current = seek({
          mediaRef: current,
          time: action.shouldBeTime,
          logLevel,
          why: action.why,
          mountTime
        });
      }
      return;
    }
    if (action.why !== null) {
      lastSeek.current = seek({
        mediaRef: current,
        time: action.shouldBeTime,
        logLevel,
        why: action.why,
        mountTime
      });
    }
    playAndHandleNotAllowedError({
      mediaRef,
      mediaType,
      onAutoPlayError,
      logLevel,
      mountTime,
      reason: action.playReason,
      isPlayer: env.isPlayer
    });
    if (action.bufferUntilFirstFrame) {
      bufferUntilFirstFrame(action.shouldBeTime);
    }
  }, [
    absoluteFrame,
    acceptableTimeShiftButLessThanDuration,
    bufferUntilFirstFrame,
    rvcCurrentTime,
    logLevel,
    desiredUnclampedTime,
    isBuffering,
    isMediaTagBuffering,
    mediaRef,
    mediaType,
    onlyWarnForMediaSeekingError,
    playbackRate,
    playerBuffering,
    playing,
    src,
    onAutoPlayError,
    isPremounting,
    isPostmounting,
    pauseWhenBuffering,
    mountTime,
    mediaTagCurrentTime,
    env.isPlayer
  ]);
};

// src/use-media-tag.ts
import { useContext as useContext29, useEffect as useEffect14, useRef as useRef19 } from "react";
var useMediaTag = ({
  mediaRef,
  id,
  mediaType,
  onAutoPlayError,
  isPremounting,
  isPostmounting
}) => {
  const { audioAndVideoTags, isPlaying } = useTimelineContext();
  const { subscribePlaying } = useContext29(SetTimelineContext);
  const isPlayingRef = useRef19(isPlaying);
  isPlayingRef.current = isPlaying;
  const logLevel = useLogLevel();
  const mountTime = useMountTime();
  const env = useRemotionEnvironment();
  useEffect14(() => {
    const tag = {
      id,
      play: (reason) => {
        if (!isPlayingRef.current()) {
          return;
        }
        if (isPremounting || isPostmounting) {
          return;
        }
        return playAndHandleNotAllowedError({
          mediaRef,
          mediaType,
          onAutoPlayError,
          logLevel,
          mountTime,
          reason,
          isPlayer: env.isPlayer
        });
      }
    };
    audioAndVideoTags.current.push(tag);
    const unsubscribe = subscribePlaying((state) => {
      if (state.playing) {
        return;
      }
      const media = mediaRef.current;
      if (!media || media.paused) {
        return;
      }
      playbackLogging({
        logLevel,
        tag: "pause",
        message: `Pausing ${media.src} because Player is not playing`,
        mountTime
      });
      media.pause();
    });
    return () => {
      unsubscribe();
      audioAndVideoTags.current = audioAndVideoTags.current.filter((a2) => a2.id !== id);
    };
  }, [
    audioAndVideoTags,
    id,
    mediaRef,
    mediaType,
    onAutoPlayError,
    isPremounting,
    isPostmounting,
    logLevel,
    mountTime,
    env.isPlayer,
    subscribePlaying
  ]);
};

// src/volume-position-state.ts
import { createContext as createContext23, useContext as useContext30, useMemo as useMemo26 } from "react";
var MediaVolumeContext = createContext23({
  playerMuted: false,
  mediaVolume: 1
});
var SetMediaVolumeContext = createContext23({
  setPlayerMuted: () => {
    throw new Error("default");
  },
  setMediaVolume: () => {
    throw new Error("default");
  }
});
var useMediaVolumeState = () => {
  const { mediaVolume } = useContext30(MediaVolumeContext);
  const { setMediaVolume } = useContext30(SetMediaVolumeContext);
  return useMemo26(() => {
    return [mediaVolume, setMediaVolume];
  }, [mediaVolume, setMediaVolume]);
};
var usePlayerMutedState = () => {
  const { playerMuted } = useContext30(MediaVolumeContext);
  const { setPlayerMuted } = useContext30(SetMediaVolumeContext);
  return useMemo26(() => {
    return [playerMuted, setPlayerMuted];
  }, [playerMuted, setPlayerMuted]);
};

// src/volume-safeguard.ts
var warnAboutTooHighVolume = (volume) => {
  if (volume >= 100) {
    throw new Error(`Volume was set to ${volume}, but regular volume is 1, not 100. Did you forget to divide by 100? Set a volume of less than 100 to dismiss this error.`);
  }
};

// src/audio/use-media-audio-state.ts
var resolveMediaAudioState = ({
  muted,
  playerMuted,
  volume,
  isInsideFreeze,
  audioEnabled
}) => {
  const isMutedForTimeline = muted || isInsideFreeze;
  const isMutedForPlayback = isMutedForTimeline || playerMuted || volume !== null && volume <= 0;
  return {
    isMutedForTimeline,
    isMutedForPlayback,
    shouldUseAudio: audioEnabled && !isMutedForPlayback
  };
};
var useMediaAudioState = ({
  muted,
  volume,
  audioEnabled
}) => {
  const [playerMuted] = usePlayerMutedState();
  const isInsideFreeze = useIsInsideFreeze();
  return resolveMediaAudioState({
    muted,
    playerMuted,
    volume,
    isInsideFreeze,
    audioEnabled
  });
};

// src/audio/AudioForPreview.tsx
import { jsx as jsx22 } from "react/jsx-runtime";
var AudioForDevelopmentForwardRefFunction = (props, ref) => {
  const [initialShouldPreMountAudioElements] = useState15(props.shouldPreMountAudioTags);
  if (props.shouldPreMountAudioTags !== initialShouldPreMountAudioElements) {
    throw new Error("Cannot change the behavior for pre-mounting audio tags dynamically.");
  }
  const logLevel = useLogLevel();
  const {
    volume,
    muted,
    playbackRate,
    preservePitch,
    shouldPreMountAudioTags,
    src,
    onDuration,
    acceptableTimeShiftInSeconds,
    _remotionInternalNeedsDurationCalculation,
    _remotionInternalNativeLoopPassed,
    _remotionInternalStack,
    allowAmplificationDuringRender,
    name,
    pauseWhenBuffering,
    showInTimeline,
    loopVolumeCurveBehavior,
    crossOrigin,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    toneFrequency,
    useWebAudioApi,
    onError,
    onNativeError,
    audioStreamIndex,
    ...nativeProps
  } = props;
  const _propsValid = true;
  if (!_propsValid) {
    throw new Error("typecheck error");
  }
  const [mediaVolume] = useMediaVolumeState();
  const volumePropFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
  if (!src) {
    throw new TypeError("No 'src' was passed to <Html5Audio>.");
  }
  const preloadedSrc = usePreload(src);
  const sequenceContext = useContext31(SequenceContext);
  const { isStudio } = useRemotionEnvironment();
  const [timelineId] = useState15(() => String(Math.random()));
  const userPreferredVolume = evaluateVolume({
    frame: volumePropFrame,
    volume,
    mediaVolume
  });
  const { isMutedForTimeline, isMutedForPlayback } = useMediaAudioState({
    muted: muted ?? false,
    volume: userPreferredVolume,
    audioEnabled: true
  });
  warnAboutTooHighVolume(userPreferredVolume);
  const crossOriginValue = getCrossOriginValue({
    crossOrigin,
    requestsVideoFrame: false,
    isClientSideRendering: false
  });
  const propsToPass = useMemo27(() => {
    return {
      muted: isMutedForPlayback,
      src: preloadedSrc,
      loop: _remotionInternalNativeLoopPassed,
      crossOrigin: crossOriginValue,
      ...nativeProps
    };
  }, [
    _remotionInternalNativeLoopPassed,
    isMutedForPlayback,
    nativeProps,
    preloadedSrc,
    crossOriginValue
  ]);
  const id = useMemo27(() => `audio-${random(src ?? "")}-${sequenceContext?.relativeFrom}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.durationInFrames}-muted:${props.muted}-loop:${props.loop}`, [
    src,
    sequenceContext?.relativeFrom,
    sequenceContext?.cumulatedFrom,
    sequenceContext?.durationInFrames,
    props.muted,
    props.loop
  ]);
  const {
    el: audioRef,
    mediaElementSourceNode,
    cleanupOnMediaTagUnmount
  } = useSharedAudio({
    aud: propsToPass,
    audioId: id,
    premounting: Boolean(sequenceContext?.premounting),
    postmounting: Boolean(sequenceContext?.postmounting)
  });
  const getStack = useCallback15(() => {
    return _remotionInternalStack ?? null;
  }, [_remotionInternalStack]);
  useMediaInTimeline({
    volume,
    mediaVolume,
    src,
    mediaType: "audio",
    playbackRate: playbackRate ?? 1,
    displayName: name ?? null,
    id: timelineId,
    getStack,
    showInTimeline,
    premountDisplay: sequenceContext?.premountDisplay ?? null,
    postmountDisplay: sequenceContext?.postmountDisplay ?? null,
    loopDisplay: undefined,
    documentationLink: "https://www.remotion.dev/docs/html5-audio",
    refForOutline: null,
    muted: isMutedForTimeline
  });
  useMediaPlayback({
    mediaRef: audioRef,
    src,
    mediaType: "audio",
    playbackRate: playbackRate ?? 1,
    preservePitch,
    onlyWarnForMediaSeekingError: false,
    acceptableTimeshift: acceptableTimeShiftInSeconds ?? null,
    isPremounting: Boolean(sequenceContext?.premounting),
    isPostmounting: Boolean(sequenceContext?.postmounting),
    pauseWhenBuffering,
    onAutoPlayError: null
  });
  useMediaTag({
    id: timelineId,
    isPostmounting: Boolean(sequenceContext?.postmounting),
    isPremounting: Boolean(sequenceContext?.premounting),
    mediaRef: audioRef,
    mediaType: "audio",
    onAutoPlayError: null
  });
  useVolume({
    logLevel,
    mediaRef: audioRef,
    source: mediaElementSourceNode,
    volume: userPreferredVolume,
    shouldUseWebAudioApi: useWebAudioApi ?? false
  });
  const effectToUse = React26.useInsertionEffect ?? React26.useLayoutEffect;
  effectToUse(() => {
    return () => {
      requestAnimationFrame(() => {
        cleanupOnMediaTagUnmount();
      });
    };
  }, [cleanupOnMediaTagUnmount]);
  useImperativeHandle4(ref, () => {
    return audioRef.current;
  }, [audioRef]);
  const currentOnDurationCallback = useRef20(onDuration);
  currentOnDurationCallback.current = onDuration;
  useEffect15(() => {
    const { current } = audioRef;
    if (!current) {
      return;
    }
    if (current.duration) {
      currentOnDurationCallback.current?.(current.src, current.duration);
      return;
    }
    const onLoadedMetadata = () => {
      currentOnDurationCallback.current?.(current.src, current.duration);
    };
    current.addEventListener("loadedmetadata", onLoadedMetadata);
    return () => {
      current.removeEventListener("loadedmetadata", onLoadedMetadata);
    };
  }, [audioRef, src]);
  if (initialShouldPreMountAudioElements) {
    return isStudio ? /* @__PURE__ */ jsx22(SequenceOrderMarker, {
      sequenceId: timelineId,
      children: null
    }) : null;
  }
  const audio = /* @__PURE__ */ jsx22("audio", {
    ref: audioRef,
    preload: "metadata",
    crossOrigin: crossOriginValue,
    ...propsToPass
  });
  return isStudio ? /* @__PURE__ */ jsx22(SequenceOrderMarker, {
    sequenceId: timelineId,
    children: audio
  }) : audio;
};
var AudioForPreview = forwardRef5(AudioForDevelopmentForwardRefFunction);

// src/audio/AudioForRendering.tsx
import {
  forwardRef as forwardRef6,
  useContext as useContext33,
  useEffect as useEffect16,
  useImperativeHandle as useImperativeHandle5,
  useLayoutEffect as useLayoutEffect11,
  useMemo as useMemo29,
  useRef as useRef21
} from "react";

// src/use-media-enabled.tsx
import { createContext as createContext24, useContext as useContext32, useMemo as useMemo28 } from "react";
import { jsx as jsx23 } from "react/jsx-runtime";
var MediaEnabledContext = createContext24(null);
var useVideoEnabled = () => {
  const context = useContext32(MediaEnabledContext);
  if (!context) {
    return window.remotion_videoEnabled;
  }
  if (context.videoEnabled === null) {
    return window.remotion_videoEnabled;
  }
  return context.videoEnabled;
};
var useAudioEnabled = () => {
  const context = useContext32(MediaEnabledContext);
  if (!context) {
    return window.remotion_audioEnabled;
  }
  if (context.audioEnabled === null) {
    return window.remotion_audioEnabled;
  }
  return context.audioEnabled;
};
var MediaEnabledProvider = ({
  children,
  videoEnabled,
  audioEnabled
}) => {
  const value = useMemo28(() => ({ videoEnabled, audioEnabled }), [videoEnabled, audioEnabled]);
  return /* @__PURE__ */ jsx23(MediaEnabledContext.Provider, {
    value,
    children
  });
};

// src/audio/AudioForRendering.tsx
import { jsx as jsx24 } from "react/jsx-runtime";
var AudioForRenderingRefForwardingFunction = (props, ref) => {
  const audioRef = useRef21(null);
  const {
    volume: volumeProp,
    playbackRate,
    allowAmplificationDuringRender,
    onDuration,
    toneFrequency,
    _remotionInternalNeedsDurationCalculation,
    _remotionInternalNativeLoopPassed,
    acceptableTimeShiftInSeconds,
    name,
    onNativeError,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    loopVolumeCurveBehavior,
    pauseWhenBuffering,
    audioStreamIndex,
    preservePitch: _preservePitch,
    ...nativeProps
  } = props;
  const absoluteFrame = useTimelinePosition();
  const volumePropFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
  const frame = useCurrentFrame();
  const sequenceContext = useContext33(SequenceContext);
  const { registerRenderAsset, unregisterRenderAsset } = useContext33(RenderAssetManager);
  const { delayRender: delayRender2, continueRender: continueRender2 } = useDelayRender();
  const id = useMemo29(() => `audio-${random(props.src ?? "")}-${sequenceContext?.relativeFrom}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.durationInFrames}`, [
    props.src,
    sequenceContext?.relativeFrom,
    sequenceContext?.cumulatedFrom,
    sequenceContext?.durationInFrames
  ]);
  const volume = evaluateVolume({
    volume: volumeProp,
    frame: volumePropFrame,
    mediaVolume: 1
  });
  warnAboutTooHighVolume(volume);
  const audioEnabled = useAudioEnabled();
  const { shouldUseAudio } = useMediaAudioState({
    muted: props.muted ?? false,
    volume,
    audioEnabled
  });
  useImperativeHandle5(ref, () => {
    return audioRef.current;
  }, []);
  useEffect16(() => {
    if (!props.src) {
      throw new Error("No src passed");
    }
    if (!shouldUseAudio) {
      return;
    }
    registerRenderAsset({
      type: "audio",
      src: getAbsoluteSrc(props.src),
      id,
      frame: absoluteFrame,
      volume,
      mediaFrame: frame,
      playbackRate: props.playbackRate ?? 1,
      toneFrequency: toneFrequency ?? 1,
      audioStartFrame: Math.max(0, -(sequenceContext?.cumulatedNegativeFrom ?? 0)),
      audioStreamIndex: audioStreamIndex ?? 0
    });
    return () => unregisterRenderAsset(id);
  }, [
    shouldUseAudio,
    props.src,
    registerRenderAsset,
    absoluteFrame,
    id,
    unregisterRenderAsset,
    volume,
    volumePropFrame,
    frame,
    playbackRate,
    props.playbackRate,
    toneFrequency,
    sequenceContext?.cumulatedNegativeFrom,
    audioStreamIndex
  ]);
  const { src } = props;
  const needsToRenderAudioTag = ref || _remotionInternalNeedsDurationCalculation;
  useLayoutEffect11(() => {
    if (window.process?.env?.NODE_ENV === "test") {
      return;
    }
    if (!needsToRenderAudioTag) {
      return;
    }
    const newHandle = delayRender2("Loading <Html5Audio> duration with src=" + src, {
      retries: delayRenderRetries ?? undefined,
      timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
    });
    const { current } = audioRef;
    const didLoad = () => {
      if (current?.duration) {
        onDuration(current.src, current.duration);
      }
      continueRender2(newHandle);
    };
    if (current?.duration) {
      onDuration(current.src, current.duration);
      continueRender2(newHandle);
    } else {
      current?.addEventListener("loadedmetadata", didLoad, { once: true });
    }
    return () => {
      current?.removeEventListener("loadedmetadata", didLoad);
      continueRender2(newHandle);
    };
  }, [
    src,
    onDuration,
    needsToRenderAudioTag,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    continueRender2,
    delayRender2
  ]);
  if (!needsToRenderAudioTag) {
    return null;
  }
  return /* @__PURE__ */ jsx24("audio", {
    ref: audioRef,
    ...nativeProps,
    onError: onNativeError
  });
};
var AudioForRendering = forwardRef6(AudioForRenderingRefForwardingFunction);

// src/audio/html5-audio.tsx
import { jsx as jsx25 } from "react/jsx-runtime";
var AudioRefForwardingFunction = (props, ref) => {
  const audioTagsContext = useContext34(SharedAudioTagsContext);
  const propsWithFreeze = props;
  const {
    startFrom,
    endAt,
    trimBefore,
    trimAfter,
    name,
    _remotionInternalStack,
    pauseWhenBuffering,
    showInTimeline,
    onError: onRemotionError,
    freeze,
    ...otherProps
  } = propsWithFreeze;
  const { loop, freeze: _freeze, ...propsOtherThanLoop } = propsWithFreeze;
  const { fps } = useVideoConfig();
  const environment = useRemotionEnvironment();
  const shouldPauseWhenBuffering = resolveV5Default(pauseWhenBuffering);
  if (environment.isClientSideRendering) {
    throw new Error("<Html5Audio> is not supported in @remotion/web-renderer. Use <Audio> from @remotion/media instead. See https://remotion.dev/docs/client-side-rendering/limitations");
  }
  if (typeof freeze !== "undefined") {
    throw new TypeError('The "freeze" prop is not supported on <Html5Audio />. Use <Sequence freeze={...}> to freeze media playback.');
  }
  const { durations, setDurations } = useContext34(DurationsContext);
  if (typeof props.src !== "string") {
    throw new TypeError(`The \`<Html5Audio>\` tag requires a string for \`src\`, but got ${JSON.stringify(props.src)} instead.`);
  }
  const preloadedSrc = usePreload(props.src);
  const onError = useCallback16((e) => {
    console.log(e.currentTarget.error);
    const errMessage = `Could not play audio with src ${preloadedSrc}: ${e.currentTarget.error}. See https://remotion.dev/docs/media-playback-error for help.`;
    if (loop) {
      if (onRemotionError) {
        onRemotionError(new Error(errMessage));
        return;
      }
      cancelRender(new Error(errMessage));
    } else {
      onRemotionError?.(new Error(errMessage));
      console.warn(errMessage);
    }
  }, [loop, onRemotionError, preloadedSrc]);
  const onDuration = useCallback16((src, durationInSeconds) => {
    setDurations({ type: "got-duration", durationInSeconds, src });
  }, [setDurations]);
  const durationFetched = durations[getAbsoluteSrc(preloadedSrc)] ?? durations[getAbsoluteSrc(props.src)];
  validateMediaTrimProps({ startFrom, endAt, trimBefore, trimAfter });
  const { trimBeforeValue, trimAfterValue } = resolveTrimProps({
    startFrom,
    endAt,
    trimBefore,
    trimAfter
  });
  if (loop && durationFetched !== undefined) {
    if (!Number.isFinite(durationFetched)) {
      return /* @__PURE__ */ jsx25(Html5Audio, {
        ...propsOtherThanLoop,
        ref,
        _remotionInternalNativeLoopPassed: true
      });
    }
    const duration = durationFetched * fps;
    return /* @__PURE__ */ jsx25(Loop, {
      layout: "none",
      durationInFrames: calculateMediaDuration({
        trimAfter: trimAfterValue,
        mediaDurationInFrames: duration,
        playbackRate: props.playbackRate ?? 1,
        trimBefore: trimBeforeValue
      }),
      children: /* @__PURE__ */ jsx25(Html5Audio, {
        ...propsOtherThanLoop,
        ref,
        _remotionInternalNativeLoopPassed: true
      })
    });
  }
  if (typeof trimBeforeValue !== "undefined" || typeof trimAfterValue !== "undefined") {
    return /* @__PURE__ */ jsx25(Sequence, {
      layout: "none",
      from: 0 - (trimBeforeValue ?? 0),
      showInTimeline: false,
      durationInFrames: trimAfterValue,
      name,
      children: /* @__PURE__ */ jsx25(Html5Audio, {
        _remotionInternalNeedsDurationCalculation: Boolean(loop),
        pauseWhenBuffering: shouldPauseWhenBuffering,
        ...otherProps,
        ref
      })
    });
  }
  validateMediaProps({
    playbackRate: props.playbackRate,
    preservePitch: props.preservePitch,
    volume: props.volume
  }, "Html5Audio");
  if (environment.isRendering) {
    return /* @__PURE__ */ jsx25(AudioForRendering, {
      onDuration,
      ...props,
      ref,
      onNativeError: onError,
      _remotionInternalNeedsDurationCalculation: Boolean(loop)
    });
  }
  return /* @__PURE__ */ jsx25(AudioForPreview, {
    _remotionInternalNativeLoopPassed: props._remotionInternalNativeLoopPassed ?? false,
    _remotionInternalStack: _remotionInternalStack ?? null,
    shouldPreMountAudioTags: audioTagsContext !== null && audioTagsContext.numberOfAudioTags > 0,
    ...props,
    ref,
    onNativeError: onError,
    onDuration,
    pauseWhenBuffering: shouldPauseWhenBuffering,
    _remotionInternalNeedsDurationCalculation: Boolean(loop),
    showInTimeline: showInTimeline ?? true
  });
};
var Html5Audio = forwardRef7(AudioRefForwardingFunction);
addSequenceStackTraces(Html5Audio);
var Audio = Html5Audio;
// src/effects/Solid.tsx
import {
  forwardRef as forwardRef8,
  useCallback as useCallback17,
  useEffect as useEffect17,
  useImperativeHandle as useImperativeHandle6,
  useMemo as useMemo30,
  useRef as useRef22,
  useState as useState16
} from "react";
import { jsx as jsx26 } from "react/jsx-runtime";
var resolveSolidPixelDensity = (pixelDensity) => {
  if (pixelDensity === undefined) {
    return 1;
  }
  if (typeof pixelDensity !== "number" || !Number.isFinite(pixelDensity) || pixelDensity <= 0) {
    throw new Error(`<Solid>: \`pixelDensity\` must be a positive finite number. Received: ${String(pixelDensity)}.`);
  }
  return pixelDensity;
};
var solidSchema = {
  ...baseSchema,
  color: {
    type: "color",
    default: "transparent",
    description: "Color"
  },
  width: {
    type: "number",
    min: 1,
    step: 1,
    default: 1920,
    description: "Width",
    hiddenFromList: false
  },
  height: {
    type: "number",
    min: 1,
    step: 1,
    default: 1080,
    description: "Height",
    hiddenFromList: false
  },
  pixelDensity: {
    type: "number",
    min: 1,
    max: 3,
    step: 0.1,
    default: 1,
    description: "Pixel density",
    hiddenFromList: false
  },
  ...transformSchema,
  ...backgroundSchema,
  ...borderSchema,
  ...borderRadiusSchema,
  ...cropSchema
};
var SolidInner = ({
  color,
  width,
  height,
  effects = [],
  className,
  style,
  pixelDensity,
  overrideId,
  reference
}) => {
  const { delayRender: delayRender2, continueRender: continueRender2, cancelRender: cancelRender2 } = useDelayRender();
  const resolvedPixelDensity = resolveSolidPixelDensity(pixelDensity);
  const canvasWidth = Math.ceil(width * resolvedPixelDensity);
  const canvasHeight = Math.ceil(height * resolvedPixelDensity);
  const [outputCanvas, setOutputCanvas] = useState16(null);
  const memoizedEffects = useMemoizedEffects({
    effects,
    overrideId: overrideId ?? null
  });
  const sourceCanvas = useMemo30(() => {
    if (typeof document === "undefined") {
      return null;
    }
    const canvas = document.createElement("canvas");
    canvas.width = 1;
    canvas.height = 1;
    return canvas;
  }, []);
  const chainState = useEffectChainState();
  const canvasRef = useCallback17((canvas) => {
    setOutputCanvas(canvas);
    if (typeof reference === "function") {
      reference(canvas);
    } else if (reference) {
      reference.current = canvas;
    }
  }, [reference]);
  useEffect17(() => {
    if (!outputCanvas || !sourceCanvas) {
      return;
    }
    const handle = delayRender2("Solid effect chain");
    if (!chainState) {
      continueRender2(handle);
      return () => {
        continueRender2(handle);
      };
    }
    const ctx = sourceCanvas.getContext("2d", { colorSpace: "srgb" });
    if (!ctx) {
      cancelRender2(new Error("Failed to acquire 2D context for <Solid> source"));
      return;
    }
    ctx.clearRect(0, 0, 1, 1);
    if (color !== undefined) {
      ctx.fillStyle = color;
      ctx.fillRect(0, 0, 1, 1);
    }
    runEffectChain({
      state: chainState.get(canvasWidth, canvasHeight),
      source: sourceCanvas,
      effects: memoizedEffects,
      output: outputCanvas,
      width: canvasWidth,
      height: canvasHeight
    }).then((completed) => {
      if (completed) {
        continueRender2(handle);
      }
    }).catch((err) => {
      cancelRender2(err);
    });
    return () => {
      continueRender2(handle);
    };
  }, [
    color,
    outputCanvas,
    sourceCanvas,
    chainState,
    canvasWidth,
    canvasHeight,
    delayRender2,
    continueRender2,
    cancelRender2,
    memoizedEffects
  ]);
  const canvasStyle = useMemo30(() => {
    return {
      width,
      height,
      ...style ?? {}
    };
  }, [height, style, width]);
  return /* @__PURE__ */ jsx26("canvas", {
    ref: canvasRef,
    width: canvasWidth,
    height: canvasHeight,
    className,
    style: canvasStyle
  });
};
var SolidOuter = forwardRef8(({
  effects = [],
  controls,
  color,
  height,
  width,
  className,
  durationInFrames,
  style,
  name,
  from,
  trimBefore,
  freeze,
  hidden,
  showInTimeline,
  pixelDensity,
  cropLeft,
  cropRight,
  cropTop,
  cropBottom,
  ...props2
}, ref) => {
  const memoizedEffectDefinitions = useMemoizedEffectDefinitions(effects);
  const actualRef = useRef22(null);
  useImperativeHandle6(ref, () => {
    return actualRef.current;
  }, []);
  const croppedStyle = useCropStyle({
    cropLeft,
    cropRight,
    cropTop,
    cropBottom,
    style: style ?? null,
    componentName: "<Solid />"
  });
  return /* @__PURE__ */ jsx26(Sequence, {
    layout: "none",
    from,
    trimBefore,
    freeze,
    hidden,
    showInTimeline,
    controls,
    _remotionInternalEffects: memoizedEffectDefinitions,
    durationInFrames,
    name: name ?? "<Solid>",
    outlineRef: actualRef,
    _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/solid",
    ...props2,
    children: /* @__PURE__ */ jsx26(SolidInner, {
      reference: actualRef,
      overrideId: controls?.overrideId ?? null,
      color,
      height,
      width,
      className,
      style: croppedStyle ?? undefined,
      effects,
      pixelDensity
    })
  });
});
var Solid = withInteractivitySchema({
  Component: SolidOuter,
  componentName: "<Solid>",
  componentIdentity: "dev.remotion.remotion.Solid",
  schema: solidSchema,
  supportsEffects: true
});
Solid.displayName = "Solid";
addSequenceStackTraces(Solid);
// src/HtmlInCanvas.tsx
import {
  createContext as createContext25,
  forwardRef as forwardRef9,
  useCallback as useCallback18,
  useContext as useContext35,
  useLayoutEffect as useLayoutEffect12,
  useMemo as useMemo31,
  useRef as useRef23
} from "react";
import { jsx as jsx27 } from "react/jsx-runtime";
var transferredOffscreenCanvases = new WeakMap;
var getTransferredOffscreenCanvas = (canvas) => {
  const existing = transferredOffscreenCanvases.get(canvas);
  if (existing) {
    return existing;
  }
  const offscreen = canvas.transferControlToOffscreen();
  transferredOffscreenCanvases.set(canvas, offscreen);
  return offscreen;
};
var cachedSupport = null;
var isHtmlInCanvasSupported = () => {
  if (cachedSupport !== null) {
    return cachedSupport;
  }
  if (typeof document === "undefined") {
    return false;
  }
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  cachedSupport = typeof ctx?.drawElementImage === "function" && typeof canvas.requestPaint === "function" && typeof canvas.captureElementImage === "function" && "transferControlToOffscreen" in HTMLCanvasElement.prototype;
  return cachedSupport;
};
var HTML_IN_CANVAS_UNSUPPORTED_MESSAGE = "HTML in Canvas is not supported. Two common causes: Chrome is older than version 148 (update Chrome), or the HTML-in-Canvas flag is disabled at chrome://flags/#canvas-draw-element (enable it and restart Chrome).";
function assertHtmlInCanvasDimensions(width, height) {
  if (typeof width !== "number" || typeof height !== "number") {
    throw new Error(`HtmlInCanvas: \`width\` and \`height\` must be numbers. Received width=${String(width)}, height=${String(height)}.`);
  }
  if (!Number.isInteger(width) || width <= 0) {
    throw new Error(`HtmlInCanvas: \`width\` must be a positive integer. Received: ${String(width)}.`);
  }
  if (!Number.isInteger(height) || height <= 0) {
    throw new Error(`HtmlInCanvas: \`height\` must be a positive integer. Received: ${String(height)}.`);
  }
}
function resolveHtmlInCanvasPixelDensity(pixelDensity) {
  if (pixelDensity === undefined) {
    return 1;
  }
  if (typeof pixelDensity !== "number" || !Number.isFinite(pixelDensity) || pixelDensity <= 0) {
    throw new Error(`HtmlInCanvas: \`pixelDensity\` must be a positive finite number. Received: ${String(pixelDensity)}.`);
  }
  return pixelDensity;
}
var isMissingPaintRecordError = (error2) => {
  return error2 instanceof DOMException && error2.name === "InvalidStateError";
};
var missingPaintRecordMessage = "HtmlInCanvas: Expected the element to be inside the viewport during rendering, but Chrome had no cached paint record for it.";
var resizePaintTarget = ({
  target,
  width,
  height
}) => {
  if (target.width !== width) {
    target.width = width;
  }
  if (target.height !== height) {
    target.height = height;
  }
};
var defaultOnPaint = ({
  canvas,
  element,
  elementImage
}) => {
  const ctx = canvas.getContext("2d");
  if (!ctx) {
    throw new Error("Failed to acquire 2D context for <HtmlInCanvas> canvas");
  }
  ctx.reset();
  const transform = ctx.drawElementImage(elementImage, 0, 0);
  element.style.transform = transform.toString();
};
var HtmlInCanvasAncestorContext = createContext25(false);
var HtmlInCanvasContent = forwardRef9(({
  width,
  height,
  effects,
  children,
  onPaint,
  onInit,
  pixelDensity,
  controls,
  style
}, ref) => {
  const isInsideAncestorHtmlInCanvas = useContext35(HtmlInCanvasAncestorContext);
  assertHtmlInCanvasDimensions(width, height);
  if (isInsideAncestorHtmlInCanvas) {
    throw new Error("<HtmlInCanvas> components cannot be nested. Chrome does not reliably render nested HTML-in-canvas subtrees. Consider merging the effects into one <HtmlInCanvas> if you can.");
  }
  const resolvedPixelDensity = resolveHtmlInCanvasPixelDensity(pixelDensity);
  const canvasWidth = Math.ceil(width * resolvedPixelDensity);
  const canvasHeight = Math.ceil(height * resolvedPixelDensity);
  const { delayRender: delayRender2, continueRender: continueRender2, cancelRender: cancelRender2 } = useDelayRender();
  const { isClientSideRendering, isRendering } = useRemotionEnvironment();
  const canRetryMissingPaintRecord = !isRendering || isClientSideRendering;
  const usesDirectLayoutCanvas = onPaint === undefined && onInit === undefined;
  if (!isHtmlInCanvasSupported()) {
    cancelRender2(new Error(HTML_IN_CANVAS_UNSUPPORTED_MESSAGE));
  }
  const canvas2dRef = useRef23(null);
  const paintTargetRef = useRef23(null);
  const divRef = useRef23(null);
  const canvasSizeKey = `${width}x${height}@${resolvedPixelDensity}-${usesDirectLayoutCanvas ? "direct" : "offscreen"}`;
  const setLayoutCanvasRef = useCallback18((node) => {
    canvas2dRef.current = node;
    if (typeof ref === "function") {
      ref(node);
    } else if (ref) {
      ref.current = node;
    }
  }, [ref]);
  const chainState = useEffectChainState();
  const memoizedEffects = useMemoizedEffects({
    effects,
    overrideId: controls?.overrideId ?? null
  });
  const effectsRef = useRef23(memoizedEffects);
  effectsRef.current = memoizedEffects;
  const onPaintRef = useRef23(onPaint);
  onPaintRef.current = onPaint;
  const onInitRef = useRef23(onInit);
  onInitRef.current = onInit;
  const initializedRef = useRef23(false);
  const onInitCleanupRef = useRef23(null);
  const unmountedRef = useRef23(false);
  const onPaintCb = useCallback18(async () => {
    const element = divRef.current;
    if (!element) {
      throw new Error("Canvas or scene element not found");
    }
    const paintTarget = paintTargetRef.current;
    if (!paintTarget) {
      throw new Error("HtmlInCanvas: paint target is not ready because the canvas is remounting");
    }
    resizePaintTarget({
      target: paintTarget,
      width: canvasWidth,
      height: canvasHeight
    });
    try {
      const placeholderCanvas = canvas2dRef.current;
      if (!placeholderCanvas) {
        throw new Error("Canvas not found");
      }
      const handle = delayRender2("onPaint");
      if (!initializedRef.current) {
        const currentOnInit = onInitRef.current;
        if (!currentOnInit) {
          initializedRef.current = true;
        } else {
          let initImage;
          try {
            initImage = placeholderCanvas.captureElementImage(element);
          } catch (error2) {
            if (isMissingPaintRecordError(error2) && canRetryMissingPaintRecord) {
              continueRender2(handle);
              return;
            }
            if (isMissingPaintRecordError(error2)) {
              throw new Error(missingPaintRecordMessage);
            }
            throw error2;
          }
          initializedRef.current = true;
          try {
            if (paintTarget instanceof HTMLCanvasElement) {
              throw new Error("HtmlInCanvas: onInit requires an OffscreenCanvas paint target");
            }
            const cleanup = await currentOnInit({
              canvas: paintTarget,
              element,
              elementImage: initImage,
              pixelDensity: resolvedPixelDensity
            });
            if (typeof cleanup !== "function") {
              throw new Error("HtmlInCanvas: when `onInit` is provided, it must return a cleanup function, or a Promise that resolves to one.");
            }
            if (unmountedRef.current) {
              cleanup();
            } else {
              onInitCleanupRef.current = cleanup;
            }
          } finally {
            initImage.close();
          }
        }
      }
      let elImage;
      try {
        elImage = placeholderCanvas.captureElementImage(element);
      } catch (error2) {
        if (isMissingPaintRecordError(error2) && canRetryMissingPaintRecord) {
          continueRender2(handle);
          return;
        }
        if (isMissingPaintRecordError(error2)) {
          throw new Error(missingPaintRecordMessage);
        }
        throw error2;
      }
      try {
        const currentOnPaint = onPaintRef.current;
        if (currentOnPaint) {
          if (paintTarget instanceof HTMLCanvasElement) {
            throw new Error("HtmlInCanvas: onPaint requires an OffscreenCanvas paint target");
          }
          const paintResult = currentOnPaint({
            canvas: paintTarget,
            element,
            elementImage: elImage,
            pixelDensity: resolvedPixelDensity
          });
          if (paintResult) {
            await paintResult;
          }
        } else {
          defaultOnPaint({
            canvas: paintTarget,
            element,
            elementImage: elImage,
            pixelDensity: resolvedPixelDensity
          });
        }
        await runEffectChain({
          state: chainState.get(canvasWidth, canvasHeight),
          source: paintTarget,
          effects: effectsRef.current,
          output: paintTarget,
          width: canvasWidth,
          height: canvasHeight
        });
      } finally {
        elImage.close();
      }
      continueRender2(handle);
    } catch (error2) {
      cancelRender2(error2);
    }
  }, [
    canvasHeight,
    canvasWidth,
    chainState,
    continueRender2,
    cancelRender2,
    delayRender2,
    resolvedPixelDensity,
    canRetryMissingPaintRecord
  ]);
  useLayoutEffect12(() => {
    const placeholder = canvas2dRef.current;
    if (!placeholder) {
      throw new Error("Canvas not found");
    }
    placeholder.layoutSubtree = true;
    const paintTarget = usesDirectLayoutCanvas ? placeholder : getTransferredOffscreenCanvas(placeholder);
    paintTargetRef.current = paintTarget;
    resizePaintTarget({
      target: paintTarget,
      width: canvasWidth,
      height: canvasHeight
    });
    initializedRef.current = false;
    unmountedRef.current = false;
    placeholder.addEventListener("paint", onPaintCb);
    return () => {
      placeholder.removeEventListener("paint", onPaintCb);
      paintTargetRef.current = null;
      initializedRef.current = false;
      unmountedRef.current = true;
      onInitCleanupRef.current?.();
      onInitCleanupRef.current = null;
    };
  }, [
    onPaintCb,
    cancelRender2,
    canvasWidth,
    canvasHeight,
    usesDirectLayoutCanvas
  ]);
  const onPaintChangedRef = useRef23(false);
  useLayoutEffect12(() => {
    if (!onPaintChangedRef.current) {
      onPaintChangedRef.current = true;
      return;
    }
    const canvas = canvas2dRef.current;
    if (!canvas) {
      return;
    }
    canvas.requestPaint?.();
  }, [onPaint, memoizedEffects]);
  useLayoutEffect12(() => {
    const canvas = canvas2dRef.current;
    if (!canvas) {
      return;
    }
    const handle = delayRender2("waiting for first paint after canvas resize");
    canvas.addEventListener("paint", () => {
      continueRender2(handle);
    }, { once: true });
    return () => {
      continueRender2(handle);
    };
  }, [width, height, continueRender2, delayRender2, canvasSizeKey]);
  const innerStyle = useMemo31(() => {
    return {
      width,
      height
    };
  }, [width, height]);
  const canvasStyle = useMemo31(() => {
    return {
      width,
      height,
      ...style ?? {}
    };
  }, [height, style, width]);
  return /* @__PURE__ */ jsx27(HtmlInCanvasAncestorContext.Provider, {
    value: true,
    children: /* @__PURE__ */ jsx27("canvas", {
      ref: setLayoutCanvasRef,
      width: canvasWidth,
      height: canvasHeight,
      style: canvasStyle,
      children: /* @__PURE__ */ jsx27("div", {
        ref: divRef,
        style: innerStyle,
        children
      })
    }, canvasSizeKey)
  });
});
HtmlInCanvasContent.displayName = "HtmlInCanvasContent";
var HtmlInCanvasInner = forwardRef9(({
  width,
  height,
  effects = [],
  children,
  onPaint,
  onInit,
  pixelDensity,
  controls,
  style,
  cropLeft,
  cropRight,
  cropTop,
  cropBottom,
  durationInFrames,
  name,
  ...sequenceProps
}, ref) => {
  const memoizedEffectDefinitions = useMemoizedEffectDefinitions(effects);
  const actualRef = useRef23(null);
  const setCanvasRef = useCallback18((node) => {
    actualRef.current = node;
    if (typeof ref === "function") {
      ref(node);
    } else if (ref) {
      ref.current = node;
    }
  }, [ref]);
  const croppedStyle = useCropStyle({
    cropLeft,
    cropRight,
    cropTop,
    cropBottom,
    style: style ?? null,
    componentName: "<HtmlInCanvas />"
  });
  return /* @__PURE__ */ jsx27(Sequence, {
    durationInFrames,
    name: name ?? "<HtmlInCanvas>",
    _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/remotion/html-in-canvas",
    controls,
    _remotionInternalEffects: memoizedEffectDefinitions,
    outlineRef: actualRef,
    layout: "none",
    ...sequenceProps,
    children: /* @__PURE__ */ jsx27(HtmlInCanvasContent, {
      ref: setCanvasRef,
      width,
      height,
      effects,
      onPaint,
      onInit,
      pixelDensity,
      controls,
      style: croppedStyle ?? undefined,
      children
    })
  });
});
HtmlInCanvasInner.displayName = "HtmlInCanvas";
var htmlInCanvasSchema = {
  ...baseSchema,
  pixelDensity: {
    type: "number",
    min: 1,
    max: 3,
    step: 0.1,
    default: 1,
    description: "Pixel density",
    hiddenFromList: false
  },
  ...transformSchema,
  ...backgroundSchema,
  ...borderSchema,
  ...borderRadiusSchema,
  ...cropSchema
};
var HtmlInCanvasWrapped = withInteractivitySchema({
  Component: HtmlInCanvasInner,
  componentName: "<HtmlInCanvas>",
  componentIdentity: "dev.remotion.remotion.HtmlInCanvas",
  schema: htmlInCanvasSchema,
  supportsEffects: true
});
var HtmlInCanvas = Object.assign(HtmlInCanvasWrapped, {
  isSupported: isHtmlInCanvasSupported
});
HtmlInCanvas.displayName = "HtmlInCanvas";
addSequenceStackTraces(HtmlInCanvas);
// src/canvas-image/CanvasImage.tsx
import {
  forwardRef as forwardRef10,
  useCallback as useCallback19,
  useContext as useContext36,
  useImperativeHandle as useImperativeHandle7,
  useLayoutEffect as useLayoutEffect13,
  useMemo as useMemo32,
  useRef as useRef24,
  useState as useState17
} from "react";

// src/truncate-src-for-label.ts
function truncateSrcForLabel(src) {
  if (typeof src !== "string") {
    return String(src);
  }
  if (src.length > 100 && (src.startsWith("data:") || src.startsWith("blob:"))) {
    return src.slice(0, 60) + "...[" + src.length + " chars total]";
  }
  return src;
}

// src/canvas-image/CanvasImage.tsx
import { jsx as jsx28 } from "react/jsx-runtime";
var canvasImageSchema = {
  src: {
    type: "asset",
    assetType: "image",
    default: undefined,
    description: "Source",
    keyframable: false
  },
  ...baseSchema,
  ...cropSchema,
  ...premountSchema,
  fit: {
    type: "enum",
    default: "fill",
    description: "Fit",
    variants: {
      fill: {},
      contain: {},
      cover: {}
    }
  },
  ...transformSchema,
  ...backgroundSchema,
  ...borderSchema,
  ...borderRadiusSchema
};
var makeAbortError = () => {
  if (typeof DOMException !== "undefined") {
    return new DOMException("Image loading was aborted", "AbortError");
  }
  const error2 = new Error("Image loading was aborted");
  error2.name = "AbortError";
  return error2;
};
var loadImage = ({
  src,
  signal
}) => {
  return new Promise((resolve, reject) => {
    const image = new Image;
    let settled = false;
    function cleanup() {
      image.onload = null;
      image.onerror = null;
    }
    function settle(callback) {
      if (settled) {
        return;
      }
      settled = true;
      cleanup();
      callback();
    }
    function onAbort() {
      settle(() => reject(makeAbortError()));
    }
    image.onload = () => {
      Promise.resolve(image.decode?.()).catch(() => {
        return;
      }).then(() => {
        const imageWidth = image.naturalWidth || image.width;
        const imageHeight = image.naturalHeight || image.height;
        if (imageWidth <= 0 || imageHeight <= 0) {
          settle(() => reject(new Error(`Could not determine dimensions for <CanvasImage> with src="${truncateSrcForLabel(src)}"`)));
          return;
        }
        settle(() => resolve({ element: image, width: imageWidth, height: imageHeight }));
      });
    };
    image.onerror = () => {
      settle(() => reject(new Error(`Could not load <CanvasImage> with src="${truncateSrcForLabel(src)}"`)));
    };
    signal.addEventListener("abort", onAbort, { once: true });
    if (signal.aborted) {
      onAbort();
      return;
    }
    image.crossOrigin = "anonymous";
    image.src = src;
  });
};
function exponentialBackoff(errorCount) {
  return 1000 * 2 ** (errorCount - 1);
}
var waitForNextFrame = ({
  onFrame
}) => {
  if (typeof requestAnimationFrame === "undefined") {
    onFrame();
    return () => {
      return;
    };
  }
  const frame = requestAnimationFrame(onFrame);
  return () => cancelAnimationFrame(frame);
};
var CanvasImageContent = forwardRef10(({
  src,
  width,
  height,
  fit = "fill",
  effects,
  controls,
  onError,
  className,
  style,
  id,
  pauseWhenLoading,
  maxRetries = 2,
  delayRenderRetries,
  delayRenderTimeoutInMilliseconds,
  refForOutline,
  ...canvasProps
}, ref) => {
  const { delayRender: delayRender2, continueRender: continueRender2, cancelRender: cancelRender2 } = useDelayRender();
  const { delayPlayback } = useBufferState();
  const [outputCanvas, setOutputCanvas] = useState17(null);
  const [loadedImage, setLoadedImage] = useState17(null);
  const actualSrc = usePreload(src);
  const chainState = useEffectChainState();
  const memoizedEffects = useMemoizedEffects({
    effects,
    overrideId: controls?.overrideId ?? null
  });
  const sequenceContext = useContext36(SequenceContext);
  const pendingLoadDelayRef = useRef24(null);
  const [isLoadPending, setIsLoadPending] = useState17(false);
  const isPremounting = Boolean(sequenceContext?.premounting);
  const isPostmounting = Boolean(sequenceContext?.postmounting);
  const continuePendingLoadDelay = useCallback19(({ markAsReady }) => {
    const pending = pendingLoadDelayRef.current;
    if (!pending || pending.continued) {
      return;
    }
    pending.continued = true;
    if (markAsReady) {
      setIsLoadPending(false);
    }
    continueRender2(pending.handle);
    pendingLoadDelayRef.current = null;
  }, [continueRender2]);
  const sourceCanvas = useMemo32(() => {
    if (typeof document === "undefined") {
      return null;
    }
    return document.createElement("canvas");
  }, []);
  const canvasRef = useCallback19((canvas) => {
    setOutputCanvas(canvas);
    if (refForOutline) {
      refForOutline.current = canvas;
    }
    if (typeof ref === "function") {
      ref(canvas);
    } else if (ref) {
      ref.current = canvas;
    }
  }, [ref, refForOutline]);
  useLayoutEffect13(() => {
    if (!pauseWhenLoading || !isLoadPending || isPremounting || isPostmounting) {
      return;
    }
    return delayPlayback().unblock;
  }, [
    delayPlayback,
    isLoadPending,
    isPostmounting,
    isPremounting,
    pauseWhenLoading
  ]);
  useLayoutEffect13(() => {
    const handle = delayRender2(`Rendering <CanvasImage> with src="${truncateSrcForLabel(actualSrc)}"`, {
      retries: delayRenderRetries ?? undefined,
      timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
    });
    const controller = new AbortController;
    let cancelled = false;
    let errorCount = 0;
    let timeoutId = null;
    setLoadedImage(null);
    setIsLoadPending(true);
    pendingLoadDelayRef.current = {
      handle,
      continued: false
    };
    const attemptLoad = () => {
      loadImage({ src: actualSrc, signal: controller.signal }).then((image) => {
        if (cancelled) {
          return;
        }
        setLoadedImage(image);
      }).catch((err) => {
        if (err.name === "AbortError") {
          continuePendingLoadDelay({ markAsReady: false });
          return;
        }
        errorCount++;
        if (errorCount <= maxRetries) {
          const backoff = exponentialBackoff(errorCount);
          console.warn(`Could not load <CanvasImage> with src="${truncateSrcForLabel(actualSrc)}", retrying in ${backoff}ms`);
          timeoutId = setTimeout(() => {
            if (!cancelled) {
              attemptLoad();
            }
          }, backoff);
        } else if (onError) {
          onError(err);
          continuePendingLoadDelay({ markAsReady: true });
        } else {
          cancelRender2(err);
        }
      });
    };
    attemptLoad();
    return () => {
      cancelled = true;
      if (timeoutId !== null) {
        clearTimeout(timeoutId);
      }
      controller.abort();
      continuePendingLoadDelay({ markAsReady: false });
    };
  }, [
    actualSrc,
    cancelRender2,
    continuePendingLoadDelay,
    delayRender2,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    maxRetries,
    onError
  ]);
  useLayoutEffect13(() => {
    if (!loadedImage || !outputCanvas || !sourceCanvas) {
      return;
    }
    const handle = delayRender2(`Applying effects to <CanvasImage> with src="${truncateSrcForLabel(actualSrc)}"`);
    let cancelled = false;
    let continued = false;
    let cancelWaitForNextFrame = () => {
      return;
    };
    const continueRenderOnce = () => {
      if (continued) {
        return;
      }
      continued = true;
      continueRender2(handle);
    };
    const canvasWidth = width ?? loadedImage.width;
    const canvasHeight = height ?? loadedImage.height;
    const sourceContext = sourceCanvas.getContext("2d", {
      colorSpace: "srgb"
    });
    if (!sourceContext) {
      cancelRender2(new Error("Could not get 2D context for <CanvasImage> source canvas"));
      continueRenderOnce();
      return () => {
        continueRenderOnce();
      };
    }
    sourceCanvas.width = canvasWidth;
    sourceCanvas.height = canvasHeight;
    outputCanvas.width = canvasWidth;
    outputCanvas.height = canvasHeight;
    sourceContext.clearRect(0, 0, canvasWidth, canvasHeight);
    sourceContext.drawImage(loadedImage.element, ...calculateImageFit(fit, { width: loadedImage.width, height: loadedImage.height }, { width: canvasWidth, height: canvasHeight }));
    runEffectChain({
      state: chainState.get(canvasWidth, canvasHeight),
      source: sourceCanvas,
      effects: memoizedEffects,
      output: outputCanvas,
      width: canvasWidth,
      height: canvasHeight
    }).then((completed) => {
      if (completed && !cancelled) {
        cancelWaitForNextFrame = waitForNextFrame({
          onFrame: () => {
            if (cancelled) {
              return;
            }
            continueRenderOnce();
            continuePendingLoadDelay({ markAsReady: true });
          }
        });
      }
    }).catch((err) => {
      if (cancelled) {
        return;
      }
      if (onError) {
        onError(err);
        continueRenderOnce();
        continuePendingLoadDelay({ markAsReady: true });
      } else {
        cancelRender2(err);
      }
    });
    return () => {
      cancelled = true;
      cancelWaitForNextFrame();
      continueRenderOnce();
    };
  }, [
    actualSrc,
    cancelRender2,
    chainState,
    continueRender2,
    continuePendingLoadDelay,
    delayRender2,
    fit,
    height,
    loadedImage,
    memoizedEffects,
    onError,
    outputCanvas,
    sourceCanvas,
    width
  ]);
  return /* @__PURE__ */ jsx28("canvas", {
    ...canvasProps,
    ref: canvasRef,
    width,
    height,
    className,
    style,
    id
  });
});
CanvasImageContent.displayName = "CanvasImageContent";
var CanvasImageInner = forwardRef10(({
  src,
  width,
  height,
  fit,
  effects = [],
  className,
  style,
  id,
  onError,
  pauseWhenLoading,
  maxRetries,
  delayRenderRetries,
  delayRenderTimeoutInMilliseconds,
  durationInFrames,
  from,
  trimBefore,
  freeze,
  premountFor,
  postmountFor,
  styleWhilePremounted,
  styleWhilePostmounted,
  hidden,
  name,
  showInTimeline,
  cropLeft,
  cropRight,
  cropTop,
  cropBottom,
  controls,
  _remotionInternalDocumentationLink,
  _remotionInternalCropComponentName,
  outlineRef,
  ...canvasProps
}, ref) => {
  if (!src) {
    throw new Error('No "src" prop was passed to <CanvasImage>.');
  }
  const memoizedEffectDefinitions = useMemoizedEffectDefinitions(effects);
  const actualRef = useRef24(null);
  useImperativeHandle7(ref, () => {
    return actualRef.current;
  }, []);
  const {
    effectivePostmountFor,
    effectivePremountFor,
    freezeFrame,
    isPremountingOrPostmounting,
    postmountingActive,
    premountingActive,
    premountingStyle
  } = usePremounting({
    from: from ?? 0,
    durationInFrames: durationInFrames ?? Infinity,
    premountFor: premountFor ?? null,
    postmountFor: postmountFor ?? null,
    style: style ?? null,
    styleWhilePremounted: styleWhilePremounted ?? null,
    styleWhilePostmounted: styleWhilePostmounted ?? null,
    hideWhilePremounted: "display-none"
  });
  const croppedStyle = useCropStyle({
    cropLeft,
    cropRight,
    cropTop,
    cropBottom,
    style: premountingStyle,
    componentName: _remotionInternalCropComponentName ?? "<CanvasImage />"
  });
  return /* @__PURE__ */ jsx28(Freeze, {
    frame: freezeFrame,
    active: isPremountingOrPostmounting,
    children: /* @__PURE__ */ jsx28(Sequence, {
      layout: "none",
      from: from ?? 0,
      trimBefore,
      durationInFrames: durationInFrames ?? Infinity,
      freeze,
      hidden,
      showInTimeline: showInTimeline ?? true,
      name: name ?? "<CanvasImage>",
      _remotionInternalDocumentationLink: _remotionInternalDocumentationLink ?? "https://www.remotion.dev/docs/canvasimage",
      controls,
      _remotionInternalEffects: memoizedEffectDefinitions,
      _remotionInternalIsMedia: { type: "image", src },
      _remotionInternalPremountDisplay: effectivePremountFor || null,
      _remotionInternalPostmountDisplay: effectivePostmountFor || null,
      _remotionInternalIsPremounting: premountingActive,
      _remotionInternalIsPostmounting: postmountingActive,
      outlineRef: outlineRef ?? actualRef,
      children: /* @__PURE__ */ jsx28(CanvasImageContent, {
        ref: actualRef,
        src,
        width,
        height,
        fit,
        effects,
        controls,
        className,
        style: croppedStyle ?? undefined,
        id,
        onError,
        pauseWhenLoading,
        maxRetries,
        delayRenderRetries,
        delayRenderTimeoutInMilliseconds,
        refForOutline: outlineRef ?? null,
        ...canvasProps
      })
    })
  });
});
var CanvasImage = withInteractivitySchema({
  Component: CanvasImageInner,
  componentName: "<CanvasImage>",
  componentIdentity: "dev.remotion.remotion.CanvasImage",
  schema: canvasImageSchema,
  supportsEffects: true
});
CanvasImage.displayName = "CanvasImage";
addSequenceStackTraces(CanvasImage);
// src/get-static-files.ts
var warnedServer = false;
var warnedPlayer = false;
var warnServerOnce = () => {
  if (warnedServer) {
    return;
  }
  warnedServer = true;
  console.warn("Called getStaticFiles() on the server. The API is only available in the browser. An empty array was returned.");
};
var warnPlayerOnce = () => {
  if (warnedPlayer) {
    return;
  }
  warnedPlayer = true;
  console.warn("Called getStaticFiles() while using the Remotion Player. The API is only available while using the Remotion Studio. An empty array was returned.");
};
var getStaticFiles = () => {
  if (ENABLE_V5_BREAKING_CHANGES) {
    throw new Error("getStaticFiles() has moved into the `@remotion/studio` package. Update your imports.");
  }
  if (typeof document === "undefined") {
    warnServerOnce();
    return [];
  }
  if (window.remotion_isPlayer) {
    warnPlayerOnce();
    return [];
  }
  return window.remotion_staticFiles;
};
// src/IFrame.tsx
import { forwardRef as forwardRef11, useCallback as useCallback20, useState as useState18 } from "react";
import { jsx as jsx29 } from "react/jsx-runtime";
var IFrameRefForwarding = ({
  onLoad,
  onError,
  delayRenderRetries,
  delayRenderTimeoutInMilliseconds,
  ...props2
}, ref) => {
  const { delayRender: delayRender2, continueRender: continueRender2 } = useDelayRender();
  const [handle] = useState18(() => delayRender2(`Loading <IFrame> with source ${props2.src}`, {
    retries: delayRenderRetries ?? undefined,
    timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
  }));
  const didLoad = useCallback20((e) => {
    continueRender2(handle);
    onLoad?.(e);
  }, [handle, onLoad, continueRender2]);
  const didGetError = useCallback20((e) => {
    continueRender2(handle);
    if (onError) {
      onError(e);
    } else {
      console.error("Error loading iframe:", e, "Handle the event using the onError() prop to make this message disappear.");
    }
  }, [handle, onError, continueRender2]);
  return /* @__PURE__ */ jsx29("iframe", {
    referrerPolicy: "strict-origin-when-cross-origin",
    ...props2,
    ref,
    onError: didGetError,
    onLoad: didLoad
  });
};
var IFrame = forwardRef11(IFrameRefForwarding);
// src/Img.tsx
import {
  useCallback as useCallback21,
  useContext as useContext37,
  useLayoutEffect as useLayoutEffect14,
  useRef as useRef25,
  useState as useState19
} from "react";
import { jsx as jsx30 } from "react/jsx-runtime";
function exponentialBackoff2(errorCount) {
  return 1000 * 2 ** (errorCount - 1);
}
var ImgContent = ({
  onError,
  maxRetries = 2,
  src,
  pauseWhenLoading,
  delayRenderRetries,
  delayRenderTimeoutInMilliseconds,
  onImageFrame,
  crossOrigin,
  decoding,
  ref,
  refForOutline,
  ...props2
}) => {
  const imageRef = useRef25(null);
  const errors = useRef25({});
  const { delayPlayback } = useBufferState();
  const sequenceContext = useContext37(SequenceContext);
  const [isLoading, setIsLoading] = useState19(false);
  const _propsValid = true;
  if (!_propsValid) {
    throw new Error("typecheck error");
  }
  const imageCallbackRef = useCallback21((img) => {
    imageRef.current = img;
    refForOutline.current = img;
    if (typeof ref === "function") {
      ref(img);
    } else if (ref) {
      ref.current = img;
    }
  }, [ref, refForOutline]);
  const actualSrc = usePreload(src);
  const retryIn = useCallback21((timeout) => {
    if (!imageRef.current) {
      return;
    }
    const currentSrc = imageRef.current.src;
    setTimeout(() => {
      if (!imageRef.current) {
        return;
      }
      const newSrc = imageRef.current?.src;
      if (newSrc !== currentSrc) {
        return;
      }
      imageRef.current.removeAttribute("src");
      imageRef.current.setAttribute("src", newSrc);
    }, timeout);
  }, []);
  const { delayRender: delayRender2, continueRender: continueRender2, cancelRender: cancelRender2 } = useDelayRender();
  const isPremounting = Boolean(sequenceContext?.premounting);
  const isPostmounting = Boolean(sequenceContext?.postmounting);
  const didGetError = useCallback21((e) => {
    if (!errors.current) {
      return;
    }
    errors.current[imageRef.current?.src] = (errors.current[imageRef.current?.src] ?? 0) + 1;
    if (onError && (errors.current[imageRef.current?.src] ?? 0) > maxRetries) {
      onError(e);
      return;
    }
    if ((errors.current[imageRef.current?.src] ?? 0) <= maxRetries) {
      const backoff = exponentialBackoff2(errors.current[imageRef.current?.src] ?? 0);
      console.warn(`Could not load image with source ${truncateSrcForLabel(imageRef.current?.src)}, retrying again in ${backoff}ms`);
      retryIn(backoff);
      return;
    }
    try {
      cancelRender2("Error loading image with src: " + truncateSrcForLabel(imageRef.current?.src));
    } catch {}
  }, [cancelRender2, maxRetries, onError, retryIn]);
  if (typeof window !== "undefined") {
    useLayoutEffect14(() => {
      if (!pauseWhenLoading || !isLoading || isPremounting || isPostmounting) {
        return;
      }
      return delayPlayback().unblock;
    }, [
      delayPlayback,
      isLoading,
      isPostmounting,
      isPremounting,
      pauseWhenLoading
    ]);
    useLayoutEffect14(() => {
      if (window.process?.env?.NODE_ENV === "test") {
        if (imageRef.current) {
          imageRef.current.src = actualSrc;
        }
        return;
      }
      const { current } = imageRef;
      if (!current) {
        return;
      }
      setIsLoading(true);
      const newHandle = delayRender2("Loading <Img> with src=" + truncateSrcForLabel(actualSrc), {
        retries: delayRenderRetries ?? undefined,
        timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
      });
      let unmounted = false;
      const onComplete = () => {
        if (unmounted) {
          continueRender2(newHandle);
          return;
        }
        if ((errors.current[imageRef.current?.src] ?? 0) > 0) {
          delete errors.current[imageRef.current?.src];
          console.info(`Retry successful - ${truncateSrcForLabel(imageRef.current?.src)} is now loaded`);
        }
        if (current) {
          onImageFrame?.(current);
        }
        setIsLoading(false);
        continueRender2(newHandle);
      };
      if (!imageRef.current) {
        onComplete();
        return;
      }
      current.src = actualSrc;
      current.decode().then(onComplete).catch((err) => {
        console.warn(err);
        if (current.complete && current.naturalWidth > 0 && current.naturalHeight > 0) {
          onComplete();
        } else {
          current.addEventListener("load", onComplete);
        }
      });
      return () => {
        unmounted = true;
        current.removeEventListener("load", onComplete);
        continueRender2(newHandle);
      };
    }, [
      actualSrc,
      delayRenderRetries,
      delayRenderTimeoutInMilliseconds,
      onImageFrame,
      continueRender2,
      delayRender2
    ]);
  }
  const { isClientSideRendering, isRendering } = useRemotionEnvironment();
  const crossOriginValue = getCrossOriginValue({
    crossOrigin,
    requestsVideoFrame: false,
    isClientSideRendering
  });
  return /* @__PURE__ */ jsx30("img", {
    ...props2,
    ref: imageCallbackRef,
    crossOrigin: crossOriginValue,
    onError: didGetError,
    decoding: isRendering ? "sync" : decoding
  });
};
var NativeImgInner = ({
  hidden,
  name,
  showInTimeline,
  src,
  from,
  trimBefore,
  durationInFrames,
  freeze,
  premountFor,
  postmountFor,
  style,
  styleWhilePremounted,
  styleWhilePostmounted,
  cropLeft,
  cropRight,
  cropTop,
  cropBottom,
  controls,
  outlineRef: refForOutline,
  ...props2
}) => {
  if (!src) {
    throw new Error('No "src" prop was passed to <Img>.');
  }
  const {
    effectivePostmountFor,
    effectivePremountFor,
    freezeFrame,
    isPremountingOrPostmounting,
    postmountingActive,
    premountingActive,
    premountingStyle
  } = usePremounting({
    from: from ?? 0,
    durationInFrames: durationInFrames ?? Infinity,
    premountFor: premountFor ?? null,
    postmountFor: postmountFor ?? null,
    style: style ?? null,
    styleWhilePremounted: styleWhilePremounted ?? null,
    styleWhilePostmounted: styleWhilePostmounted ?? null,
    hideWhilePremounted: "display-none"
  });
  const croppedStyle = useCropStyle({
    cropLeft,
    cropRight,
    cropTop,
    cropBottom,
    style: premountingStyle,
    componentName: "<Img />"
  });
  return /* @__PURE__ */ jsx30(Freeze, {
    frame: freezeFrame,
    active: isPremountingOrPostmounting,
    children: /* @__PURE__ */ jsx30(Sequence, {
      layout: "none",
      from: from ?? 0,
      trimBefore,
      durationInFrames: durationInFrames ?? Infinity,
      freeze,
      _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img",
      _remotionInternalIsMedia: { type: "image", src },
      _remotionInternalPremountDisplay: effectivePremountFor || null,
      _remotionInternalPostmountDisplay: effectivePostmountFor || null,
      _remotionInternalIsPremounting: premountingActive,
      _remotionInternalIsPostmounting: postmountingActive,
      name: name ?? "<Img>",
      controls,
      showInTimeline: showInTimeline ?? true,
      hidden,
      outlineRef: refForOutline,
      children: /* @__PURE__ */ jsx30(ImgContent, {
        src,
        refForOutline,
        style: croppedStyle ?? undefined,
        ...props2
      })
    })
  });
};
var CanvasImageWithPrivateProps = CanvasImage;
var imgSchema = {
  src: {
    type: "asset",
    assetType: "image",
    default: undefined,
    description: "Source",
    keyframable: false
  },
  ...baseSchema,
  ...cropSchema,
  ...premountSchema,
  ...transformSchema,
  ...backgroundSchema,
  ...borderSchema,
  ...borderRadiusSchema
};
var imgCanvasFallbackIncompatibleProps = new Set([
  "alt",
  "crossOrigin",
  "decoding",
  "fetchPriority",
  "loading",
  "onError",
  "onImageFrame",
  "onLoad",
  "sizes",
  "srcSet",
  "useMap"
]);
var getIncompatiblePropNames = (props2) => Object.keys(props2).filter((key) => props2[key] !== undefined && imgCanvasFallbackIncompatibleProps.has(key));
var formatPropList = (props2) => {
  return props2.map((prop) => `"${prop}"`).join(", ");
};
var validateCanvasImageFallbackProps = ({
  props: props2,
  ref,
  width,
  height
}) => {
  if (typeof width === "string" || typeof height === "string") {
    throw new Error('The "width" and "height" props must be numbers on <Img> when effects are passed, because <Img> renders a <CanvasImage>. Use numeric props or CSS dimensions in "style".');
  }
  const conflictingProps = getIncompatiblePropNames(props2);
  if (ref !== null && ref !== undefined) {
    conflictingProps.unshift("ref");
  }
  if (conflictingProps.length === 0) {
    return;
  }
  throw new Error(`The ${formatPropList(conflictingProps)} prop${conflictingProps.length === 1 ? "" : "s"} cannot be used on <Img> when effects are passed, because <Img> renders a <canvas> instead of a native <img>. Remove ${conflictingProps.length === 1 ? "this prop" : "these props"}.`);
};
var getFitFromObjectFit = (style) => {
  const objectFit = style?.objectFit;
  if (objectFit === "fill" || objectFit === "contain" || objectFit === "cover") {
    return objectFit;
  }
  return;
};
var ImgInner = ({
  effects = [],
  ref,
  hidden,
  name,
  showInTimeline,
  src,
  from,
  trimBefore,
  durationInFrames,
  freeze,
  premountFor,
  postmountFor,
  styleWhilePremounted,
  styleWhilePostmounted,
  controls,
  width,
  height,
  className,
  style,
  cropLeft,
  cropRight,
  cropTop,
  cropBottom,
  id,
  pauseWhenLoading,
  maxRetries,
  delayRenderRetries,
  delayRenderTimeoutInMilliseconds,
  ...props2
}) => {
  const refForOutline = useRef25(null);
  const shouldPauseWhenLoading = resolveV5Default(pauseWhenLoading);
  if (effects.length === 0) {
    return /* @__PURE__ */ jsx30(NativeImgInner, {
      ...props2,
      ref,
      hidden,
      name,
      showInTimeline,
      src,
      from,
      trimBefore,
      durationInFrames,
      freeze,
      premountFor,
      postmountFor,
      styleWhilePremounted,
      styleWhilePostmounted,
      controls,
      width,
      height,
      className,
      style,
      cropLeft,
      cropRight,
      cropTop,
      cropBottom,
      id,
      pauseWhenLoading: shouldPauseWhenLoading,
      maxRetries,
      delayRenderRetries,
      delayRenderTimeoutInMilliseconds,
      outlineRef: refForOutline
    });
  }
  if (!src) {
    throw new Error('No "src" prop was passed to <Img>.');
  }
  validateCanvasImageFallbackProps({
    props: props2,
    ref,
    width,
    height
  });
  const canvasWidth = typeof width === "number" ? width : undefined;
  const canvasHeight = typeof height === "number" ? height : undefined;
  const canvasProps = props2;
  const canvasFit = getFitFromObjectFit(style) ?? "fill";
  return /* @__PURE__ */ jsx30(CanvasImageWithPrivateProps, {
    src,
    width: canvasWidth,
    height: canvasHeight,
    fit: canvasFit,
    effects,
    className,
    style,
    cropLeft,
    cropRight,
    cropTop,
    cropBottom,
    id,
    pauseWhenLoading: shouldPauseWhenLoading,
    maxRetries,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    from,
    trimBefore,
    durationInFrames,
    freeze,
    premountFor,
    postmountFor,
    styleWhilePremounted,
    styleWhilePostmounted,
    hidden,
    name: name ?? "<Img>",
    showInTimeline,
    _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/img",
    _remotionInternalCropComponentName: "<Img />",
    controls,
    outlineRef: refForOutline,
    ...canvasProps
  });
};
var Img = withInteractivitySchema({
  Component: ImgInner,
  componentName: "<Img>",
  componentIdentity: "dev.remotion.remotion.Img",
  schema: imgSchema,
  supportsEffects: true
});
addSequenceStackTraces(Img);
// src/Interactive.tsx
import React33, { forwardRef as forwardRef12, useCallback as useCallback22, useRef as useRef26 } from "react";
import { jsx as jsx31 } from "react/jsx-runtime";
var sourcePathToIdentityPrefix = (packageName) => {
  if (packageName === "remotion") {
    return "dev.remotion.remotion";
  }
  if (packageName.startsWith("@remotion/")) {
    const normalizedPackageName = packageName.slice("@remotion/".length).replace(/-([a-z])/g, (_, char) => char.toUpperCase());
    return `dev.remotion.${normalizedPackageName}`;
  }
  throw new Error(`Unsupported Remotion package name: ${packageName}`);
};
var makeRemotionComponentIdentity = ({
  packageName,
  componentName
}) => {
  return `${sourcePathToIdentityPrefix(packageName)}.${componentName}`;
};
var interactiveElementSchema = {
  ...baseSchema,
  ...transformSchema,
  ...cropSchema
};
var interactiveBackgroundElementSchema = {
  ...interactiveElementSchema,
  ...backgroundSchema
};
var interactiveBorderElementSchema = {
  ...interactiveBackgroundElementSchema,
  ...borderSchema,
  ...borderRadiusSchema
};
var interactiveTextElementSchema = {
  ...interactiveBorderElementSchema,
  ...textSchema,
  ...textContentSchema
};
var interactiveSvgTextElementSchema = {
  ...interactiveElementSchema,
  ...svgPaintSchema,
  ...textSchema,
  ...textContentSchema
};
var interactiveSvgElementSchema = {
  ...interactiveElementSchema,
  ...svgPaintSchema
};
var interactiveSvgStrokeElementSchema = {
  ...interactiveElementSchema,
  ...svgStrokeSchema
};
var interactiveSvgRootElementSchema = {
  ...interactiveBorderElementSchema,
  ...svgPaintSchema
};
var setRef2 = (ref, value) => {
  if (typeof ref === "function") {
    ref(value);
  } else if (ref) {
    ref.current = value;
  }
};
var withSchema = (options) => {
  const Wrapped = withInteractivitySchema(options);
  addSequenceStackTraces(Wrapped);
  return Wrapped;
};
var makeInteractiveElement = (tag, displayName, schema) => {
  const Inner = forwardRef12((propsWithControls, ref) => {
    const {
      durationInFrames,
      from,
      trimBefore,
      freeze,
      hidden,
      name,
      showInTimeline,
      controls,
      cropLeft,
      cropRight,
      cropTop,
      cropBottom,
      style,
      ...props2
    } = propsWithControls;
    const croppedStyle = useCropStyle({
      cropLeft,
      cropRight,
      cropTop,
      cropBottom,
      style: style ?? null,
      componentName: displayName
    });
    const refForOutline = useRef26(null);
    const callbackRef = useCallback22((element) => {
      refForOutline.current = element;
      setRef2(ref, element);
    }, [ref]);
    return /* @__PURE__ */ jsx31(Sequence, {
      layout: "none",
      from: from ?? 0,
      trimBefore,
      durationInFrames: durationInFrames ?? Infinity,
      freeze,
      hidden,
      name: name ?? displayName,
      showInTimeline: showInTimeline ?? true,
      controls,
      _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/interactive",
      outlineRef: refForOutline,
      children: React33.createElement(tag, {
        ...props2,
        style: croppedStyle ?? undefined,
        ref: callbackRef
      })
    });
  });
  Inner.displayName = displayName;
  const Wrapped = withSchema({
    Component: Inner,
    componentName: displayName,
    componentIdentity: makeRemotionComponentIdentity({
      packageName: "remotion",
      componentName: displayName.slice(1, -1)
    }),
    schema,
    supportsEffects: false
  });
  Wrapped.displayName = displayName;
  return Wrapped;
};
var makeInteractiveTextElement = (tag, displayName) => {
  return makeInteractiveElement(tag, displayName, interactiveTextElementSchema);
};
var makeInteractiveSvgElement = (tag, displayName) => {
  return makeInteractiveElement(tag, displayName, interactiveSvgElementSchema);
};
var makeInteractiveSvgStrokeElement = (tag, displayName) => {
  return makeInteractiveElement(tag, displayName, interactiveSvgStrokeElementSchema);
};
var Interactive = {
  baseSchema,
  captionsSchema,
  transformSchema,
  textSchema,
  backgroundSchema,
  borderSchema,
  borderRadiusSchema,
  cropSchema,
  svgPaintSchema,
  svgStrokeSchema,
  premountSchema,
  sequenceSchema,
  withSchema,
  _internalMakeRemotionComponentIdentity: makeRemotionComponentIdentity,
  A: makeInteractiveTextElement("a", "<Interactive.A>"),
  Article: makeInteractiveTextElement("article", "<Interactive.Article>"),
  Aside: makeInteractiveTextElement("aside", "<Interactive.Aside>"),
  Button: makeInteractiveTextElement("button", "<Interactive.Button>"),
  Circle: makeInteractiveSvgElement("circle", "<Interactive.Circle>"),
  Code: makeInteractiveTextElement("code", "<Interactive.Code>"),
  Div: makeInteractiveTextElement("div", "<Interactive.Div>"),
  Ellipse: makeInteractiveSvgElement("ellipse", "<Interactive.Ellipse>"),
  Em: makeInteractiveTextElement("em", "<Interactive.Em>"),
  Footer: makeInteractiveTextElement("footer", "<Interactive.Footer>"),
  G: makeInteractiveSvgElement("g", "<Interactive.G>"),
  H1: makeInteractiveTextElement("h1", "<Interactive.H1>"),
  H2: makeInteractiveTextElement("h2", "<Interactive.H2>"),
  H3: makeInteractiveTextElement("h3", "<Interactive.H3>"),
  H4: makeInteractiveTextElement("h4", "<Interactive.H4>"),
  H5: makeInteractiveTextElement("h5", "<Interactive.H5>"),
  H6: makeInteractiveTextElement("h6", "<Interactive.H6>"),
  Header: makeInteractiveTextElement("header", "<Interactive.Header>"),
  Label: makeInteractiveTextElement("label", "<Interactive.Label>"),
  Li: makeInteractiveTextElement("li", "<Interactive.Li>"),
  Line: makeInteractiveSvgStrokeElement("line", "<Interactive.Line>"),
  Main: makeInteractiveTextElement("main", "<Interactive.Main>"),
  Nav: makeInteractiveTextElement("nav", "<Interactive.Nav>"),
  Ol: makeInteractiveTextElement("ol", "<Interactive.Ol>"),
  P: makeInteractiveTextElement("p", "<Interactive.P>"),
  Path: makeInteractiveSvgElement("path", "<Interactive.Path>"),
  Pre: makeInteractiveTextElement("pre", "<Interactive.Pre>"),
  Rect: makeInteractiveSvgElement("rect", "<Interactive.Rect>"),
  Section: makeInteractiveTextElement("section", "<Interactive.Section>"),
  Small: makeInteractiveTextElement("small", "<Interactive.Small>"),
  Span: makeInteractiveTextElement("span", "<Interactive.Span>"),
  Strong: makeInteractiveTextElement("strong", "<Interactive.Strong>"),
  Svg: makeInteractiveElement("svg", "<Interactive.Svg>", interactiveSvgRootElementSchema),
  Text: makeInteractiveElement("text", "<Interactive.Text>", interactiveSvgTextElementSchema),
  Ul: makeInteractiveTextElement("ul", "<Interactive.Ul>")
};
// src/internals.ts
import { createRef as createRef3 } from "react";

// src/animated-image/get-duration-in-seconds.ts
var getAnimatedImageDurationInSeconds = async ({
  resolvedSrc,
  signal,
  requestInit,
  contentType
}) => {
  const { decoder, selectedTrack } = await createImageDecoder({
    resolvedSrc,
    signal,
    requestInit,
    contentType
  });
  try {
    const { image } = await decoder.decode({
      frameIndex: selectedTrack.frameCount - 1,
      completeFramesOnly: true
    });
    try {
      if (image.duration === null) {
        throw new Error("Could not determine animated image duration");
      }
      return (image.timestamp + image.duration) / 1e6;
    } finally {
      image.close();
    }
  } finally {
    decoder.close();
  }
};

// src/CompositionManager.tsx
import React34 from "react";
var compositionsRef = React34.createRef();

// src/CompositionManagerProvider.tsx
import {
  useCallback as useCallback23,
  useEffect as useEffect18,
  useImperativeHandle as useImperativeHandle8,
  useLayoutEffect as useLayoutEffect15,
  useMemo as useMemo33,
  useRef as useRef27,
  useState as useState20
} from "react";
import { jsx as jsx32 } from "react/jsx-runtime";
var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? useEffect18 : useLayoutEffect15;
var CompositionManagerProvider = ({
  children,
  onlyRenderComposition,
  currentCompositionMetadata,
  initialCompositions,
  initialCanvasContent
}) => {
  const { isStudio } = useRemotionEnvironment();
  const [compositionManagerId] = useState20(() => String(Math.random()));
  const committedOrderRef = useRef27(null);
  const committedOrderIdsRef = useRef27(null);
  const internalOrderRef = useRef27(new Map(initialCompositions.map((composition, index) => [
    getCompositionAndFolderOrderKey({
      type: "composition",
      id: composition.id
    }),
    index
  ])));
  const nextInternalOrderRef = useRef27(initialCompositions.length);
  const [folders, setFolders] = useState20([]);
  const [canvasContent, setCanvasContent] = useState20(initialCanvasContent);
  const [currentAssetMetadata, setCurrentAssetMetadata] = useState20(null);
  const [compositions, setCompositions] = useState20(() => initialCompositions.map((composition, order) => ({ ...composition, order })));
  const currentcompositionsRef = useRef27(compositions);
  const updateCompositions = useCallback23((updateComps) => {
    setCompositions((comps) => {
      const updated = updateComps(comps);
      currentcompositionsRef.current = updated;
      return updated;
    });
  }, []);
  const registerComposition = useCallback23((comp) => {
    const orderKey = getCompositionAndFolderOrderKey({
      type: "composition",
      id: comp.id
    });
    const internalOrder = nextInternalOrderRef.current++;
    internalOrderRef.current.set(orderKey, internalOrder);
    updateCompositions((comps) => {
      if (comps.find((c2) => c2.id === comp.id)) {
        throw new Error(`Multiple composition with id ${comp.id} are registered.`);
      }
      return [
        ...comps,
        {
          ...comp,
          order: committedOrderRef.current?.get(orderKey) ?? internalOrder
        }
      ];
    });
  }, [updateCompositions]);
  const unregisterComposition = useCallback23((id) => {
    internalOrderRef.current.delete(getCompositionAndFolderOrderKey({ type: "composition", id }));
    setCompositions((comps) => {
      return comps.filter((c2) => c2.id !== id);
    });
  }, []);
  const registerFolder = useCallback23((name, parent, stack) => {
    const orderKey = getCompositionAndFolderOrderKey({
      type: "folder",
      id: getFolderOrderId({ name, parent })
    });
    const internalOrder = nextInternalOrderRef.current++;
    internalOrderRef.current.set(orderKey, internalOrder);
    setFolders((prevFolders) => {
      return [
        ...prevFolders,
        {
          name,
          parent,
          order: committedOrderRef.current?.get(orderKey) ?? internalOrder,
          stack
        }
      ];
    });
  }, []);
  const unregisterFolder = useCallback23((name, parent) => {
    internalOrderRef.current.delete(getCompositionAndFolderOrderKey({
      type: "folder",
      id: getFolderOrderId({ name, parent })
    }));
    setFolders((prevFolders) => {
      return prevFolders.filter((p) => !(p.name === name && p.parent === parent));
    });
  }, []);
  useIsomorphicLayoutEffect2(() => {
    if (!isStudio) {
      return;
    }
    let unmounted = false;
    const onCommitOrder = (event) => {
      const { detail } = event;
      const managerOrder = detail.compositionManagers.find((item) => item.managerId === compositionManagerId);
      if (!managerOrder) {
        return;
      }
      const orderIds = managerOrder.compositionAndFolderOrder.map(getCompositionAndFolderOrderKey);
      const previousOrder = committedOrderIdsRef.current;
      if (previousOrder !== null && previousOrder.length === orderIds.length && previousOrder.every((id, index) => id === orderIds[index])) {
        return;
      }
      const order = new Map(orderIds.map((id, index) => [id, index]));
      committedOrderIdsRef.current = orderIds;
      committedOrderRef.current = order;
      queueMicrotask(() => {
        if (unmounted) {
          return;
        }
        updateCompositions((currentCompositions) => {
          let changed = false;
          const nextCompositions = currentCompositions.map((composition) => {
            const nextOrder = order.get(getCompositionAndFolderOrderKey({
              type: "composition",
              id: composition.id
            })) ?? internalOrderRef.current.get(getCompositionAndFolderOrderKey({
              type: "composition",
              id: composition.id
            })) ?? composition.order;
            if (nextOrder === composition.order) {
              return composition;
            }
            changed = true;
            return { ...composition, order: nextOrder };
          });
          return changed ? nextCompositions : currentCompositions;
        });
        setFolders((currentFolders) => {
          let changed = false;
          const nextFolders = currentFolders.map((folder) => {
            const nextOrder = order.get(getCompositionAndFolderOrderKey({
              type: "folder",
              id: getFolderOrderId(folder)
            })) ?? internalOrderRef.current.get(getCompositionAndFolderOrderKey({
              type: "folder",
              id: getFolderOrderId(folder)
            })) ?? folder.order;
            if (nextOrder === folder.order) {
              return folder;
            }
            changed = true;
            return { ...folder, order: nextOrder };
          });
          return changed ? nextFolders : currentFolders;
        });
      });
    };
    window.addEventListener(COMMIT_ORDER_EVENT, onCommitOrder);
    return () => {
      unmounted = true;
      window.removeEventListener(COMMIT_ORDER_EVENT, onCommitOrder);
    };
  }, [compositionManagerId, isStudio, updateCompositions]);
  useImperativeHandle8(compositionsRef, () => {
    return {
      getCompositions: () => currentcompositionsRef.current
    };
  }, []);
  const compositionManagerSetters = useMemo33(() => {
    return {
      registerComposition,
      unregisterComposition,
      registerFolder,
      unregisterFolder,
      setCanvasContent,
      setCurrentAssetMetadata,
      onlyRenderComposition
    };
  }, [
    registerComposition,
    registerFolder,
    unregisterComposition,
    unregisterFolder,
    onlyRenderComposition
  ]);
  const compositionManagerContextValue = useMemo33(() => {
    return {
      compositions,
      folders,
      currentCompositionMetadata,
      currentAssetMetadata,
      canvasContent
    };
  }, [
    compositions,
    folders,
    currentCompositionMetadata,
    currentAssetMetadata,
    canvasContent
  ]);
  const providers = /* @__PURE__ */ jsx32(CompositionManager.Provider, {
    value: compositionManagerContextValue,
    children: /* @__PURE__ */ jsx32(CompositionSetters.Provider, {
      value: compositionManagerSetters,
      children
    })
  });
  return isStudio ? /* @__PURE__ */ jsx32(CompositionManagerOrderMarker, {
    managerId: compositionManagerId,
    children: providers
  }) : providers;
};

// src/default-css.ts
var exports_default_css = {};
__export(exports_default_css, {
  makeDefaultPreviewCSS: () => makeDefaultPreviewCSS,
  injectCSS: () => injectCSS,
  OBJECTFIT_CONTAIN_CLASS_NAME: () => OBJECTFIT_CONTAIN_CLASS_NAME
});
var injected = {};
var injectCSS = (css) => {
  if (typeof document === "undefined") {
    return () => {};
  }
  if (injected[css]) {
    return () => {};
  }
  const head = document.head || document.getElementsByTagName("head")[0];
  const style = document.createElement("style");
  style.appendChild(document.createTextNode(css));
  head.prepend(style);
  injected[css] = style;
  return () => {
    const styleElement = injected[css];
    if (styleElement) {
      if (styleElement.parentNode) {
        styleElement.parentNode.removeChild(styleElement);
      }
      delete injected[css];
    }
  };
};
var OBJECTFIT_CONTAIN_CLASS_NAME = "__remotion_objectfitcontain";
var makeDefaultPreviewCSS = (scope, backgroundColor) => {
  if (!scope) {
    return `
    * {
      box-sizing: border-box;
    }
    body {
      margin: 0;
	    background-color: ${backgroundColor};
    }
    .${OBJECTFIT_CONTAIN_CLASS_NAME} {
      object-fit: contain;
    }
    `;
  }
  return `
    ${scope} * {
      box-sizing: border-box;
    }
    ${scope} *:-webkit-full-screen {
      width: 100%;
      height: 100%;
    }
    ${scope} .${OBJECTFIT_CONTAIN_CLASS_NAME} {
      object-fit: contain;
    }
  `;
};

// src/get-preview-dom-element.ts
var REMOTION_STUDIO_CONTAINER_ELEMENT = "__remotion-studio-container";
var getPreviewDomElement = () => {
  return document.getElementById(REMOTION_STUDIO_CONTAINER_ELEMENT);
};

// src/max-video-cache-size.ts
import React35 from "react";
var MaxMediaCacheSizeContext = React35.createContext(null);

// src/media-resource-manager.ts
var disposeResource = (resource) => {
  if (resource.disposed) {
    return;
  }
  resource.disposed = true;
  resource.values.clear();
  resource.dispose();
};
var makeMediaResourceManager = () => {
  const resources = new Map;
  let disposed = false;
  return {
    acquire: ({
      key,
      create
    }) => {
      if (disposed) {
        throw new Error("Media resource manager has already been disposed");
      }
      let entry = resources.get(key);
      if (!entry) {
        const created = create();
        entry = {
          resource: created.resource,
          dispose: created.dispose,
          refCount: 0,
          disposeGeneration: 0,
          disposed: false,
          values: new Map
        };
        resources.set(key, entry);
      }
      entry.refCount++;
      entry.disposeGeneration++;
      let released = false;
      return {
        resource: entry.resource,
        getOrCreateValue: (valueKey, createValue) => {
          if (entry.values.has(valueKey)) {
            return entry.values.get(valueKey);
          }
          const value = createValue();
          entry.values.set(valueKey, value);
          return value;
        },
        release: () => {
          if (released) {
            return;
          }
          released = true;
          entry.refCount--;
          if (entry.refCount !== 0) {
            return;
          }
          const disposeGeneration = ++entry.disposeGeneration;
          queueMicrotask(() => {
            if (entry.refCount !== 0 || entry.disposeGeneration !== disposeGeneration) {
              return;
            }
            if (resources.get(key) === entry) {
              resources.delete(key);
            }
            disposeResource(entry);
          });
        }
      };
    },
    invalidate: (key) => {
      const entry = resources.get(key);
      if (!entry) {
        return;
      }
      resources.delete(key);
      entry.disposeGeneration++;
      if (entry.refCount === 0) {
        disposeResource(entry);
      }
    },
    dispose: () => {
      if (disposed) {
        return;
      }
      disposed = true;
      const entries = Array.from(resources.values());
      resources.clear();
      let firstError = null;
      for (const entry of entries) {
        try {
          disposeResource(entry);
        } catch (error2) {
          firstError ??= error2;
        }
      }
      if (firstError !== null) {
        throw firstError;
      }
    }
  };
};
var getMediabunnyInputResourceKey = ({
  src,
  credentials,
  requestInitFingerprint,
  revision
}) => JSON.stringify([
  "mediabunny-input",
  src,
  credentials,
  requestInitFingerprint,
  revision
]);
var MEDIABUNNY_DURATION_VALUE_KEY = "mediabunny-duration";
var globalMediaResourceManager = makeMediaResourceManager();

// src/register-root.ts
var Root = null;
var listeners = [];
var registerRoot = (comp) => {
  if (!comp) {
    throw new Error(`You must pass a React component to registerRoot(), but ${JSON.stringify(comp)} was passed.`);
  }
  if (Root) {
    throw new Error("registerRoot() was called more than once.");
  }
  Root = comp;
  listeners.forEach((l) => {
    l(comp);
  });
};
var getRoot = () => {
  return Root;
};
var waitForRoot = (fn) => {
  if (Root) {
    fn(Root);
    return () => {
      return;
    };
  }
  listeners.push(fn);
  return () => {
    listeners = listeners.filter((l) => l !== fn);
  };
};

// src/RemotionRoot.tsx
import { useMemo as useMemo34 } from "react";
import { jsx as jsx33 } from "react/jsx-runtime";
var RemotionRootContexts = ({
  children,
  numberOfAudioTags,
  logLevel,
  audioLatencyHint,
  previewSampleRate,
  videoEnabled,
  audioEnabled,
  frameState,
  _experimentalKeepAudioContextAlive
}) => {
  const logging = useMemo34(() => {
    return { logLevel, mountTime: Date.now() };
  }, [logLevel]);
  return /* @__PURE__ */ jsx33(LogLevelContext.Provider, {
    value: logging,
    children: /* @__PURE__ */ jsx33(TimelineContextProvider, {
      frameState,
      children: /* @__PURE__ */ jsx33(MediaEnabledProvider, {
        videoEnabled,
        audioEnabled,
        children: /* @__PURE__ */ jsx33(EditorPropsProvider, {
          children: /* @__PURE__ */ jsx33(PrefetchProvider, {
            children: /* @__PURE__ */ jsx33(SequenceManagerProvider, {
              children: /* @__PURE__ */ jsx33(DurationsContextProvider, {
                children: /* @__PURE__ */ jsx33(BufferingProvider, {
                  children: /* @__PURE__ */ jsx33(SharedAudioContextProvider, {
                    audioLatencyHint,
                    audioEnabled,
                    previewSampleRate,
                    _experimentalKeepAudioContextAlive,
                    children: /* @__PURE__ */ jsx33(SharedAudioTagsContextProvider, {
                      numberOfAudioTags,
                      children
                    })
                  })
                })
              })
            })
          })
        })
      })
    })
  });
};

// src/render-resource-manager.ts
import React37 from "react";
var makeRenderResourceManager = () => {
  const resources = new Map;
  let disposed = false;
  return {
    getOrCreateResource: ({
      key,
      create
    }) => {
      if (disposed) {
        throw new Error("Render resource manager has already been disposed");
      }
      const existing = resources.get(key);
      if (existing) {
        return existing.resource;
      }
      const created = create();
      resources.set(key, created);
      return created.resource;
    },
    dispose: () => {
      if (disposed) {
        return;
      }
      disposed = true;
      const resourcesToDispose = Array.from(resources.values());
      resources.clear();
      let firstError = null;
      for (const resource of resourcesToDispose) {
        try {
          resource.dispose();
        } catch (error2) {
          firstError ??= error2;
        }
      }
      if (firstError !== null) {
        throw firstError;
      }
    }
  };
};
var RenderResourceManagerContext = React37.createContext(null);

// src/codec.ts
var validCodecs = [
  "h264",
  "h265",
  "vp8",
  "vp9",
  "av1",
  "mp3",
  "aac",
  "wav",
  "prores",
  "h264-mkv",
  "h264-ts",
  "gif"
];

// src/validation/validate-default-codec.ts
function validateCodec(defaultCodec, location, name) {
  if (typeof defaultCodec === "undefined") {
    return;
  }
  if (typeof defaultCodec !== "string") {
    throw new TypeError(`The "${name}" prop ${location} must be a string, but you passed a value of type ${typeof defaultCodec}.`);
  }
  if (!validCodecs.includes(defaultCodec)) {
    throw new Error(`The "${name}" prop ${location} must be one of ${validCodecs.join(", ")}, but you passed ${defaultCodec}.`);
  }
}

// src/resolve-video-config.ts
var validateCalculated = ({
  calculated,
  compositionId,
  compositionFps,
  compositionHeight,
  compositionWidth,
  compositionDurationInFrames
}) => {
  const calculateMetadataErrorLocation = `calculated by calculateMetadata() for the composition "${compositionId}"`;
  const defaultErrorLocation = `of the "<Composition />" component with the id "${compositionId}"`;
  const width = calculated?.width ?? compositionWidth ?? undefined;
  validateDimension(width, "width", calculated?.width ? calculateMetadataErrorLocation : defaultErrorLocation);
  const height = calculated?.height ?? compositionHeight ?? undefined;
  validateDimension(height, "height", calculated?.height ? calculateMetadataErrorLocation : defaultErrorLocation);
  const fps = calculated?.fps ?? compositionFps ?? null;
  validateFps(fps, calculated?.fps ? calculateMetadataErrorLocation : defaultErrorLocation, false);
  const durationInFrames = calculated?.durationInFrames ?? compositionDurationInFrames ?? null;
  validateDurationInFrames(durationInFrames, {
    allowFloats: false,
    component: `of the "<Composition />" component with the id "${compositionId}"`
  });
  const defaultCodec = calculated?.defaultCodec;
  validateCodec(defaultCodec, calculateMetadataErrorLocation, "defaultCodec");
  const defaultOutName = calculated?.defaultOutName;
  const defaultVideoImageFormat = calculated?.defaultVideoImageFormat;
  const defaultPixelFormat = calculated?.defaultPixelFormat;
  const defaultProResProfile = calculated?.defaultProResProfile;
  const defaultSampleRate = calculated?.defaultSampleRate;
  return {
    width,
    height,
    fps,
    durationInFrames,
    defaultCodec,
    defaultOutName,
    defaultVideoImageFormat,
    defaultPixelFormat,
    defaultProResProfile,
    defaultSampleRate
  };
};
var makeVideoConfigWithMetadata = ({
  calculated,
  compositionDurationInFrames,
  compositionFps,
  compositionHeight,
  compositionId,
  compositionWidth,
  defaultProps,
  originalProps
}) => {
  const data = validateCalculated({
    calculated,
    compositionDurationInFrames,
    compositionFps,
    compositionHeight,
    compositionWidth,
    compositionId
  });
  return {
    metadataSource: {
      durationInFrames: calculated?.durationInFrames === undefined ? "composition" : "calculate-metadata",
      fps: calculated?.fps === undefined ? "composition" : "calculate-metadata",
      height: calculated?.height === undefined ? "composition" : "calculate-metadata",
      width: calculated?.width === undefined ? "composition" : "calculate-metadata"
    },
    videoConfig: {
      ...data,
      id: compositionId,
      defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}),
      props: serializeThenDeserializeInStudio(calculated?.props ?? originalProps),
      defaultCodec: data.defaultCodec ?? null,
      defaultOutName: data.defaultOutName ?? null,
      defaultVideoImageFormat: data.defaultVideoImageFormat ?? null,
      defaultPixelFormat: data.defaultPixelFormat ?? null,
      defaultProResProfile: data.defaultProResProfile ?? null,
      defaultSampleRate: data.defaultSampleRate ?? null
    }
  };
};
var resolveVideoConfigWithMetadata = ({
  calculateMetadata,
  signal,
  defaultProps,
  inputProps: originalProps,
  compositionId,
  compositionDurationInFrames,
  compositionFps,
  compositionHeight,
  compositionWidth
}) => {
  const calculatedProm = calculateMetadata ? calculateMetadata({
    defaultProps,
    props: originalProps,
    abortSignal: signal,
    compositionId,
    isRendering: getRemotionEnvironment().isRendering
  }) : null;
  if (calculatedProm !== null && typeof calculatedProm === "object" && "then" in calculatedProm) {
    return calculatedProm.then((c2) => {
      return makeVideoConfigWithMetadata({
        calculated: c2,
        compositionDurationInFrames,
        compositionFps,
        compositionHeight,
        compositionWidth,
        compositionId,
        defaultProps,
        originalProps
      });
    });
  }
  return makeVideoConfigWithMetadata({
    calculated: calculatedProm,
    compositionDurationInFrames,
    compositionFps,
    compositionHeight,
    compositionWidth,
    compositionId,
    defaultProps,
    originalProps
  });
};
var resolveVideoConfig = (params) => {
  const resolved = resolveVideoConfigWithMetadata(params);
  if (typeof resolved === "object" && "then" in resolved) {
    return resolved.then(({ videoConfig }) => videoConfig);
  }
  return resolved.videoConfig;
};
var resolveVideoConfigWithMetadataOrCatch = (params) => {
  try {
    return {
      type: "success",
      result: resolveVideoConfigWithMetadata(params)
    };
  } catch (err) {
    return {
      type: "error",
      error: err
    };
  }
};
var resolveVideoConfigOrCatch = (params) => {
  try {
    const promiseOrReturnValue = resolveVideoConfig(params);
    return {
      type: "success",
      result: promiseOrReturnValue
    };
  } catch (err) {
    return {
      type: "error",
      error: err
    };
  }
};

// src/sequence-stack-traces.ts
import React38 from "react";
var SequenceStackTracesUpdateContext = React38.createContext(() => {});

// src/setup-env-variables.ts
var getEnvVariables = () => {
  if (getRemotionEnvironment().isRendering) {
    const param = window.remotion_envVariables;
    if (!param) {
      return {};
    }
    return { ...JSON.parse(param), NODE_ENV: "production" };
  }
  if (false) {}
  return {
    NODE_ENV: "production"
  };
};
var setupEnvVariables = () => {
  const env = getEnvVariables();
  if (!window.process) {
    window.process = {};
  }
  if (!window.process.env) {
    window.process.env = {};
  }
  Object.keys(env).forEach((key) => {
    window.process.env[key] = env[key];
  });
};

// src/use-pixel-density.ts
import React39, { useContext as useContext38 } from "react";
var PixelDensityContext = React39.createContext(null);
var getBrowserPixelDensity = () => {
  if (typeof window === "undefined") {
    return 1;
  }
  return window.devicePixelRatio || 1;
};
var usePixelDensity = (options) => {
  const pixelDensity = useContext38(PixelDensityContext);
  const canUseRemotionHooks = useContext38(CanUseRemotionHooks);
  if (pixelDensity !== null) {
    return pixelDensity;
  }
  if (canUseRemotionHooks || options?.dontThrowIfOutsideOfRemotion) {
    return getBrowserPixelDensity();
  }
  throw new Error([
    "usePixelDensity() was called outside of a Remotion context.",
    "This hook can only be called in a component that is being rendered by Remotion.",
    "If you want this hook to return the browser pixel density outside of Remotion, pass {dontThrowIfOutsideOfRemotion: true} as an option.",
    "If you think you called this hook in a Remotion component, make sure all versions of Remotion are aligned."
  ].join(`
`));
};

// src/video/OffthreadVideo.tsx
import { useCallback as useCallback26 } from "react";

// src/video/OffthreadVideoForRendering.tsx
import {
  useCallback as useCallback24,
  useContext as useContext39,
  useEffect as useEffect19,
  useLayoutEffect as useLayoutEffect16,
  useMemo as useMemo35,
  useState as useState21
} from "react";

// src/video/offthread-video-source.ts
var getOffthreadVideoSource = ({
  src,
  transparent,
  currentTime,
  toneMapped
}) => {
  return `http://localhost:${window.remotion_proxyPort}/proxy?src=${encodeURIComponent(getAbsoluteSrc(src))}&time=${encodeURIComponent(Math.max(0, currentTime))}&transparent=${String(transparent)}&toneMapped=${String(toneMapped)}`;
};

// src/video/OffthreadVideoForRendering.tsx
import { jsx as jsx34 } from "react/jsx-runtime";
var OffthreadVideoForRendering = ({
  onError,
  volume: volumeProp,
  playbackRate,
  src,
  muted,
  allowAmplificationDuringRender,
  transparent,
  toneMapped,
  toneFrequency,
  name,
  loopVolumeCurveBehavior,
  delayRenderRetries,
  delayRenderTimeoutInMilliseconds,
  onVideoFrame,
  crossOrigin,
  audioStreamIndex,
  preservePitch: _preservePitch,
  ...props2
}) => {
  const absoluteFrame = useTimelinePosition();
  const frame = useCurrentFrame();
  const volumePropsFrame = useFrameForVolumeProp(loopVolumeCurveBehavior);
  const videoConfig = useUnsafeVideoConfig();
  const sequenceContext = useContext39(SequenceContext);
  const mediaStartsAt = useMediaStartsAt();
  const { registerRenderAsset, unregisterRenderAsset } = useContext39(RenderAssetManager);
  if (!src) {
    throw new TypeError("No `src` was passed to <OffthreadVideo>.");
  }
  const id = useMemo35(() => `offthreadvideo-${random(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
    src,
    sequenceContext?.cumulatedFrom,
    sequenceContext?.relativeFrom,
    sequenceContext?.durationInFrames
  ]);
  const volume = evaluateVolume({
    volume: volumeProp,
    frame: volumePropsFrame,
    mediaVolume: 1
  });
  warnAboutTooHighVolume(volume);
  const audioEnabled = useAudioEnabled();
  const { shouldUseAudio } = useMediaAudioState({
    muted,
    volume,
    audioEnabled
  });
  if (!videoConfig) {
    throw new Error("No video config found");
  }
  useEffect19(() => {
    if (!src) {
      throw new Error("No src passed");
    }
    if (!shouldUseAudio) {
      return;
    }
    registerRenderAsset({
      type: "video",
      src: getAbsoluteSrc(src),
      id,
      frame: absoluteFrame,
      volume,
      mediaFrame: frame,
      playbackRate,
      toneFrequency,
      audioStartFrame: Math.max(0, -(sequenceContext?.cumulatedNegativeFrom ?? 0)),
      audioStreamIndex
    });
    return () => unregisterRenderAsset(id);
  }, [
    shouldUseAudio,
    src,
    registerRenderAsset,
    id,
    unregisterRenderAsset,
    volume,
    frame,
    absoluteFrame,
    playbackRate,
    toneFrequency,
    sequenceContext?.cumulatedNegativeFrom,
    audioStreamIndex
  ]);
  const currentTime = useMemo35(() => {
    return getExpectedMediaFrameUncorrected({
      frame,
      playbackRate: playbackRate || 1,
      startFrom: -mediaStartsAt
    }) / videoConfig.fps;
  }, [frame, mediaStartsAt, playbackRate, videoConfig.fps]);
  const actualSrc = useMemo35(() => {
    return getOffthreadVideoSource({
      src,
      currentTime,
      transparent,
      toneMapped
    });
  }, [toneMapped, currentTime, src, transparent]);
  const [imageSrc, setImageSrc] = useState21(null);
  const { delayRender: delayRender2, continueRender: continueRender2 } = useDelayRender();
  useLayoutEffect16(() => {
    if (!window.remotion_videoEnabled) {
      return;
    }
    const cleanup = [];
    setImageSrc(null);
    const controller = new AbortController;
    const newHandle = delayRender2(`Fetching ${actualSrc} from server`, {
      retries: delayRenderRetries ?? undefined,
      timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
    });
    const execute = async () => {
      try {
        const res = await fetch(actualSrc, {
          signal: controller.signal,
          cache: "no-store"
        });
        if (res.status !== 200) {
          if (res.status === 500) {
            const json = await res.json();
            if (json.error) {
              const cleanedUpErrorMessage = json.error.replace(/^Error: /, "");
              throw new Error(cleanedUpErrorMessage);
            }
          }
          throw new Error(`Server returned status ${res.status} while fetching ${actualSrc}`);
        }
        const blob = await res.blob();
        const url = URL.createObjectURL(blob);
        cleanup.push(() => URL.revokeObjectURL(url));
        setImageSrc({
          src: url,
          handle: newHandle
        });
      } catch (err) {
        if (err.message.includes("aborted")) {
          continueRender2(newHandle);
          return;
        }
        if (controller.signal.aborted) {
          continueRender2(newHandle);
          return;
        }
        if (err.message.includes("Failed to fetch")) {
          err = new Error(`Failed to fetch ${actualSrc}. This could be caused by Chrome rejecting the request because the disk space is low. Consider increasing the disk size of your environment.`, { cause: err });
        }
        if (onError) {
          onError(err);
        } else {
          cancelRender(err);
        }
      }
    };
    execute();
    cleanup.push(() => {
      if (controller.signal.aborted) {
        return;
      }
      controller.abort();
    });
    return () => {
      cleanup.forEach((c2) => c2());
    };
  }, [
    actualSrc,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    onError,
    continueRender2,
    delayRender2
  ]);
  const onErr = useCallback24(() => {
    if (onError) {
      onError?.(new Error("Failed to load image with src " + imageSrc));
    } else {
      cancelRender("Failed to load image with src " + imageSrc);
    }
  }, [imageSrc, onError]);
  const className = useMemo35(() => {
    return [OBJECTFIT_CONTAIN_CLASS_NAME, props2.className].filter(truthy).join(" ");
  }, [props2.className]);
  const onImageFrame = useCallback24((img) => {
    if (onVideoFrame) {
      onVideoFrame(img);
    }
  }, [onVideoFrame]);
  if (!imageSrc || !window.remotion_videoEnabled) {
    return null;
  }
  continueRender2(imageSrc.handle);
  return /* @__PURE__ */ jsx34(Img, {
    src: imageSrc.src,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    onImageFrame,
    ...props2,
    onError: onErr,
    className
  });
};

// src/video/VideoForPreview.tsx
import React41, {
  forwardRef as forwardRef13,
  useCallback as useCallback25,
  useContext as useContext40,
  useEffect as useEffect21,
  useImperativeHandle as useImperativeHandle9,
  useMemo as useMemo36,
  useRef as useRef28,
  useState as useState22
} from "react";

// src/video/emit-video-frame.ts
import { useEffect as useEffect20 } from "react";
var useEmitVideoFrame = ({
  ref,
  onVideoFrame
}) => {
  useEffect20(() => {
    const { current } = ref;
    if (!current) {
      return;
    }
    if (!onVideoFrame) {
      return;
    }
    let handle = 0;
    const callback = (_now, metadata) => {
      if (!ref.current) {
        return;
      }
      onVideoFrame(ref.current, _now, metadata);
      handle = ref.current.requestVideoFrameCallback(callback);
    };
    onVideoFrame(current);
    if (!current.requestVideoFrameCallback) {
      return;
    }
    handle = current.requestVideoFrameCallback(callback);
    return () => {
      if (handle) {
        current.cancelVideoFrameCallback(handle);
      }
    };
  }, [onVideoFrame, ref]);
};

// src/video/MediaPlaybackError.ts
class MediaPlaybackError extends Error {
  src;
  constructor({ message, src }) {
    super(message);
    this.name = "MediaPlaybackError";
    this.src = src;
  }
}

// src/video/VideoForPreview.tsx
import { jsx as jsx35 } from "react/jsx-runtime";
var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
  const context = useContext40(SharedAudioContext);
  if (!context) {
    throw new Error("SharedAudioContext not found");
  }
  const videoRef = useRef28(null);
  const sharedSource = useMemo36(() => {
    if (!context.audioContext) {
      return null;
    }
    return makeSharedElementSourceNode({
      audioContext: context.audioContext,
      ref: videoRef
    });
  }, [context.audioContext]);
  const effectToUse = React41.useInsertionEffect ?? React41.useLayoutEffect;
  effectToUse(() => {
    return () => {
      requestAnimationFrame(() => {
        sharedSource?.cleanup();
      });
    };
  }, [sharedSource]);
  const {
    volume,
    muted,
    playbackRate,
    preservePitch,
    onlyWarnForMediaSeekingError,
    src,
    onDuration,
    acceptableTimeShift,
    acceptableTimeShiftInSeconds,
    toneFrequency,
    name,
    _remotionInternalNativeLoopPassed,
    _remotionInternalStack,
    style,
    pauseWhenBuffering,
    showInTimeline,
    loopVolumeCurveBehavior,
    onError,
    onAutoPlayError,
    onVideoFrame,
    crossOrigin,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    allowAmplificationDuringRender,
    useWebAudioApi,
    audioStreamIndex,
    ...nativeProps
  } = props2;
  const _propsValid = true;
  if (!_propsValid) {
    throw new Error("typecheck error");
  }
  const volumePropFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
  const { fps, durationInFrames } = useVideoConfig();
  const parentSequence = useContext40(SequenceContext);
  const { isStudio } = useRemotionEnvironment();
  const logLevel = useLogLevel();
  const mountTime = useMountTime();
  const [timelineId] = useState22(() => String(Math.random()));
  if (typeof acceptableTimeShift !== "undefined") {
    throw new Error("acceptableTimeShift has been removed. Use acceptableTimeShiftInSeconds instead.");
  }
  const [mediaVolume] = useMediaVolumeState();
  const userPreferredVolume = evaluateVolume({
    frame: volumePropFrame,
    volume,
    mediaVolume
  });
  const { isMutedForTimeline, isMutedForPlayback } = useMediaAudioState({
    muted: muted ?? false,
    volume: userPreferredVolume,
    audioEnabled: true
  });
  warnAboutTooHighVolume(userPreferredVolume);
  const getStack = useCallback25(() => {
    return _remotionInternalStack ?? null;
  }, [_remotionInternalStack]);
  useMediaInTimeline({
    volume,
    mediaVolume,
    mediaType: "video",
    src,
    playbackRate: props2.playbackRate ?? 1,
    displayName: name ?? null,
    id: timelineId,
    getStack,
    showInTimeline,
    premountDisplay: parentSequence?.premountDisplay ?? null,
    postmountDisplay: parentSequence?.postmountDisplay ?? null,
    loopDisplay: undefined,
    documentationLink: onlyWarnForMediaSeekingError ? "https://www.remotion.dev/docs/offthreadvideo" : "https://www.remotion.dev/docs/html5-video",
    refForOutline: videoRef,
    muted: isMutedForTimeline
  });
  useMediaPlayback({
    mediaRef: videoRef,
    src,
    mediaType: "video",
    playbackRate: props2.playbackRate ?? 1,
    preservePitch,
    onlyWarnForMediaSeekingError,
    acceptableTimeshift: acceptableTimeShiftInSeconds ?? null,
    isPremounting: Boolean(parentSequence?.premounting),
    isPostmounting: Boolean(parentSequence?.postmounting),
    pauseWhenBuffering,
    onAutoPlayError: onAutoPlayError ?? null
  });
  useMediaTag({
    id: timelineId,
    isPostmounting: Boolean(parentSequence?.postmounting),
    isPremounting: Boolean(parentSequence?.premounting),
    mediaRef: videoRef,
    mediaType: "video",
    onAutoPlayError: onAutoPlayError ?? null
  });
  useVolume({
    logLevel,
    mediaRef: videoRef,
    volume: userPreferredVolume,
    source: sharedSource,
    shouldUseWebAudioApi: useWebAudioApi ?? false
  });
  const actualFrom = parentSequence ? parentSequence.relativeFrom : 0;
  const duration = parentSequence ? Math.min(parentSequence.durationInFrames, durationInFrames) : durationInFrames;
  const preloadedSrc = usePreload(src);
  const actualSrc = useAppendVideoFragment({
    actualSrc: preloadedSrc,
    actualFrom,
    duration,
    fps
  });
  useImperativeHandle9(ref, () => {
    return videoRef.current;
  }, []);
  useState22(() => playbackLogging({
    logLevel,
    message: `Mounting video with source = ${actualSrc}, v=${VERSION}, user agent=${typeof navigator === "undefined" ? "server" : navigator.userAgent}`,
    tag: "video",
    mountTime
  }));
  useEffect21(() => {
    const { current } = videoRef;
    if (!current) {
      return;
    }
    const errorHandler = () => {
      if (current.error) {
        console.error("Error occurred in video", current?.error);
        if (onError) {
          const err = new MediaPlaybackError({
            message: `Code ${current.error.code}: ${current.error.message}`,
            src
          });
          onError(err);
          return;
        }
        throw new MediaPlaybackError({
          message: `The browser threw an error while playing the video ${src}: Code ${current.error.code} - ${current?.error?.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`,
          src
        });
      } else {
        if (onError) {
          const err = new MediaPlaybackError({
            message: `The browser threw an error while playing the video ${src}`,
            src
          });
          onError(err);
          return;
        }
        throw new MediaPlaybackError({
          message: "The browser threw an error while playing the video",
          src
        });
      }
    };
    current.addEventListener("error", errorHandler, { once: true });
    return () => {
      current.removeEventListener("error", errorHandler);
    };
  }, [onError, src]);
  const currentOnDurationCallback = useRef28(onDuration);
  currentOnDurationCallback.current = onDuration;
  useEmitVideoFrame({ ref: videoRef, onVideoFrame });
  useEffect21(() => {
    const { current } = videoRef;
    if (!current) {
      return;
    }
    if (current.duration) {
      currentOnDurationCallback.current?.(src, current.duration);
      return;
    }
    const onLoadedMetadata = () => {
      currentOnDurationCallback.current?.(src, current.duration);
    };
    current.addEventListener("loadedmetadata", onLoadedMetadata);
    return () => {
      current.removeEventListener("loadedmetadata", onLoadedMetadata);
    };
  }, [src]);
  useEffect21(() => {
    const { current } = videoRef;
    if (!current) {
      return;
    }
    if (isIosSafari()) {
      current.preload = "metadata";
    } else {
      current.preload = "auto";
    }
  }, []);
  const actualStyle = useMemo36(() => {
    return {
      ...style
    };
  }, [style]);
  const crossOriginValue = getCrossOriginValue({
    crossOrigin,
    requestsVideoFrame: Boolean(onVideoFrame),
    isClientSideRendering: false
  });
  const video = /* @__PURE__ */ jsx35("video", {
    ...nativeProps,
    ref: videoRef,
    muted: isMutedForPlayback,
    playsInline: true,
    src: actualSrc,
    loop: _remotionInternalNativeLoopPassed,
    style: actualStyle,
    disableRemotePlayback: true,
    crossOrigin: crossOriginValue,
    controls: false
  });
  return isStudio ? /* @__PURE__ */ jsx35(SequenceOrderMarker, {
    sequenceId: timelineId,
    children: video
  }) : video;
};
var VideoForPreview = forwardRef13(VideoForDevelopmentRefForwardingFunction);

// src/video/OffthreadVideo.tsx
import { jsx as jsx36 } from "react/jsx-runtime";
var InnerOffthreadVideo = (props2) => {
  const {
    startFrom,
    endAt,
    trimBefore,
    trimAfter,
    name,
    pauseWhenBuffering,
    _remotionInternalStack,
    showInTimeline,
    ...otherProps
  } = props2;
  const environment = useRemotionEnvironment();
  const shouldPauseWhenBuffering = resolveV5Default(pauseWhenBuffering);
  if (environment.isClientSideRendering) {
    throw new Error("<OffthreadVideo> is not supported in @remotion/web-renderer. Use <Video> from @remotion/media instead. See https://remotion.dev/docs/client-side-rendering/limitations");
  }
  const onDuration = useCallback26(() => {
    return;
  }, []);
  if (typeof props2.src !== "string") {
    throw new TypeError(`The \`<OffthreadVideo>\` tag requires a string for \`src\`, but got ${JSON.stringify(props2.src)} instead.`);
  }
  validateMediaTrimProps({ startFrom, endAt, trimBefore, trimAfter });
  const { trimBeforeValue, trimAfterValue } = resolveTrimProps({
    startFrom,
    endAt,
    trimBefore,
    trimAfter
  });
  if (typeof trimBeforeValue !== "undefined" || typeof trimAfterValue !== "undefined") {
    return /* @__PURE__ */ jsx36(Sequence, {
      layout: "none",
      from: 0 - (trimBeforeValue ?? 0),
      showInTimeline: false,
      durationInFrames: trimAfterValue,
      name,
      children: /* @__PURE__ */ jsx36(InnerOffthreadVideo, {
        pauseWhenBuffering: shouldPauseWhenBuffering,
        ...otherProps,
        trimAfter: undefined,
        name: undefined,
        showInTimeline,
        trimBefore: undefined,
        _remotionInternalStack: undefined,
        startFrom: undefined,
        endAt: undefined
      })
    });
  }
  validateMediaProps(props2, "Video");
  if (environment.isRendering) {
    return /* @__PURE__ */ jsx36(OffthreadVideoForRendering, {
      pauseWhenBuffering: shouldPauseWhenBuffering,
      ...otherProps,
      trimAfter: undefined,
      name: undefined,
      showInTimeline,
      trimBefore: undefined,
      _remotionInternalStack: undefined,
      startFrom: undefined,
      endAt: undefined
    });
  }
  const {
    transparent,
    toneMapped,
    onAutoPlayError,
    onVideoFrame,
    crossOrigin,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    ...propsForPreview
  } = otherProps;
  return /* @__PURE__ */ jsx36(VideoForPreview, {
    _remotionInternalStack: _remotionInternalStack ?? null,
    onDuration,
    onlyWarnForMediaSeekingError: true,
    pauseWhenBuffering: shouldPauseWhenBuffering,
    showInTimeline: showInTimeline ?? true,
    onAutoPlayError: onAutoPlayError ?? undefined,
    onVideoFrame: onVideoFrame ?? null,
    crossOrigin,
    ...propsForPreview,
    _remotionInternalNativeLoopPassed: false
  });
};
var OffthreadVideo = ({
  src,
  acceptableTimeShiftInSeconds,
  allowAmplificationDuringRender,
  audioStreamIndex,
  crossOrigin,
  delayRenderRetries,
  delayRenderTimeoutInMilliseconds,
  loopVolumeCurveBehavior,
  muted,
  name,
  onAutoPlayError,
  onError,
  onVideoFrame,
  pauseWhenBuffering,
  playbackRate,
  preservePitch,
  showInTimeline,
  style,
  toneFrequency,
  toneMapped,
  transparent,
  trimAfter,
  trimBefore,
  useWebAudioApi,
  volume,
  _remotionInternalNativeLoopPassed,
  endAt,
  _remotionInternalStack,
  startFrom,
  imageFormat,
  ...props2
}) => {
  if (imageFormat) {
    throw new TypeError(`The \`<OffthreadVideo>\` tag does no longer accept \`imageFormat\`. Use the \`transparent\` prop if you want to render a transparent video.`);
  }
  return /* @__PURE__ */ jsx36(InnerOffthreadVideo, {
    acceptableTimeShiftInSeconds,
    allowAmplificationDuringRender: allowAmplificationDuringRender ?? true,
    audioStreamIndex: audioStreamIndex ?? 0,
    crossOrigin,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    loopVolumeCurveBehavior: loopVolumeCurveBehavior ?? "repeat",
    muted: muted ?? false,
    name,
    onAutoPlayError: onAutoPlayError ?? null,
    onError,
    onVideoFrame,
    pauseWhenBuffering: resolveV5Default(pauseWhenBuffering),
    playbackRate: playbackRate ?? 1,
    preservePitch,
    toneFrequency: toneFrequency ?? 1,
    showInTimeline: showInTimeline ?? true,
    src,
    _remotionInternalStack,
    startFrom,
    _remotionInternalNativeLoopPassed: _remotionInternalNativeLoopPassed ?? false,
    endAt,
    style,
    toneMapped: toneMapped ?? true,
    transparent: transparent ?? false,
    trimAfter,
    trimBefore,
    useWebAudioApi: useWebAudioApi ?? false,
    volume,
    ...props2
  });
};
addSequenceStackTraces(OffthreadVideo);

// src/watch-static-file.ts
var WATCH_REMOTION_STATIC_FILES = "remotion_staticFilesChanged";
var watchStaticFile = (fileName, callback) => {
  if (ENABLE_V5_BREAKING_CHANGES) {
    throw new Error("watchStaticFile() has moved into the `@remotion/studio` package. Update your imports.");
  }
  if (!getRemotionEnvironment().isStudio) {
    console.warn("The watchStaticFile() API is only available while using the Remotion Studio.");
    return { cancel: () => {
      return;
    } };
  }
  const withoutStaticBase = fileName.startsWith(window.remotion_staticBase) ? fileName.replace(window.remotion_staticBase, "") : fileName;
  const withoutLeadingSlash = withoutStaticBase.startsWith("/") ? withoutStaticBase.slice(1) : withoutStaticBase;
  let prevFileData = window.remotion_staticFiles.find((file) => file.name === withoutLeadingSlash);
  const checkFile = (event) => {
    const staticFiles = event.detail.files;
    const newFileData = staticFiles.find((file) => file.name === withoutLeadingSlash);
    if (!newFileData) {
      if (prevFileData !== undefined) {
        callback(null);
      }
      prevFileData = undefined;
      return;
    }
    if (prevFileData === undefined || prevFileData.lastModified !== newFileData.lastModified) {
      callback(newFileData);
      prevFileData = newFileData;
    }
  };
  window.addEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
  const cancel = () => {
    return window.removeEventListener(WATCH_REMOTION_STATIC_FILES, checkFile);
  };
  return { cancel };
};

// src/wrap-remotion-context.tsx
import React43, { useMemo as useMemo37 } from "react";
import { jsx as jsx37 } from "react/jsx-runtime";
function useRemotionContexts() {
  const compositionManagerCtx = React43.useContext(CompositionManager);
  const timelineContext = React43.useContext(TimelineContext);
  const setTimelineContext = React43.useContext(SetTimelineContext);
  const sequenceContext = React43.useContext(SequenceContext);
  const canUseRemotionHooksContext = React43.useContext(CanUseRemotionHooks);
  const preloadContext = React43.useContext(PreloadContext);
  const resolveCompositionContext = React43.useContext(ResolveCompositionContext);
  const renderAssetManagerContext = React43.useContext(RenderAssetManager);
  const sequenceManagerContext = React43.useContext(SequenceManager);
  const sequenceManagerRefContext = React43.useContext(SequenceManagerRefContext);
  const visualModePropStatusesRefContext = React43.useContext(VisualModePropStatusesRefContext);
  const bufferManagerContext = React43.useContext(BufferingContextReact);
  const logLevelContext = React43.useContext(LogLevelContext);
  return useMemo37(() => ({
    compositionManagerCtx,
    timelineContext,
    setTimelineContext,
    sequenceContext,
    canUseRemotionHooksContext,
    preloadContext,
    resolveCompositionContext,
    renderAssetManagerContext,
    sequenceManagerContext,
    sequenceManagerRefContext,
    visualModePropStatusesRefContext,
    bufferManagerContext,
    logLevelContext
  }), [
    compositionManagerCtx,
    sequenceContext,
    setTimelineContext,
    timelineContext,
    canUseRemotionHooksContext,
    preloadContext,
    resolveCompositionContext,
    renderAssetManagerContext,
    sequenceManagerContext,
    sequenceManagerRefContext,
    visualModePropStatusesRefContext,
    bufferManagerContext,
    logLevelContext
  ]);
}
var RemotionContextProvider = (props2) => {
  const { children, contexts } = props2;
  return /* @__PURE__ */ jsx37(LogLevelContext.Provider, {
    value: contexts.logLevelContext,
    children: /* @__PURE__ */ jsx37(CanUseRemotionHooks.Provider, {
      value: contexts.canUseRemotionHooksContext,
      children: /* @__PURE__ */ jsx37(PreloadContext.Provider, {
        value: contexts.preloadContext,
        children: /* @__PURE__ */ jsx37(CompositionManager.Provider, {
          value: contexts.compositionManagerCtx,
          children: /* @__PURE__ */ jsx37(SequenceManagerRefContext.Provider, {
            value: contexts.sequenceManagerRefContext,
            children: /* @__PURE__ */ jsx37(SequenceManager.Provider, {
              value: contexts.sequenceManagerContext,
              children: /* @__PURE__ */ jsx37(VisualModePropStatusesRefContext.Provider, {
                value: contexts.visualModePropStatusesRefContext,
                children: /* @__PURE__ */ jsx37(RenderAssetManager.Provider, {
                  value: contexts.renderAssetManagerContext,
                  children: /* @__PURE__ */ jsx37(ResolveCompositionContext.Provider, {
                    value: contexts.resolveCompositionContext,
                    children: /* @__PURE__ */ jsx37(TimelineContext.Provider, {
                      value: contexts.timelineContext,
                      children: /* @__PURE__ */ jsx37(SetTimelineContext.Provider, {
                        value: contexts.setTimelineContext,
                        children: /* @__PURE__ */ jsx37(SequenceContext.Provider, {
                          value: contexts.sequenceContext,
                          children: /* @__PURE__ */ jsx37(BufferingContextReact.Provider, {
                            value: contexts.bufferManagerContext,
                            children
                          })
                        })
                      })
                    })
                  })
                })
              })
            })
          })
        })
      })
    })
  });
};

// src/internals.ts
var compositionSelectorRef = createRef3();
var Internals = {
  AbsoluteFillElement,
  MaxMediaCacheSizeContext,
  getMediabunnyInputResourceKey,
  globalMediaResourceManager,
  makeMediaResourceManager,
  MEDIABUNNY_DURATION_VALUE_KEY,
  makeRenderResourceManager,
  RenderResourceManagerContext,
  createRuntimeValueStore,
  useUnsafeVideoConfig,
  useFrameForVolumeProp,
  useTimelinePosition,
  useAbsoluteTimelinePosition,
  useIsInsideFreeze,
  useMediaAudioState,
  evaluateVolume,
  getAbsoluteSrc,
  getAnimatedImageDurationInSeconds,
  getAssetDisplayName,
  Timeline: exports_timeline_position_state,
  validateMediaTrimProps,
  validateMediaProps,
  resolveTrimProps,
  VideoForPreview,
  CompositionManager,
  CompositionSetters,
  VisualModePropStatusesContext,
  VisualModePropStatusesRefContext,
  VisualModeDragOverridesContext,
  VisualModeSettersContext,
  SequenceManager,
  SequenceManagerProvider,
  SequenceManagerRefContext,
  SequenceRegistrationContext,
  CommitOrderInternals,
  SequenceStackTracesUpdateContext,
  baseSchema,
  sequenceSchema,
  SequenceWithoutSchema,
  sequenceStyleSchema,
  sequenceVisualStyleSchema,
  sequencePremountSchema,
  sequenceCropSchema,
  textSchema,
  transformSchema,
  premountSchema,
  flattenActiveSchema,
  getFlatSchemaWithAllKeys,
  RemotionRootContexts,
  CompositionManagerProvider,
  useVideo,
  getRoot,
  useMediaVolumeState,
  usePlayerMutedState,
  useMediaInTimeline,
  useLazyComponent,
  truthy,
  SequenceContext,
  PremountContext,
  usePremounting,
  useRemotionContexts,
  RemotionContextProvider,
  CSSUtils: exports_default_css,
  setupEnvVariables,
  MediaVolumeContext,
  SetMediaVolumeContext,
  getRemotionEnvironment,
  SharedAudioContext,
  SharedAudioContextProvider,
  SharedAudioTagsContext,
  SharedAudioTagsContextProvider,
  invalidCompositionErrorMessage,
  invalidFolderNameErrorMessage,
  calculateMediaDuration,
  isCompositionIdValid,
  isFolderNameValid,
  getPreviewDomElement,
  compositionsRef,
  portalNode,
  setPortalNodeCurrentScale,
  waitForRoot,
  SetTimelineContext,
  CanUseRemotionHooksProvider,
  CanUseRemotionHooks,
  DisableInteractivityProvider,
  PrefetchProvider,
  DurationsContextProvider,
  IsPlayerContextProvider,
  useIsPlayer,
  EditorPropsProvider,
  EditorPropsContext,
  usePreload,
  resolveVideoConfig,
  resolveVideoConfigOrCatch,
  resolveVideoConfigWithMetadataOrCatch,
  ResolveCompositionContext,
  useResolvedVideoConfig,
  resolveCompositionsRef,
  REMOTION_STUDIO_CONTAINER_ELEMENT,
  RenderAssetManager,
  persistCurrentFrame,
  usePlaybackRate,
  useTimelineContext,
  useTimelineSetFrame,
  isIosSafari,
  WATCH_REMOTION_STATIC_FILES,
  addSequenceStackTraces,
  useMediaStartsAt,
  BufferingProvider,
  BufferingContextReact,
  getComponentsToAddStacksTo,
  getSequenceComponent,
  getSingleChildComponent,
  getStackForControls,
  REMOTION_INTERNAL_STACK_PROP,
  setComponentIdentityResolver,
  CurrentScaleContext,
  PixelDensityContext,
  PreviewSizeContext,
  calculateScale,
  validateRenderAsset,
  Log,
  LogLevelContext,
  useLogLevel,
  playbackLogging,
  timeValueRef,
  compositionSelectorRef,
  RemotionEnvironmentContext,
  warnAboutTooHighVolume,
  AudioForPreview,
  OBJECTFIT_CONTAIN_CLASS_NAME,
  InnerOffthreadVideo,
  useBasicMediaInTimeline,
  getInputPropsOverride,
  setInputPropsOverride,
  useVideoEnabled,
  useAudioEnabled,
  useBuffering,
  TimelinePosition: exports_timeline_position_state,
  DelayRenderContextType,
  TimelineContext,
  usePlaying,
  PlaybackRateContext,
  AbsoluteTimeContext,
  RenderAssetManagerProvider,
  getEffectiveVisualModeValue,
  CompositionRenderErrorContext,
  useEffectChainState,
  createEffectChainState,
  cleanupEffectChainState,
  runEffectChain,
  useMemoizedEffects,
  useMemoizedEffectDefinitions,
  createEffect,
  createWebGLContextError,
  createWebGL2ContextError,
  computeEffectiveSchemaValuesDotNotation,
  interpolateKeyframedStatus,
  makeStaticDragOverride,
  makeKeyframedDragOverride,
  resolveDragOverrideValue,
  getStaticDragOverrideValue,
  OverrideIdsToNodePathsGettersContext,
  OverrideIdsToNodePathsSettersContext,
  findPropsToDelete,
  makeSequencePropsSubscriptionKey,
  getPropStatusesCtx,
  getEffectPropStatusesCtx,
  hiddenField,
  durationInFramesField,
  freezeField,
  fromField,
  resolveSequenceCrop,
  useCropStyle
};
Object.assign(Internals, { useSyncExternalStore: useSyncExternalStore2 });
// src/font-face-registry.ts
var fontDataByUrl = new Map;
// src/series/index.tsx
import React45, {
  forwardRef as forwardRef14,
  useMemo as useMemo38
} from "react";

// src/series/flatten-children.tsx
import React44 from "react";
var flattenChildren = (children) => {
  const childrenArray = React44.Children.toArray(children);
  return childrenArray.reduce((flatChildren, child) => {
    if (child.type === React44.Fragment) {
      return flatChildren.concat(flattenChildren(child.props.children));
    }
    flatChildren.push(child);
    return flatChildren;
  }, []);
};

// src/series/index.tsx
import { jsx as jsx38, jsxs as jsxs3, Fragment } from "react/jsx-runtime";
var seriesSequenceSchema = {
  durationInFrames: Interactive.baseSchema.durationInFrames,
  name: Interactive.sequenceSchema.name,
  hidden: Interactive.sequenceSchema.hidden,
  showInTimeline: Interactive.sequenceSchema.showInTimeline,
  freeze: Interactive.baseSchema.freeze,
  trimBefore: Interactive.sequenceSchema.trimBefore,
  layout: Interactive.sequenceSchema.layout
};
var SeriesSequenceInner = forwardRef14(({ offset = 0, className = "", _remotionInternalRender = null, ...props2 }, ref) => {
  useRequireToBeInsideSeries();
  if (_remotionInternalRender) {
    return _remotionInternalRender({ ...props2, offset, className: className || undefined }, ref);
  }
  return /* @__PURE__ */ jsx38(IsNotInsideSeriesProvider, {
    children: props2.children
  });
});
var SeriesSequence = Interactive.withSchema({
  Component: SeriesSequenceInner,
  componentName: "<Series.Sequence>",
  componentIdentity: "dev.remotion.remotion.Series.Sequence",
  schema: seriesSequenceSchema,
  supportsEffects: false
});
var SequenceWithoutSchemaWithRef = SequenceWithoutSchema;
var validateSeriesSequenceProps = ({
  durationInFrames,
  offset: offsetProp,
  index,
  childrenLength
}) => {
  const debugInfo = `index = ${index}, duration = ${durationInFrames}`;
  if (index !== childrenLength - 1 || durationInFrames !== Infinity) {
    validateDurationInFrames(durationInFrames, {
      component: `of a <Series.Sequence /> component`,
      allowFloats: true
    });
  }
  const offset = offsetProp ?? 0;
  if (Number.isNaN(offset)) {
    throw new TypeError(`The "offset" property of a <Series.Sequence /> must not be NaN, but got NaN (${debugInfo}).`);
  }
  if (!Number.isFinite(offset)) {
    throw new TypeError(`The "offset" property of a <Series.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
  }
  if (offset % 1 !== 0) {
    throw new TypeError(`The "offset" property of a <Series.Sequence /> must be finite, but got ${offset} (${debugInfo}).`);
  }
  return offset;
};
var SeriesInner = (props2) => {
  const childrenValue = useMemo38(() => {
    const flattenedChildren = flattenChildren(props2.children);
    const renderChildren = (i, startFrame) => {
      if (i === flattenedChildren.length) {
        return null;
      }
      const child = flattenedChildren[i];
      const castedChild = child;
      if (typeof castedChild === "string") {
        if (castedChild.trim() === "") {
          return renderChildren(i + 1, startFrame);
        }
        throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as its children, but you passed a string "${castedChild}"`);
      }
      if (castedChild.type !== SeriesSequence) {
        throw new TypeError(`The <Series /> component only accepts a list of <Series.Sequence /> components as its children, but got ${castedChild} instead`);
      }
      const castedElement = castedChild;
      validateSeriesSequenceProps({
        durationInFrames: castedElement.props.durationInFrames,
        offset: castedElement.props.offset,
        index: i,
        childrenLength: flattenedChildren.length
      });
      return React45.cloneElement(castedElement, {
        _remotionInternalRender: (resolvedProps, ref) => {
          const durationInFramesProp = resolvedProps.durationInFrames;
          const {
            durationInFrames: _durationInFrames,
            children: sequenceChildren,
            offset: offsetProp,
            controls,
            from: _from,
            name,
            ...passedProps
          } = resolvedProps;
          const offset = validateSeriesSequenceProps({
            durationInFrames: durationInFramesProp,
            offset: offsetProp,
            index: i,
            childrenLength: flattenedChildren.length
          });
          const currentStartFrame = startFrame + offset;
          const nextStartFrame = startFrame + durationInFramesProp + offset;
          return /* @__PURE__ */ jsxs3(Fragment, {
            children: [
              /* @__PURE__ */ jsx38(SequenceWithoutSchemaWithRef, {
                ref,
                name: name || "<Series.Sequence>",
                _remotionInternalDocumentationLink: name ? undefined : "https://www.remotion.dev/docs/series",
                controls: controls ?? undefined,
                from: currentStartFrame,
                durationInFrames: durationInFramesProp,
                ...passedProps,
                _remotionInternalSingleChildComponent: getSingleChildComponent(sequenceChildren),
                children: /* @__PURE__ */ jsx38(IsNotInsideSeriesProvider, {
                  children: sequenceChildren
                })
              }),
              renderChildren(i + 1, nextStartFrame)
            ]
          });
        }
      });
    };
    return renderChildren(0, 0);
  }, [props2.children]);
  return /* @__PURE__ */ jsx38(Sequence, {
    layout: "none",
    name: "<Series>",
    _remotionInternalDocumentationLink: "https://www.remotion.dev/docs/series",
    ...props2,
    children: /* @__PURE__ */ jsx38(IsInsideSeriesContainer, {
      children: childrenValue
    })
  });
};
var Series = Object.assign(withInteractivitySchema({
  Component: SeriesInner,
  componentName: "<Series>",
  componentIdentity: "dev.remotion.remotion.Series",
  schema: sequenceSchemaDefaultLayoutNone,
  supportsEffects: false
}), {
  Sequence: SeriesSequence
});
addSequenceStackTraces(Series);
// src/static-file.ts
var problematicCharacters = {
  "%3A": ":",
  "%2F": "/",
  "%3F": "?",
  "%23": "#",
  "%5B": "[",
  "%5D": "]",
  "%40": "@",
  "%21": "!",
  "%24": "$",
  "%26": "&",
  "%27": "'",
  "%28": "(",
  "%29": ")",
  "%2A": "*",
  "%2B": "+",
  "%2C": ",",
  "%3B": ";"
};
var didWarn2 = {};
var warnOnce3 = (message) => {
  if (didWarn2[message]) {
    return;
  }
  console.warn(message);
  didWarn2[message] = true;
};
var includesHexOfUnsafeChar = (path) => {
  for (const key of Object.keys(problematicCharacters)) {
    if (path.includes(key)) {
      return { containsHex: true, hexCode: key };
    }
  }
  return { containsHex: false };
};
var trimLeadingSlash = (path) => {
  if (path.startsWith("/")) {
    return trimLeadingSlash(path.substring(1));
  }
  return path;
};
var inner = (path) => {
  if (typeof window !== "undefined" && window.remotion_staticBase) {
    if (path.startsWith(window.remotion_staticBase)) {
      throw new Error(`The value "${path}" is already prefixed with the static base ${window.remotion_staticBase}. You don't need to call staticFile() on it.`);
    }
    return `${window.remotion_staticBase}/${trimLeadingSlash(path)}`;
  }
  return `/${trimLeadingSlash(path)}`;
};
var encodeBySplitting = (path) => {
  const splitBySlash = path.split("/");
  const encodedArray = splitBySlash.map((element) => {
    return encodeURIComponent(element);
  });
  const merged = encodedArray.join("/");
  return merged;
};
var staticFile = (path) => {
  if (path === null) {
    throw new TypeError("null was passed to staticFile()");
  }
  if (typeof path === "undefined") {
    throw new TypeError("undefined was passed to staticFile()");
  }
  if (path.startsWith("http://") || path.startsWith("https://")) {
    throw new TypeError(`staticFile() does not support remote URLs - got "${path}". Instead, pass the URL without wrapping it in staticFile(). See: https://remotion.dev/docs/staticfile-remote-urls`);
  }
  if (path.startsWith("..") || path.startsWith("./")) {
    throw new TypeError(`staticFile() does not support relative paths - got "${path}". Instead, pass the name of a file that is inside the public/ folder. See: https://remotion.dev/docs/staticfile-relative-paths`);
  }
  if (path.startsWith("/Users") || path.startsWith("/home") || path.startsWith("/tmp") || path.startsWith("/etc") || path.startsWith("/opt") || path.startsWith("/var") || path.startsWith("C:") || path.startsWith("D:") || path.startsWith("E:")) {
    throw new TypeError(`staticFile() does not support absolute paths - got "${path}". Instead, pass the name of a file that is inside the public/ folder. See: https://remotion.dev/docs/staticfile-relative-paths`);
  }
  if (path.startsWith("public/")) {
    throw new TypeError(`Do not include the public/ prefix when using staticFile() - got "${path}". See: https://remotion.dev/docs/staticfile-relative-paths`);
  }
  const includesHex = includesHexOfUnsafeChar(path);
  if (includesHex.containsHex) {
    warnOnce3(`WARNING: You seem to pass an already encoded path (path contains ${includesHex.hexCode}). Since Remotion 4.0, the encoding is done by staticFile() itself. You may want to remove a encodeURIComponent() wrapping.`);
  }
  if (typeof window !== "undefined") {
    const matchingStaticFile = window.remotion_staticFiles?.find((file) => file.name === trimLeadingSlash(path));
    if (matchingStaticFile) {
      return matchingStaticFile.src;
    }
  }
  const preprocessed = encodeBySplitting(path);
  const preparsed = inner(preprocessed);
  if (!preparsed.startsWith("/")) {
    return `/${preparsed}`;
  }
  return preparsed;
};
// src/Still.tsx
import React46 from "react";
var Still = (props2) => {
  const newProps = {
    ...props2,
    durationInFrames: 1,
    fps: 1
  };
  return React46.createElement(Composition, newProps);
};
addSequenceStackTraces(Still);
// src/video/html5-video.tsx
import { forwardRef as forwardRef16, useCallback as useCallback27, useContext as useContext42 } from "react";

// src/video/VideoForRendering.tsx
import {
  forwardRef as forwardRef15,
  useContext as useContext41,
  useEffect as useEffect22,
  useImperativeHandle as useImperativeHandle10,
  useLayoutEffect as useLayoutEffect17,
  useMemo as useMemo39,
  useRef as useRef29
} from "react";

// src/video/seek-until-right.ts
var roundTo6Commas = (num) => {
  return Math.round(num * 1e5) / 1e5;
};
var seekToTime = ({
  element,
  desiredTime,
  logLevel,
  mountTime
}) => {
  if (isApproximatelyTheSame(element.currentTime, desiredTime)) {
    return {
      wait: Promise.resolve(desiredTime),
      cancel: () => {}
    };
  }
  seek({
    logLevel,
    mediaRef: element,
    time: desiredTime,
    why: "Seeking during rendering",
    mountTime
  });
  let cancel;
  let cancelSeeked = null;
  const prom = new Promise((resolve) => {
    cancel = element.requestVideoFrameCallback((now, metadata) => {
      const displayIn = metadata.expectedDisplayTime - now;
      if (displayIn <= 0) {
        resolve(metadata.mediaTime);
        return;
      }
      setTimeout(() => {
        resolve(metadata.mediaTime);
      }, displayIn + 150);
    });
  });
  const waitForSeekedEvent = new Promise((resolve) => {
    const onDone = () => {
      resolve();
    };
    element.addEventListener("seeked", onDone, {
      once: true
    });
    cancelSeeked = () => {
      element.removeEventListener("seeked", onDone);
    };
  });
  return {
    wait: Promise.all([prom, waitForSeekedEvent]).then(([time]) => time),
    cancel: () => {
      cancelSeeked?.();
      element.cancelVideoFrameCallback(cancel);
    }
  };
};
var seekToTimeMultipleUntilRight = ({
  element,
  desiredTime,
  fps,
  logLevel,
  mountTime
}) => {
  const threshold = 1 / fps / 2;
  let currentCancel = () => {
    return;
  };
  if (Number.isFinite(element.duration) && element.currentTime >= element.duration && desiredTime >= element.duration) {
    return {
      prom: Promise.resolve(),
      cancel: () => {}
    };
  }
  const prom = new Promise((resolve, reject) => {
    const firstSeek = seekToTime({
      element,
      desiredTime: desiredTime + threshold,
      logLevel,
      mountTime
    });
    firstSeek.wait.then((seekedTo) => {
      const difference = Math.abs(desiredTime - seekedTo);
      if (difference <= threshold) {
        return resolve();
      }
      const sign = desiredTime > seekedTo ? 1 : -1;
      const newSeek = seekToTime({
        element,
        desiredTime: seekedTo + threshold * sign,
        logLevel,
        mountTime
      });
      currentCancel = newSeek.cancel;
      newSeek.wait.then((newTime) => {
        const newDifference = Math.abs(desiredTime - newTime);
        if (roundTo6Commas(newDifference) <= roundTo6Commas(threshold)) {
          return resolve();
        }
        const thirdSeek = seekToTime({
          element,
          desiredTime: desiredTime + threshold,
          logLevel,
          mountTime
        });
        currentCancel = thirdSeek.cancel;
        return thirdSeek.wait.then(() => {
          resolve();
        }).catch((err) => {
          reject(err);
        });
      }).catch((err) => {
        reject(err);
      });
    });
    currentCancel = firstSeek.cancel;
  });
  return {
    prom,
    cancel: () => {
      currentCancel();
    }
  };
};

// src/video/VideoForRendering.tsx
import { jsx as jsx39 } from "react/jsx-runtime";
var VideoForRenderingForwardFunction = ({
  onError,
  volume: volumeProp,
  allowAmplificationDuringRender,
  playbackRate,
  onDuration,
  toneFrequency,
  name,
  acceptableTimeShiftInSeconds,
  delayRenderRetries,
  delayRenderTimeoutInMilliseconds,
  loopVolumeCurveBehavior,
  audioStreamIndex,
  onVideoFrame,
  preservePitch: _preservePitch,
  ...props2
}, ref) => {
  const absoluteFrame = useTimelinePosition();
  const frame = useCurrentFrame();
  const volumePropsFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
  const videoConfig = useUnsafeVideoConfig();
  const videoRef = useRef29(null);
  const sequenceContext = useContext41(SequenceContext);
  const mediaStartsAt = useMediaStartsAt();
  const environment = useRemotionEnvironment();
  const logLevel = useLogLevel();
  const mountTime = useMountTime();
  const { delayRender: delayRender2, continueRender: continueRender2 } = useDelayRender();
  const { registerRenderAsset, unregisterRenderAsset } = useContext41(RenderAssetManager);
  const id = useMemo39(() => `video-${random(props2.src ?? "")}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
    props2.src,
    sequenceContext?.cumulatedFrom,
    sequenceContext?.relativeFrom,
    sequenceContext?.durationInFrames
  ]);
  const volume = evaluateVolume({
    volume: volumeProp,
    frame: volumePropsFrame,
    mediaVolume: 1
  });
  warnAboutTooHighVolume(volume);
  const audioEnabled = useAudioEnabled();
  const { shouldUseAudio } = useMediaAudioState({
    muted: props2.muted ?? false,
    volume,
    audioEnabled
  });
  if (!videoConfig) {
    throw new Error("No video config found");
  }
  useEffect22(() => {
    if (!props2.src) {
      throw new Error("No src passed");
    }
    if (!shouldUseAudio) {
      return;
    }
    registerRenderAsset({
      type: "video",
      src: getAbsoluteSrc(props2.src),
      id,
      frame: absoluteFrame,
      volume,
      mediaFrame: frame,
      playbackRate: playbackRate ?? 1,
      toneFrequency: toneFrequency ?? 1,
      audioStartFrame: Math.max(0, -(sequenceContext?.cumulatedNegativeFrom ?? 0)),
      audioStreamIndex: audioStreamIndex ?? 0
    });
    return () => unregisterRenderAsset(id);
  }, [
    shouldUseAudio,
    props2.src,
    registerRenderAsset,
    id,
    unregisterRenderAsset,
    volume,
    frame,
    absoluteFrame,
    playbackRate,
    toneFrequency,
    sequenceContext?.cumulatedNegativeFrom,
    audioStreamIndex
  ]);
  useImperativeHandle10(ref, () => {
    return videoRef.current;
  }, []);
  useEmitVideoFrame({ ref: videoRef, onVideoFrame });
  useEffect22(() => {
    if (!window.remotion_videoEnabled) {
      return;
    }
    const { current } = videoRef;
    if (!current) {
      return;
    }
    const currentTime = getMediaTime({
      frame,
      playbackRate: playbackRate || 1,
      startFrom: -mediaStartsAt,
      fps: videoConfig.fps
    });
    const handle = delayRender2(`Rendering <Html5Video /> with src="${props2.src}" at time ${currentTime}`, {
      retries: delayRenderRetries ?? undefined,
      timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
    });
    if (window.process?.env?.NODE_ENV === "test") {
      continueRender2(handle);
      return;
    }
    if (isApproximatelyTheSame(current.currentTime, currentTime)) {
      if (current.readyState >= 2) {
        continueRender2(handle);
        return;
      }
      const loadedDataHandler = () => {
        continueRender2(handle);
      };
      current.addEventListener("loadeddata", loadedDataHandler, { once: true });
      return () => {
        current.removeEventListener("loadeddata", loadedDataHandler);
      };
    }
    const endedHandler = () => {
      continueRender2(handle);
    };
    const seek2 = seekToTimeMultipleUntilRight({
      element: current,
      desiredTime: currentTime,
      fps: videoConfig.fps,
      logLevel,
      mountTime
    });
    seek2.prom.then(() => {
      continueRender2(handle);
    });
    current.addEventListener("ended", endedHandler, { once: true });
    const errorHandler = () => {
      if (current?.error) {
        console.error("Error occurred in video", current?.error);
        if (onError) {
          return;
        }
        throw new MediaPlaybackError({
          message: `The browser threw an error while playing the video ${props2.src}: Code ${current.error.code} - ${current?.error?.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`,
          src: props2.src
        });
      } else {
        throw new MediaPlaybackError({
          message: "The browser threw an error",
          src: props2.src
        });
      }
    };
    current.addEventListener("error", errorHandler, { once: true });
    return () => {
      seek2.cancel();
      current.removeEventListener("ended", endedHandler);
      current.removeEventListener("error", errorHandler);
      continueRender2(handle);
    };
  }, [
    volumePropsFrame,
    props2.src,
    playbackRate,
    videoConfig.fps,
    frame,
    mediaStartsAt,
    onError,
    delayRenderRetries,
    delayRenderTimeoutInMilliseconds,
    logLevel,
    mountTime,
    continueRender2,
    delayRender2
  ]);
  const { src } = props2;
  if (environment.isRendering) {
    useLayoutEffect17(() => {
      if (window.process?.env?.NODE_ENV === "test") {
        return;
      }
      const newHandle = delayRender2("Loading <Html5Video> duration with src=" + src, {
        retries: delayRenderRetries ?? undefined,
        timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
      });
      const { current } = videoRef;
      const didLoad = () => {
        if (current?.duration) {
          onDuration(src, current.duration);
        }
        continueRender2(newHandle);
      };
      if (current?.duration) {
        onDuration(src, current.duration);
        continueRender2(newHandle);
      } else {
        current?.addEventListener("loadedmetadata", didLoad, { once: true });
      }
      return () => {
        current?.removeEventListener("loadedmetadata", didLoad);
        continueRender2(newHandle);
      };
    }, [
      src,
      onDuration,
      delayRenderRetries,
      delayRenderTimeoutInMilliseconds,
      continueRender2,
      delayRender2
    ]);
  }
  return /* @__PURE__ */ jsx39("video", {
    ref: videoRef,
    disableRemotePlayback: true,
    ...props2
  });
};
var VideoForRendering = forwardRef15(VideoForRenderingForwardFunction);

// src/video/html5-video.tsx
import { jsx as jsx40 } from "react/jsx-runtime";
var VideoForwardingFunction = (props2, ref) => {
  const {
    startFrom,
    endAt,
    trimBefore,
    trimAfter,
    name,
    pauseWhenBuffering,
    _remotionInternalStack,
    _remotionInternalNativeLoopPassed,
    showInTimeline,
    onAutoPlayError,
    onVideoFrame,
    ...otherProps
  } = props2;
  const { loop, ...propsOtherThanLoop } = props2;
  const { fps } = useVideoConfig();
  const environment = useRemotionEnvironment();
  const shouldPauseWhenBuffering = resolveV5Default(pauseWhenBuffering);
  if (environment.isClientSideRendering) {
    throw new Error("<Html5Video> is not supported in @remotion/web-renderer. Use <Video> from @remotion/media instead. See https://remotion.dev/docs/client-side-rendering/limitations");
  }
  const { durations, setDurations } = useContext42(DurationsContext);
  if (typeof ref === "string") {
    throw new Error("string refs are not supported");
  }
  if (typeof props2.src !== "string") {
    throw new TypeError(`The \`<Html5Video>\` tag requires a string for \`src\`, but got ${JSON.stringify(props2.src)} instead.`);
  }
  const preloadedSrc = usePreload(props2.src);
  const onDuration = useCallback27((src, durationInSeconds) => {
    setDurations({ type: "got-duration", durationInSeconds, src });
  }, [setDurations]);
  const durationFetched = durations[getAbsoluteSrc(preloadedSrc)] ?? durations[getAbsoluteSrc(props2.src)];
  validateMediaTrimProps({ startFrom, endAt, trimBefore, trimAfter });
  const { trimBeforeValue, trimAfterValue } = resolveTrimProps({
    startFrom,
    endAt,
    trimBefore,
    trimAfter
  });
  if (loop && durationFetched !== undefined) {
    if (!Number.isFinite(durationFetched)) {
      return /* @__PURE__ */ jsx40(Html5Video, {
        ...propsOtherThanLoop,
        ref,
        _remotionInternalStack,
        _remotionInternalNativeLoopPassed: true
      });
    }
    const mediaDuration = durationFetched * fps;
    return /* @__PURE__ */ jsx40(Loop, {
      durationInFrames: calculateMediaDuration({
        trimAfter: trimAfterValue,
        mediaDurationInFrames: mediaDuration,
        playbackRate: props2.playbackRate ?? 1,
        trimBefore: trimBeforeValue
      }),
      layout: "none",
      name,
      showInTimeline: false,
      children: /* @__PURE__ */ jsx40(Html5Video, {
        ...propsOtherThanLoop,
        ref,
        _remotionInternalStack,
        _remotionInternalNativeLoopPassed: true
      })
    });
  }
  if (typeof trimBeforeValue !== "undefined" || typeof trimAfterValue !== "undefined") {
    return /* @__PURE__ */ jsx40(Sequence, {
      layout: "none",
      from: 0 - (trimBeforeValue ?? 0),
      showInTimeline: false,
      durationInFrames: trimAfterValue === undefined ? undefined : trimAfterValue / (props2.playbackRate ?? 1),
      name,
      children: /* @__PURE__ */ jsx40(Html5Video, {
        pauseWhenBuffering: shouldPauseWhenBuffering,
        onVideoFrame,
        ...otherProps,
        ref,
        _remotionInternalStack
      })
    });
  }
  validateMediaProps({
    playbackRate: props2.playbackRate,
    preservePitch: props2.preservePitch,
    volume: props2.volume
  }, "Html5Video");
  if (environment.isRendering) {
    return /* @__PURE__ */ jsx40(VideoForRendering, {
      onDuration,
      onVideoFrame: onVideoFrame ?? null,
      ...otherProps,
      ref
    });
  }
  return /* @__PURE__ */ jsx40(VideoForPreview, {
    onlyWarnForMediaSeekingError: false,
    ...otherProps,
    ref,
    onVideoFrame: onVideoFrame ?? null,
    pauseWhenBuffering: shouldPauseWhenBuffering,
    onDuration,
    _remotionInternalStack: _remotionInternalStack ?? null,
    _remotionInternalNativeLoopPassed: _remotionInternalNativeLoopPassed ?? false,
    showInTimeline: showInTimeline ?? true,
    onAutoPlayError: onAutoPlayError ?? undefined
  });
};
var Html5Video = forwardRef16(VideoForwardingFunction);
addSequenceStackTraces(Html5Video);
var Video = Html5Video;
// src/index.ts
checkMultipleRemotionVersions();
var Experimental = {
  Clipper,
  Null,
  useIsPlayer
};
var proxyObj = {};
var Config = new Proxy(proxyObj, {
  get(_, prop) {
    if (prop === "Bundling" || prop === "Rendering" || prop === "Log" || prop === "Puppeteer" || prop === "Output") {
      return Config;
    }
    return () => {
      console.warn("⚠️  The CLI configuration has been extracted from Remotion Core.");
      console.warn("Update the import from the config file:");
      console.warn();
      console.warn("- Delete:");
      console.warn('import {Config} from "remotion";');
      console.warn("+ Replace:");
      console.warn('import {Config} from "@remotion/cli/config";');
      console.warn();
      console.warn("For more information, see https://www.remotion.dev/docs/4-0-migration.");
      process.exit(1);
    };
  }
});
Sequence.displayName = "Sequence";
addSequenceStackTraces(Sequence);
setSequenceComponent(Sequence);
addSequenceStackTraces(Composition);
addSequenceStackTraces(Folder);
export {
  watchStaticFile,
  useVideoConfig,
  useRemotionEnvironment,
  usePixelDensity,
  useDelayRender,
  useCurrentScale,
  useCurrentFrame,
  useBufferState,
  staticFile,
  spring,
  registerRoot,
  random,
  prefetch,
  measureSpring,
  isHtmlInCanvasSupported,
  interpolateColors,
  interpolate,
  getStaticFiles,
  getRemotionEnvironment,
  getInputProps,
  delayRender,
  createEffect,
  continueRender,
  cancelRender,
  assertValidInterpolatePosterizeOption,
  assertValidInterpolateEasingOption,
  absoluteFillSchema,
  Video,
  VERSION,
  Still,
  Solid,
  Series,
  Sequence,
  OffthreadVideo,
  MediaPlaybackError,
  Loop,
  Internals,
  Interactive,
  Img,
  IFrame,
  HtmlInCanvas,
  Html5Video,
  Html5Audio,
  HTML_IN_CANVAS_UNSUPPORTED_MESSAGE,
  Freeze,
  FolderContext,
  Folder,
  Experimental,
  Easing,
  Config,
  Composition,
  CanvasImage,
  Audio,
  Artifact,
  AnimatedImage,
  AbsoluteFill
};