UNPKG

remotion

Version:

Make videos programmatically

1,567 lines (1,526 loc) • 242 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/enable-sequence-stack-traces.ts import React 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 }; }; // src/enable-sequence-stack-traces.ts var originalCreateElement = React.createElement; var componentsToAddStacksTo = []; var enableSequenceStackTraces = () => { if (!getRemotionEnvironment().isStudio) { return; } const proxy = new Proxy(originalCreateElement, { apply(target, thisArg, argArray) { if (componentsToAddStacksTo.includes(argArray[0])) { const [first, props, ...rest] = argArray; const newProps = { ...props ?? {}, stack: new Error().stack }; return Reflect.apply(target, thisArg, [first, newProps, ...rest]); } return Reflect.apply(target, thisArg, argArray); } }); React.createElement = proxy; }; var addSequenceStackTraces = (component) => { componentsToAddStacksTo.push(component); enableSequenceStackTraces(); }; // src/is-player.tsx import { createContext as createContext2, useContext } from "react"; import { jsx } from "react/jsx-runtime"; var IsPlayerContext = createContext2(false); var IsPlayerContextProvider = ({ children }) => { return /* @__PURE__ */ jsx(IsPlayerContext.Provider, { value: true, children }); }; var useIsPlayer = () => { return useContext(IsPlayerContext); }; // src/truthy.ts function truthy(value) { return Boolean(value); } // src/version.ts var VERSION = "4.0.331"; // 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 forwardRef2, useContext as useContext10, useEffect as useEffect3, useMemo as useMemo9, useState as useState4 } from "react"; // src/AbsoluteFill.tsx import { forwardRef, useMemo } from "react"; import { jsx as jsx2 } 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 AbsoluteFillRefForwarding = (props, ref) => { const { style, ...other } = props; const actualStyle = useMemo(() => { 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__ */ jsx2("div", { ref, style: actualStyle, ...other }); }; var AbsoluteFill = forwardRef(AbsoluteFillRefForwarding); // src/SequenceContext.tsx import { createContext as createContext3 } from "react"; var SequenceContext = createContext3(null); // src/SequenceManager.tsx import React3, { useCallback, useMemo as useMemo2, useState } from "react"; import { jsx as jsx3 } from "react/jsx-runtime"; var SequenceManager = React3.createContext({ registerSequence: () => { throw new Error("SequenceManagerContext not initialized"); }, unregisterSequence: () => { throw new Error("SequenceManagerContext not initialized"); }, sequences: [] }); var SequenceVisibilityToggleContext = React3.createContext({ hidden: {}, setHidden: () => { throw new Error("SequenceVisibilityToggle not initialized"); } }); var SequenceManagerProvider = ({ children }) => { const [sequences, setSequences] = useState([]); const [hidden, setHidden] = useState({}); const registerSequence = useCallback((seq) => { setSequences((seqs) => { return [...seqs, seq]; }); }, []); const unregisterSequence = useCallback((seq) => { setSequences((seqs) => seqs.filter((s) => s.id !== seq)); }, []); const sequenceContext = useMemo2(() => { return { registerSequence, sequences, unregisterSequence }; }, [registerSequence, sequences, unregisterSequence]); const hiddenContext = useMemo2(() => { return { hidden, setHidden }; }, [hidden]); return /* @__PURE__ */ jsx3(SequenceManager.Provider, { value: sequenceContext, children: /* @__PURE__ */ jsx3(SequenceVisibilityToggleContext.Provider, { value: hiddenContext, children }) }); }; // src/nonce.ts import { createContext as createContext4, useContext as useContext2, useEffect, useRef, useState as useState2 } from "react"; var NonceContext = createContext4({ getNonce: () => 0, fastRefreshes: 0, manualRefreshes: 0 }); var SetNonceContext = createContext4({ increaseManualRefreshes: () => {} }); var useNonce = () => { const context = useContext2(NonceContext); const [nonce, setNonce] = useState2(() => context.getNonce()); const lastContext = useRef(context); useEffect(() => { if (lastContext.current === context) { return; } lastContext.current = context; setNonce(context.getNonce); }, [context]); return nonce; }; // src/timeline-position-state.ts var exports_timeline_position_state = {}; __export(exports_timeline_position_state, { useTimelineSetFrame: () => useTimelineSetFrame, useTimelinePosition: () => useTimelinePosition, usePlayingState: () => usePlayingState, persistCurrentFrame: () => persistCurrentFrame, getInitialFrameState: () => getInitialFrameState, getFrameForComposition: () => getFrameForComposition, TimelineContext: () => TimelineContext, SetTimelineContext: () => SetTimelineContext }); import { createContext as createContext8, useContext as useContext5, useMemo as useMemo6 } from "react"; // src/use-video.ts import { useContext as useContext4, useMemo as useMemo5 } from "react"; // src/CompositionManagerContext.tsx import { createContext as createContext5 } from "react"; var CompositionManager = createContext5({ compositions: [], folders: [], currentCompositionMetadata: null, canvasContent: null }); var CompositionSetters = createContext5({ registerComposition: () => { return; }, unregisterComposition: () => { return; }, registerFolder: () => { return; }, unregisterFolder: () => { return; }, setCanvasContent: () => { return; }, updateCompositionDefaultProps: () => { return; }, onlyRenderComposition: null }); // src/ResolveCompositionConfig.tsx import { createContext as createContext7, createRef, useCallback as useCallback3, useContext as useContext3, useEffect as useEffect2, useImperativeHandle as useImperativeHandle2, useMemo as useMemo4, useState as useState3 } from "react"; // src/EditorProps.tsx import React4, { createContext as createContext6, useCallback as useCallback2, useImperativeHandle, useMemo as useMemo3 } from "react"; import { jsx as jsx4 } from "react/jsx-runtime"; var EditorPropsContext = createContext6({ props: {}, updateProps: () => { throw new Error("Not implemented"); }, resetUnsaved: () => { throw new Error("Not implemented"); } }); var editorPropsProviderRef = React4.createRef(); var timeValueRef = React4.createRef(); var EditorPropsProvider = ({ children }) => { const [props, setProps] = React4.useState({}); const updateProps = useCallback2(({ defaultProps, id, newProps }) => { setProps((prev) => { return { ...prev, [id]: typeof newProps === "function" ? newProps(prev[id] ?? defaultProps) : newProps }; }); }, []); const resetUnsaved = useCallback2((compositionId) => { setProps((prev) => { if (prev[compositionId]) { const newProps = { ...prev }; delete newProps[compositionId]; return newProps; } return prev; }); }, []); useImperativeHandle(editorPropsProviderRef, () => { return { getProps: () => props, setProps }; }, [props]); const ctx = useMemo3(() => { return { props, updateProps, resetUnsaved }; }, [props, resetUnsaved, updateProps]); return /* @__PURE__ */ jsx4(EditorPropsContext.Provider, { value: ctx, children }); }; // 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 && 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 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 `${window.remotion_staticBase}/${value.replace(FILE_TOKEN, "")}`; } 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/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 param = window.remotion_inputProps; if (!param) { return {}; } const parsed = deserializeJSONWithSpecialTypes(param); return parsed; }; // src/codec.ts var validCodecs = [ "h264", "h265", "vp8", "vp9", "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/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/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; return { width, height, fps, durationInFrames, defaultCodec, defaultOutName, defaultVideoImageFormat, defaultPixelFormat }; }; var resolveVideoConfig = ({ calculateMetadata, signal, defaultProps, originalProps, compositionId, compositionDurationInFrames, compositionFps, compositionHeight, compositionWidth }) => { const calculatedProm = calculateMetadata ? calculateMetadata({ defaultProps, props: originalProps, abortSignal: signal, compositionId }) : null; if (calculatedProm !== null && typeof calculatedProm === "object" && "then" in calculatedProm) { return calculatedProm.then((c) => { const { height, width, durationInFrames, fps, defaultCodec, defaultOutName, defaultVideoImageFormat, defaultPixelFormat } = validateCalculated({ calculated: c, compositionDurationInFrames, compositionFps, compositionHeight, compositionWidth, compositionId }); return { width, height, fps, durationInFrames, id: compositionId, defaultProps: serializeThenDeserializeInStudio(defaultProps), props: serializeThenDeserializeInStudio(c.props ?? originalProps), defaultCodec: defaultCodec ?? null, defaultOutName: defaultOutName ?? null, defaultVideoImageFormat: defaultVideoImageFormat ?? null, defaultPixelFormat: defaultPixelFormat ?? null }; }); } const data = validateCalculated({ calculated: calculatedProm, compositionDurationInFrames, compositionFps, compositionHeight, compositionWidth, compositionId }); if (calculatedProm === null) { return { ...data, id: compositionId, defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}), props: serializeThenDeserializeInStudio(originalProps), defaultCodec: null, defaultOutName: null, defaultVideoImageFormat: null, defaultPixelFormat: null }; } return { ...data, id: compositionId, defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}), props: serializeThenDeserializeInStudio(calculatedProm.props ?? originalProps), defaultCodec: calculatedProm.defaultCodec ?? null, defaultOutName: calculatedProm.defaultOutName ?? null, defaultVideoImageFormat: calculatedProm.defaultVideoImageFormat ?? null, defaultPixelFormat: calculatedProm.defaultPixelFormat ?? null }; }; var resolveVideoConfigOrCatch = (params) => { try { const promiseOrReturnValue = resolveVideoConfig(params); return { type: "success", result: promiseOrReturnValue }; } catch (err) { return { type: "error", error: err }; } }; // src/ResolveCompositionConfig.tsx import { jsx as jsx5 } from "react/jsx-runtime"; var ResolveCompositionContext = createContext7(null); var resolveCompositionsRef = createRef(); var needsResolution = (composition) => { return Boolean(composition.calculateMetadata); }; var PROPS_UPDATED_EXTERNALLY = "remotion.propsUpdatedExternally"; var ResolveCompositionConfig = ({ children }) => { const [currentRenderModalComposition, setCurrentRenderModalComposition] = useState3(null); const { compositions, canvasContent, currentCompositionMetadata } = useContext3(CompositionManager); const { fastRefreshes, manualRefreshes } = useContext3(NonceContext); if (manualRefreshes) {} const selectedComposition = useMemo4(() => { return compositions.find((c) => canvasContent && canvasContent.type === "composition" && canvasContent.compositionId === c.id); }, [canvasContent, compositions]); const renderModalComposition = compositions.find((c) => c.id === currentRenderModalComposition); const { props: allEditorProps } = useContext3(EditorPropsContext); const inputProps = useMemo4(() => { return typeof window === "undefined" || getRemotionEnvironment().isPlayer ? {} : getInputProps() ?? {}; }, []); const [resolvedConfigs, setResolvedConfigs] = useState3({}); const selectedEditorProps = useMemo4(() => { return selectedComposition ? allEditorProps[selectedComposition.id] ?? {} : {}; }, [allEditorProps, selectedComposition]); const renderModalProps = useMemo4(() => { return renderModalComposition ? allEditorProps[renderModalComposition.id] ?? {} : {}; }, [allEditorProps, renderModalComposition]); const hasResolution = Boolean(currentCompositionMetadata); const doResolution = useCallback3(({ calculateMetadata, combinedProps, compositionDurationInFrames, compositionFps, compositionHeight, compositionId, compositionWidth, defaultProps }) => { const controller = new AbortController; if (hasResolution) { return controller; } const { signal } = controller; const result = resolveVideoConfigOrCatch({ compositionId, calculateMetadata, originalProps: combinedProps, signal, defaultProps, compositionDurationInFrames, compositionFps, compositionHeight, compositionWidth }); if (result.type === "error") { setResolvedConfigs((r) => ({ ...r, [compositionId]: { type: "error", error: result.error } })); return controller; } const promOrNot = result.result; if (typeof promOrNot === "object" && "then" in promOrNot) { setResolvedConfigs((r) => { const prev = r[compositionId]; if (prev?.type === "success" || prev?.type === "success-and-refreshing") { return { ...r, [compositionId]: { type: "success-and-refreshing", result: prev.result } }; } return { ...r, [compositionId]: { type: "loading" } }; }); promOrNot.then((c) => { if (controller.signal.aborted) { return; } setResolvedConfigs((r) => ({ ...r, [compositionId]: { type: "success", result: c } })); }).catch((err) => { if (controller.signal.aborted) { return; } setResolvedConfigs((r) => ({ ...r, [compositionId]: { type: "error", error: err } })); }); } else { setResolvedConfigs((r) => ({ ...r, [compositionId]: { type: "success", result: promOrNot } })); } return controller; }, [hasResolution]); const currentComposition = canvasContent?.type === "composition" ? canvasContent.compositionId : null; useImperativeHandle2(resolveCompositionsRef, () => { return { setCurrentRenderModalComposition: (id) => { setCurrentRenderModalComposition(id); }, reloadCurrentlySelectedComposition: () => { if (!currentComposition) { return; } const composition = compositions.find((c) => c.id === currentComposition); if (!composition) { throw new Error(`Could not find composition with id ${currentComposition}`); } const editorProps = allEditorProps[currentComposition] ?? {}; const defaultProps = { ...composition.defaultProps ?? {}, ...editorProps ?? {} }; const props = { ...defaultProps, ...inputProps ?? {} }; doResolution({ defaultProps, calculateMetadata: composition.calculateMetadata, combinedProps: props, compositionDurationInFrames: composition.durationInFrames ?? null, compositionFps: composition.fps ?? null, compositionHeight: composition.height ?? null, compositionWidth: composition.width ?? null, compositionId: composition.id }); } }; }, [ allEditorProps, compositions, currentComposition, doResolution, inputProps ]); const isTheSame = selectedComposition?.id === renderModalComposition?.id; const currentDefaultProps = useMemo4(() => { return { ...selectedComposition?.defaultProps ?? {}, ...selectedEditorProps ?? {} }; }, [selectedComposition?.defaultProps, selectedEditorProps]); const originalProps = useMemo4(() => { return { ...currentDefaultProps, ...inputProps ?? {} }; }, [currentDefaultProps, inputProps]); const canResolve = selectedComposition && needsResolution(selectedComposition); const shouldIgnoreUpdate = typeof window !== "undefined" && window.remotion_ignoreFastRefreshUpdate && fastRefreshes <= window.remotion_ignoreFastRefreshUpdate; useEffect2(() => { if (shouldIgnoreUpdate) { return; } if (canResolve) { const controller = doResolution({ calculateMetadata: selectedComposition.calculateMetadata, combinedProps: originalProps, compositionDurationInFrames: selectedComposition.durationInFrames ?? null, compositionFps: selectedComposition.fps ?? null, compositionHeight: selectedComposition.height ?? null, compositionWidth: selectedComposition.width ?? null, defaultProps: currentDefaultProps, compositionId: selectedComposition.id }); return () => { controller.abort(); }; } }, [ canResolve, currentDefaultProps, doResolution, originalProps, selectedComposition?.calculateMetadata, selectedComposition?.durationInFrames, selectedComposition?.fps, selectedComposition?.height, selectedComposition?.id, selectedComposition?.width, shouldIgnoreUpdate ]); useEffect2(() => { if (renderModalComposition && !isTheSame) { const combinedProps = { ...renderModalComposition.defaultProps ?? {}, ...renderModalProps ?? {}, ...inputProps ?? {} }; const controller = doResolution({ calculateMetadata: renderModalComposition.calculateMetadata, compositionDurationInFrames: renderModalComposition.durationInFrames ?? null, compositionFps: renderModalComposition.fps ?? null, compositionHeight: renderModalComposition.height ?? null, compositionId: renderModalComposition.id, compositionWidth: renderModalComposition.width ?? null, defaultProps: currentDefaultProps, combinedProps }); return () => { controller.abort(); }; } }, [ currentDefaultProps, doResolution, inputProps, isTheSame, renderModalComposition, renderModalProps ]); const resolvedConfigsIncludingStaticOnes = useMemo4(() => { const staticComps = compositions.filter((c) => { return c.calculateMetadata === null; }); return { ...resolvedConfigs, ...staticComps.reduce((acc, curr) => { return { ...acc, [curr.id]: { type: "success", result: { ...curr, defaultProps: curr.defaultProps ?? {} } } }; }, {}) }; }, [compositions, resolvedConfigs]); return /* @__PURE__ */ jsx5(ResolveCompositionContext.Provider, { value: resolvedConfigsIncludingStaticOnes, children }); }; var useResolvedVideoConfig = (preferredCompositionId) => { const context = useContext3(ResolveCompositionContext); const { props: allEditorProps } = useContext3(EditorPropsContext); const { compositions, canvasContent, currentCompositionMetadata } = useContext3(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]); return useMemo4(() => { if (!composition) { return null; } if (currentCompositionMetadata) { return { type: "success", 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", 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" || getRemotionEnvironment().isPlayer ? {} : getInputProps() ?? {} }, defaultCodec: null, defaultOutName: null, defaultVideoImageFormat: null, defaultPixelFormat: null } }; } if (!context[composition.id]) { return null; } return context[composition.id]; }, [composition, context, currentCompositionMetadata, selectedEditorProps]); }; // src/use-video.ts var useVideo = () => { const { canvasContent, compositions, currentCompositionMetadata } = useContext4(CompositionManager); const selected = compositions.find((c) => { return canvasContent?.type === "composition" && c.id === canvasContent.compositionId; }); const resolved = useResolvedVideoConfig(selected?.id ?? null); return useMemo5(() => { 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 }; }, [currentCompositionMetadata, resolved, selected]); }; // src/timeline-position-state.ts var TimelineContext = createContext8({ frame: {}, playing: false, playbackRate: 1, rootId: "", imperativePlaying: { current: false }, setPlaybackRate: () => { throw new Error("default"); }, audioAndVideoTags: { current: [] } }); var SetTimelineContext = createContext8({ setFrame: () => { throw new Error("default"); }, setPlaying: () => { throw new Error("default"); } }); 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 useTimelinePosition = () => { const videoConfig = useVideo(); const state = useContext5(TimelineContext); if (!videoConfig) { return typeof window === "undefined" ? 0 : window.remotion_initialFrame ?? 0; } const unclamped = state.frame[videoConfig.id] ?? (getRemotionEnvironment().isPlayer ? 0 : getFrameForComposition(videoConfig.id)); return Math.min(videoConfig.durationInFrames - 1, unclamped); }; var useTimelineSetFrame = () => { const { setFrame } = useContext5(SetTimelineContext); return setFrame; }; var usePlayingState = () => { const { playing, imperativePlaying } = useContext5(TimelineContext); const { setPlaying } = useContext5(SetTimelineContext); return useMemo6(() => [playing, setPlaying, imperativePlaying], [imperativePlaying, playing, setPlaying]); }; // src/use-video-config.ts import { useContext as useContext7 } from "react"; // src/CanUseRemotionHooks.tsx import { createContext as createContext9 } from "react"; import { jsx as jsx6 } from "react/jsx-runtime"; var CanUseRemotionHooks = createContext9(false); var CanUseRemotionHooksProvider = ({ children }) => { return /* @__PURE__ */ jsx6(CanUseRemotionHooks.Provider, { value: true, children }); }; // src/use-unsafe-video-config.ts import { useContext as useContext6, useMemo as useMemo7 } from "react"; 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 useMemo7(() => { if (!video) { return null; } const { id, durationInFrames, fps, height, width, defaultProps, props, defaultCodec, defaultOutName, defaultVideoImageFormat, defaultPixelFormat } = video; return { id, width: ctxWidth ?? width, height: ctxHeight ?? height, fps, durationInFrames: ctxDuration ?? durationInFrames, defaultProps, props, defaultCodec, defaultOutName, defaultVideoImageFormat, defaultPixelFormat }; }, [ctxDuration, ctxHeight, ctxWidth, video]); }; // src/use-video-config.ts var useVideoConfig = () => { const videoConfig = useUnsafeVideoConfig(); const context = useContext7(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 { useContext as useContext9, useMemo as useMemo8 } from "react"; // src/use-current-frame.ts import { useContext as useContext8 } from "react"; var useCurrentFrame = () => { const canUseRemotionHooks = useContext8(CanUseRemotionHooks); if (!canUseRemotionHooks) { if (getRemotionEnvironment().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 = useContext8(SequenceContext); const contextOffset = context ? context.cumulatedFrom + context.relativeFrom : 0; return frame - contextOffset; }; // src/freeze.tsx import { jsx as jsx7 } 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 = useMemo8(() => { if (typeof active === "boolean") { return active; } if (typeof active === "function") { return active(frame); } }, [active, frame]); const timelineContext = useContext9(TimelineContext); const sequenceContext = useContext9(SequenceContext); const relativeFrom = sequenceContext?.relativeFrom ?? 0; const timelineValue = useMemo8(() => { if (!isActive) { return timelineContext; } return { ...timelineContext, playing: false, imperativePlaying: { current: false }, frame: { [videoConfig.id]: frameToFreeze + relativeFrom } }; }, [isActive, timelineContext, videoConfig.id, frameToFreeze, relativeFrom]); return /* @__PURE__ */ jsx7(TimelineContext.Provider, { value: timelineValue, children }); }; // src/Sequence.tsx import { jsx as jsx8 } from "react/jsx-runtime"; var RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Infinity, children, name, height, width, showInTimeline = true, _remotionInternalLoopDisplay: loopDisplay, _remotionInternalStack: stack, _remotionInternalPremountDisplay: premountDisplay, ...other }, ref) => { const { layout = "absolute-fill" } = other; const [id] = useState4(() => String(Math.random())); const parentSequence = useContext10(SequenceContext); const { rootId } = useContext10(TimelineContext); const cumulatedFrom = parentSequence ? parentSequence.cumulatedFrom + parentSequence.relativeFrom : 0; const nonce = useNonce(); if (layout !== "absolute-fill" && layout !== "none") { throw new TypeError(`The layout prop of <Sequence /> expects either "absolute-fill" or "none", but you passed: ${layout}`); } if (layout === "none" && typeof other.style !== "undefined") { throw new TypeError('If layout="none", you may not pass a 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}.`); } const absoluteFrame = useTimelinePosition(); const videoConfig = useVideoConfig(); const parentSequenceDuration = parentSequence ? Math.min(parentSequence.durationInFrames - from, durationInFrames) : durationInFrames; const actualDurationInFrames = Math.max(0, Math.min(videoConfig.durationInFrames - from, parentSequenceDuration)); const { registerSequence, unregisterSequence } = useContext10(SequenceManager); const { hidden } = useContext10(SequenceVisibilityToggleContext); const premounting = useMemo9(() => { return parentSequence?.premounting || Boolean(other._remotionInternalIsPremounting); }, [other._remotionInternalIsPremounting, parentSequence?.premounting]); const contextValue = useMemo9(() => { return { cumulatedFrom, relativeFrom: from, durationInFrames: actualDurationInFrames, parentFrom: parentSequence?.relativeFrom ?? 0, id, height: height ?? parentSequence?.height ?? null, width: width ?? parentSequence?.width ?? null, premounting }; }, [ cumulatedFrom, from, actualDurationInFrames, parentSequence, id, height, width, premounting ]); const timelineClipName = useMemo9(() => { return name ?? ""; }, [name]); useEffect3(() => { if (!getRemotionEnvironment().isStudio) { return; } registerSequence({ from, duration: actualDurationInFrames, id, displayName: timelineClipName, parent: parentSequence?.id ?? null, type: "sequence", rootId, showInTimeline, nonce, loopDisplay, stack: stack ?? null, premountDisplay: premountDisplay ?? null }); return () => { unregisterSequence(id); }; }, [ durationInFrames, id, name, registerSequence, timelineClipName, unregisterSequence, parentSequence?.id, actualDurationInFrames, rootId, from, showInTimeline, nonce, loopDisplay, stack, premountDisplay ]); const endThreshold = Math.ceil(cumulatedFrom + from + durationInFrames - 1); const content = absoluteFrame < cumulatedFrom + from ? null : absoluteFrame > endThreshold ? null : children; const styleIfThere = other.layout === "none" ? undefined : other.style; const defaultStyle = useMemo9(() => { return { flexDirection: undefined, ...width ? { width } : {}, ...height ? { height } : {}, ...styleIfThere ?? {} }; }, [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 />.'); } const isSequenceHidden = hidden[id] ?? false; if (isSequenceHidden) { return null; } return /* @__PURE__ */ jsx8(SequenceContext.Provider, { value: contextValue, children: content === null ? null : other.layout === "none" ? content : /* @__PURE__ */ jsx8(AbsoluteFill, { ref, style: defaultStyle, className: other.className, children: content }) }); }; var RegularSequence = forwardRef2(RegularSequenceRefForwardingFunction); var PremountedSequenceRefForwardingFunction = (props, ref) => { const frame = useCurrentFrame(); if (props.layout === "none") { throw new Error('`<Sequence>` with `premountFor` prop does not support layout="none"'); } const { style: passedStyle, from = 0, premountFor = 0, styleWhilePremounted, ...otherProps } = props; const premountingActive = frame < from && frame >= from - premountFor; const style = useMemo9(() => { return { ...passedStyle, opacity: premountingActive ? 0 : 1, pointerEvents: premountingActive ? "none" : passedStyle?.pointerEvents ?? undefined, ...premountingActive ? styleWhilePremounted : {} }; }, [passedStyle, premountingActive, styleWhilePremounted]); return /* @__PURE__ */ jsx8(Freeze, { frame: from, active: premountingActive, children: /* @__PURE__ */ jsx8(Sequence, { ref, from, style, _remotionInternalPremountDisplay: premountFor, _remotionInternalIsPremounting: premountingActive, ...otherProps }) }); }; var PremountedSequence = forwardRef2(PremountedSequenceRefForwardingFunction); var SequenceRefForwardingFunction = (props, ref) => { if (props.layout !== "none" && props.premountFor && !getRemotionEnvironment().isRendering) { return /* @__PURE__ */ jsx8(PremountedSequence, { ...props, ref }); } return /* @__PURE__ */ jsx8(RegularSequence, { ...props, ref }); }; var Sequence = forwardRef2(SequenceRefForwardingFunction); // src/animated-image/AnimatedImage.tsx import { forwardRef as forwardRef3, useEffect as useEffect4, useImperativeHandle as useImperativeHandle4, useLayoutEffect, useRef as useRef3, useState as useState5 } from "react"; // src/cancel-render.ts 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 cancelRender(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"); } window.remotion_cancelledError = error.stack; throw error; } // 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 Log = { trace: (logLevel, ...args) => { if (isEqualOrBelowLogLevel(logLevel, "trace")) { return console.log(...args); } }, verbose: (