UNPKG

@remotion/studio

Version:

APIs for interacting with the Remotion Studio

341 lines (340 loc) 17.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.setBundleModeAndUpdate = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); // This file is not compiled by Typescript, but by ESBuild // to keep the dynamic import const react_1 = require("react"); // In React 18, you should use createRoot() from "react-dom/client". // In React 18, you should use render from "react-dom". // We support both, but Webpack chooses both of them and normalizes them to "react-dom/client", // hence why we import the right thing all the time but need to differentiate here const client_1 = __importDefault(require("react-dom/client")); const remotion_1 = require("remotion"); const no_react_1 = require("remotion/no-react"); let currentBundleMode = { type: 'index', }; const setBundleMode = (state) => { currentBundleMode = state; }; const getBundleMode = () => { return currentBundleMode; }; remotion_1.Internals.CSSUtils.injectCSS(remotion_1.Internals.CSSUtils.makeDefaultPreviewCSS(null, '#1f2428')); const getCanSerializeDefaultProps = (object) => { try { const str = JSON.stringify(object); // 256MB is the theoretical limit, making it throw if over 90% of that is reached. return str.length < 256 * 1024 * 1024 * 0.9; } catch (err) { if (err.message.includes('Invalid string length')) { return false; } throw err; } }; const isInHeadlessBrowser = () => { return typeof window.remotion_puppeteerTimeout !== 'undefined'; }; const DelayedSpinner = () => { const [show, setShow] = (0, react_1.useState)(false); (0, react_1.useEffect)(() => { const timeout = setTimeout(() => { setShow(true); }, 2000); return () => { clearTimeout(timeout); }; }, []); if (!show) { return null; } return ((0, jsx_runtime_1.jsx)(remotion_1.AbsoluteFill, { style: { justifyContent: 'center', alignItems: 'center', fontSize: 13, opacity: 0.6, color: 'white', fontFamily: 'Helvetica, Arial, sans-serif', }, children: "Loading Studio" })); }; const GetVideoComposition = ({ state }) => { const { compositions, currentCompositionMetadata, canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager); const { setCanvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionSetters); const portalContainer = (0, react_1.useRef)(null); const { delayRender, continueRender } = (0, remotion_1.useDelayRender)(); const [handle] = (0, react_1.useState)(() => delayRender(`Waiting for Composition "${state.compositionName}"`)); (0, react_1.useEffect)(() => { return () => continueRender(handle); }, [handle, continueRender]); (0, react_1.useEffect)(() => { if (compositions.length === 0) { return; } const foundComposition = compositions.find((c) => c.id === state.compositionName); if (!foundComposition) { throw new Error(`Found no composition with the name ${state.compositionName}. The following compositions were found instead: ${compositions .map((c) => c.id) .join(', ')}. All compositions must have their ID calculated deterministically and must be mounted at the same time.`); } setCanvasContent({ type: 'composition', compositionId: foundComposition.id, }); }, [compositions, state, currentCompositionMetadata, setCanvasContent]); (0, react_1.useEffect)(() => { if (!canvasContent) { return; } const { current } = portalContainer; if (!current) { throw new Error('portal did not render'); } current.appendChild(remotion_1.Internals.portalNode()); continueRender(handle); return () => { current.removeChild(remotion_1.Internals.portalNode()); }; }, [canvasContent, handle, continueRender]); if (!currentCompositionMetadata) { return null; } return ((0, jsx_runtime_1.jsx)("div", { ref: portalContainer, id: "remotion-canvas", style: { width: currentCompositionMetadata.width, height: currentCompositionMetadata.height, display: 'flex', backgroundColor: 'transparent', } })); }; const DEFAULT_ROOT_COMPONENT_TIMEOUT = 10000; const waitForRootHandle = (0, remotion_1.delayRender)('Loading root component - See https://remotion.dev/docs/troubleshooting/loading-root-component if you experience a timeout', { timeoutInMilliseconds: typeof window === 'undefined' ? DEFAULT_ROOT_COMPONENT_TIMEOUT : ((_a = window.remotion_puppeteerTimeout) !== null && _a !== void 0 ? _a : DEFAULT_ROOT_COMPONENT_TIMEOUT), }); const videoContainer = document.getElementById('video-container'); let root = null; const getRootForElement = () => { if (root) { return root; } root = client_1.default.createRoot(videoContainer); return root; }; const renderToDOM = (content) => { if (!client_1.default.createRoot) { if (no_react_1.NoReactInternals.ENABLE_V5_BREAKING_CHANGES) { throw new Error('Remotion 5.0 does only support React 18+. However, ReactDOM.createRoot() is undefined.'); } client_1.default.render(content, videoContainer); return; } getRootForElement().render(content); }; const renderContent = (Root) => { var _a, _b; const bundleMode = getBundleMode(); if (bundleMode.type === 'composition') { const markup = ((0, jsx_runtime_1.jsxs)(remotion_1.Internals.RemotionRoot, { audioEnabled: window.remotion_audioEnabled, videoEnabled: window.remotion_videoEnabled, logLevel: window.remotion_logLevel, numberOfAudioTags: 0, audioLatencyHint: (_a = window.remotion_audioLatencyHint) !== null && _a !== void 0 ? _a : 'interactive', onlyRenderComposition: bundleMode.compositionName, currentCompositionMetadata: { props: no_react_1.NoReactInternals.deserializeJSONWithSpecialTypes(bundleMode.serializedResolvedPropsWithSchema), durationInFrames: bundleMode.compositionDurationInFrames, fps: bundleMode.compositionFps, height: bundleMode.compositionHeight, width: bundleMode.compositionWidth, defaultCodec: bundleMode.compositionDefaultCodec, defaultOutName: bundleMode.compositionDefaultOutName, defaultVideoImageFormat: bundleMode.compositionDefaultVideoImageFormat, defaultPixelFormat: bundleMode.compositionDefaultPixelFormat, defaultProResProfile: bundleMode.compositionDefaultProResProfile, }, children: [(0, jsx_runtime_1.jsx)(Root, {}), (0, jsx_runtime_1.jsx)(GetVideoComposition, { state: bundleMode })] })); renderToDOM(markup); } if (bundleMode.type === 'evaluation') { const markup = ((0, jsx_runtime_1.jsx)(remotion_1.Internals.RemotionRoot, { audioEnabled: window.remotion_audioEnabled, videoEnabled: window.remotion_videoEnabled, logLevel: window.remotion_logLevel, numberOfAudioTags: 0, onlyRenderComposition: null, currentCompositionMetadata: null, audioLatencyHint: (_b = window.remotion_audioLatencyHint) !== null && _b !== void 0 ? _b : 'interactive', children: (0, jsx_runtime_1.jsx)(Root, {}) })); renderToDOM(markup); } if (bundleMode.type === 'index') { if (isInHeadlessBrowser()) { return; } renderToDOM((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(DelayedSpinner, {}) })); Promise.resolve().then(() => __importStar(require('./internals'))).then(({ StudioInternals }) => { window.remotion_isStudio = true; window.remotion_isReadOnlyStudio = true; remotion_1.Internals.enableSequenceStackTraces(); renderToDOM((0, jsx_runtime_1.jsx)(StudioInternals.Studio, { readOnly: true, rootComponent: Root })); }) .catch((err) => { renderToDOM((0, jsx_runtime_1.jsxs)("div", { children: ["Failed to load Remotion Studio: ", err.message] })); }); } }; remotion_1.Internals.waitForRoot((Root) => { renderContent(Root); (0, remotion_1.continueRender)(waitForRootHandle); }); const setBundleModeAndUpdate = (state) => { setBundleMode(state); const delay = (0, remotion_1.delayRender)('Waiting for root component to load - See https://remotion.dev/docs/troubleshooting/loading-root-component if you experience a timeout'); remotion_1.Internals.waitForRoot((Root) => { renderContent(Root); requestAnimationFrame(() => { (0, remotion_1.continueRender)(delay); }); }); }; exports.setBundleModeAndUpdate = setBundleModeAndUpdate; if (typeof window !== 'undefined') { const getUnevaluatedComps = () => { if (!remotion_1.Internals.getRoot()) { throw new Error('registerRoot() was never called. 1. Make sure you specified the correct entrypoint for your bundle. 2. If your registerRoot() call is deferred, use the delayRender/continueRender pattern to tell Remotion to wait.'); } if (!remotion_1.Internals.compositionsRef.current) { throw new Error('Unexpectedly did not have a CompositionManager'); } const compositions = remotion_1.Internals.compositionsRef.current.getCompositions(); const canSerializeDefaultProps = getCanSerializeDefaultProps(compositions); if (!canSerializeDefaultProps) { remotion_1.Internals.Log.warn({ logLevel: window.remotion_logLevel, tag: null }, 'defaultProps are too big to serialize - trying to find the problematic composition...'); remotion_1.Internals.Log.warn({ logLevel: window.remotion_logLevel, tag: null }, 'Serialization:', compositions); for (const comp of compositions) { if (!getCanSerializeDefaultProps(comp)) { throw new Error(`defaultProps too big - could not serialize - the defaultProps of composition with ID ${comp.id} - the object that was passed to defaultProps was too big. Learn how to mitigate this error by visiting https://remotion.dev/docs/troubleshooting/serialize-defaultprops`); } } remotion_1.Internals.Log.warn({ logLevel: window.remotion_logLevel, tag: null }, 'Could not single out a problematic composition - The composition list as a whole is too big to serialize.'); throw new Error('defaultProps too big - Could not serialize - an object that was passed to defaultProps was too big. Learn how to mitigate this error by visiting https://remotion.dev/docs/troubleshooting/serialize-defaultprops'); } return compositions; }; window.getStaticCompositions = () => { var _a; const compositions = getUnevaluatedComps(); const inputProps = typeof window === 'undefined' || (0, remotion_1.getRemotionEnvironment)().isPlayer ? {} : ((_a = (0, remotion_1.getInputProps)()) !== null && _a !== void 0 ? _a : {}); return Promise.all(compositions.map(async (c) => { var _a, _b, _c, _d, _e, _f; const handle = (0, remotion_1.delayRender)(`Running calculateMetadata() for composition ${c.id}. If you didn't want to evaluate this composition, use "selectComposition()" instead of "getCompositions()"`); const originalProps = { ...((_a = c.defaultProps) !== null && _a !== void 0 ? _a : {}), ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}), }; const comp = remotion_1.Internals.resolveVideoConfig({ calculateMetadata: c.calculateMetadata, compositionDurationInFrames: (_b = c.durationInFrames) !== null && _b !== void 0 ? _b : null, compositionFps: (_c = c.fps) !== null && _c !== void 0 ? _c : null, compositionHeight: (_d = c.height) !== null && _d !== void 0 ? _d : null, compositionWidth: (_e = c.width) !== null && _e !== void 0 ? _e : null, signal: new AbortController().signal, originalProps, defaultProps: (_f = c.defaultProps) !== null && _f !== void 0 ? _f : {}, compositionId: c.id, }); const resolved = await Promise.resolve(comp); (0, remotion_1.continueRender)(handle); const { props, defaultProps, ...data } = resolved; return { ...data, serializedResolvedPropsWithCustomSchema: no_react_1.NoReactInternals.serializeJSONWithSpecialTypes({ data: props, indent: undefined, staticBase: null, }).serializedString, serializedDefaultPropsWithCustomSchema: no_react_1.NoReactInternals.serializeJSONWithSpecialTypes({ data: defaultProps, indent: undefined, staticBase: null, }).serializedString, }; })); }; window.remotion_getCompositionNames = () => { return getUnevaluatedComps().map((c) => c.id); }; window.remotion_calculateComposition = async (compId) => { var _a, _b, _c, _d, _e, _f, _g; const compositions = getUnevaluatedComps(); const selectedComp = compositions.find((c) => c.id === compId); if (!selectedComp) { throw new Error(`Could not find composition with ID ${compId}. Available compositions: ${compositions .map((c) => c.id) .join(', ')}`); } const abortController = new AbortController(); const handle = (0, remotion_1.delayRender)(`Running the calculateMetadata() function for composition ${compId}`); const inputProps = typeof window === 'undefined' || (0, remotion_1.getRemotionEnvironment)().isPlayer ? {} : ((_a = (0, remotion_1.getInputProps)()) !== null && _a !== void 0 ? _a : {}); const originalProps = { ...((_b = selectedComp.defaultProps) !== null && _b !== void 0 ? _b : {}), ...(inputProps !== null && inputProps !== void 0 ? inputProps : {}), }; const prom = await Promise.resolve(remotion_1.Internals.resolveVideoConfig({ calculateMetadata: selectedComp.calculateMetadata, compositionDurationInFrames: (_c = selectedComp.durationInFrames) !== null && _c !== void 0 ? _c : null, compositionFps: (_d = selectedComp.fps) !== null && _d !== void 0 ? _d : null, compositionHeight: (_e = selectedComp.height) !== null && _e !== void 0 ? _e : null, compositionWidth: (_f = selectedComp.width) !== null && _f !== void 0 ? _f : null, originalProps, signal: abortController.signal, defaultProps: (_g = selectedComp.defaultProps) !== null && _g !== void 0 ? _g : {}, compositionId: selectedComp.id, })); (0, remotion_1.continueRender)(handle); const { props, defaultProps, ...data } = prom; return { ...data, serializedResolvedPropsWithCustomSchema: no_react_1.NoReactInternals.serializeJSONWithSpecialTypes({ data: props, indent: undefined, staticBase: null, }).serializedString, serializedDefaultPropsWithCustomSchema: no_react_1.NoReactInternals.serializeJSONWithSpecialTypes({ data: defaultProps, indent: undefined, staticBase: null, }).serializedString, }; }; window.remotion_setBundleMode = exports.setBundleModeAndUpdate; }