UNPKG

@remotion/renderer

Version:

Render Remotion videos using Node.js or Bun

149 lines (148 loc) 6.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.seekToFrame = exports.waitForReady = void 0; const symbolicateable_error_1 = require("./error-handling/symbolicateable-error"); const logger_1 = require("./logger"); const parse_browser_error_stack_1 = require("./parse-browser-error-stack"); const puppeteer_evaluate_1 = require("./puppeteer-evaluate"); const cancelledToken = 'cancelled'; const readyToken = 'ready'; const waitForReady = ({ page, timeoutInMilliseconds, frame, indent, logLevel, }) => { const cleanups = []; const retrieveCancelledErrorAndReject = () => { return new Promise((_, reject) => { (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatch)({ pageFunction: () => window.remotion_cancelledError, args: [], frame: null, page, timeoutInMilliseconds, }) .then(({ value: val }) => { if (typeof val !== 'string') { reject(val); return; } reject(new symbolicateable_error_1.SymbolicateableError({ frame: null, stack: val, name: 'CancelledError', message: val.split('\n')[0], stackFrame: (0, parse_browser_error_stack_1.parseStack)(val.split('\n')), chunk: null, })); }) .catch((err) => { logger_1.Log.verbose({ indent, logLevel }, 'Could not get cancelled error', err); reject(new Error('Render was cancelled using cancelRender()')); }); }); }; const waitForReadyProm = new Promise((resolve, reject) => { const waitTask = page.mainFrame()._mainWorld.waitForFunction({ browser: page.browser, // Increase timeout so the delayRender() timeout fires earlier timeout: timeoutInMilliseconds + 3000, pageFunction: `window.remotion_renderReady === true ? "${readyToken}" : window.remotion_cancelledError !== undefined ? "${cancelledToken}" : false`, title: frame === null ? 'the page to render the React component' : `the page to render the React component at frame ${frame}`, }); cleanups.push(() => { waitTask.terminate(new Error('cleanup')); }); waitTask.promise .then((a) => { const token = a.toString(); if (token === cancelledToken) { return retrieveCancelledErrorAndReject(); } if (token === readyToken) { return resolve(a); } reject(new Error('Unexpected token ' + token)); }) .catch((err) => { if (err.message.includes('timeout') && err.message.includes('exceeded')) { (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatchAndTimeout)({ pageFunction: () => { return Object.keys(window.remotion_delayRenderTimeouts) .map((id, i) => { const { label } = window.remotion_delayRenderTimeouts[id]; if (label === null) { return `${i + 1}. (no label)`; } return `"${i + 1}. ${label}"`; }) .join(', '); }, args: [], frame, page, timeoutInMilliseconds: 5000, }) .then((res) => { reject(new Error(`Timeout (${timeoutInMilliseconds}ms) exceeded rendering the component${frame ? ' at frame ' + frame : ' initially'}. ${res.value ? `Open delayRender() handles: ${res.value}` : ''}. You can increase the timeout using the "timeoutInMilliseconds" / "--timeout" option of the function or command you used to trigger this render.`)); }) .catch((newErr) => { logger_1.Log.warn({ indent, logLevel }, 'Tried to get delayRender() handles for timeout, but could not do so because of', newErr); // Ignore, use prev error reject(err); }); } else { reject(err); } }); }); const onDisposedPromise = new Promise((_, reject) => { const onDispose = () => { reject(new Error('Target closed (page disposed)')); }; page.on("disposed" /* PageEmittedEvents.Disposed */, onDispose); cleanups.push(() => { page.off("disposed" /* PageEmittedEvents.Disposed */, onDispose); }); }); const onClosedSilentPromise = new Promise((_, reject) => { const onClosedSilent = () => { reject(new Error('Target closed')); }; page.browser.on("closed-silent" /* BrowserEmittedEvents.ClosedSilent */, onClosedSilent); cleanups.push(() => { page.browser.off("closed-silent" /* BrowserEmittedEvents.ClosedSilent */, onClosedSilent); }); }); return Promise.race([ onDisposedPromise, onClosedSilentPromise, waitForReadyProm, ]).finally(() => { cleanups.forEach((cleanup) => { cleanup(); }); }); }; exports.waitForReady = waitForReady; const seekToFrame = async ({ frame, page, composition, timeoutInMilliseconds, logLevel, indent, attempt, }) => { await (0, exports.waitForReady)({ page, timeoutInMilliseconds, frame: null, indent, logLevel, }); await (0, puppeteer_evaluate_1.puppeteerEvaluateWithCatchAndTimeout)({ pageFunction: (f, c, a) => { window.remotion_setFrame(f, c, a); }, args: [frame, composition, attempt], frame, page, timeoutInMilliseconds, }); await (0, exports.waitForReady)({ page, timeoutInMilliseconds, frame, indent, logLevel }); await page.evaluateHandle('document.fonts.ready'); }; exports.seekToFrame = seekToFrame;