"use strict"; // Prints to CLI and also reports back to browser var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.renderStillFlow = void 0; const renderer_1 = require("@remotion/renderer"); const node_fs_1 = require("node:fs"); const node_path_1 = __importDefault(require("node:path")); const no_react_1 = require("remotion/no-react"); const browser_download_bar_1 = require("../browser-download-bar"); const chalk_1 = require("../chalk"); const cleanup_before_quit_1 = require("../cleanup-before-quit"); const config_1 = require("../config"); const determine_image_format_1 = require("../determine-image-format"); const get_cli_options_1 = require("../get-cli-options"); const get_composition_with_dimension_override_1 = require("../get-composition-with-dimension-override"); const make_link_1 = require("../hyperlinks/make-link"); const log_1 = require("../log"); const make_on_download_1 = require("../make-on-download"); const on_artifact_1 = require("../on-artifact"); const parsed_cli_1 = require("../parsed-cli"); const progress_bar_1 = require("../progress-bar"); const progress_types_1 = require("../progress-types"); const setup_cache_1 = require("../setup-cache"); const should_use_non_overlaying_logger_1 = require("../should-use-non-overlaying-logger"); const truthy_1 = require("../truthy"); const user_passed_output_location_1 = require("../user-passed-output-location"); const add_log_to_aggregate_progress_1 = require("./add-log-to-aggregate-progress"); const renderStillFlow = async ({ remotionRoot, fullEntryPoint, entryPointReason, remainingArgs, browser, browserExecutable, chromiumOptions, envVariables, height, serializedInputPropsWithCustomSchema, overwrite, port, publicDir, puppeteerTimeout, jpegQuality, scale, stillFrame, width, compositionIdFromUi, imageFormatFromUi, logLevel, onProgress, indent, addCleanupCallback, cancelSignal, outputLocationFromUi, offthreadVideoCacheSizeInBytes, binariesDirectory, publicPath, chromeMode, offthreadVideoThreads, audioLatencyHint, mediaCacheSizeInBytes, askAIEnabled, experimentalClientSideRenderingEnabled, keyboardShortcutsEnabled, }) => { var _a, _b; const isVerbose = renderer_1.RenderInternals.isEqualOrBelowLogLevel(logLevel, 'verbose'); log_1.Log.verbose({ indent, logLevel }, chalk_1.chalk.gray(`Entry point = ${fullEntryPoint} (${entryPointReason})`)); const aggregate = (0, progress_types_1.initialAggregateRenderProgress)(); const updatesDontOverwrite = (0, should_use_non_overlaying_logger_1.shouldUseNonOverlayingLogger)({ logLevel }); const renderProgress = (0, progress_bar_1.createOverwriteableCliOutput)({ quiet: (0, parsed_cli_1.quietFlagProvided)(), cancelSignal, updatesDontOverwrite: (0, should_use_non_overlaying_logger_1.shouldUseNonOverlayingLogger)({ logLevel }), indent, }); const updateRenderProgress = ({ newline, printToConsole, }) => { const { output, progress, message } = (0, progress_bar_1.makeRenderingAndStitchingProgress)({ prog: aggregate, isUsingParallelEncoding: false, }); if (printToConsole) { renderProgress.update(updatesDontOverwrite ? message : output, newline); } onProgress({ message, value: progress, ...aggregate }); }; function updateBrowserProgress(progress) { aggregate.browser = progress; onProgress({ message: `Downloading ${chromeMode === 'chrome-for-testing' ? 'Chrome for Testing' : 'Headless Shell'} ${Math.round(progress.progress * 100)}%`, value: 0, ...aggregate, }); } const onBrowserDownload = (0, browser_download_bar_1.defaultBrowserDownloadProgress)({ quiet: (0, parsed_cli_1.quietFlagProvided)(), indent, logLevel, onProgress: updateBrowserProgress, }); await renderer_1.RenderInternals.internalEnsureBrowser({ browserExecutable, indent, logLevel, onBrowserDownload, chromeMode, }); const browserInstance = renderer_1.RenderInternals.internalOpenBrowser({ browser, browserExecutable, chromiumOptions, forceDeviceScaleFactor: scale, indent, viewport: null, logLevel, onBrowserDownload, chromeMode, }); const { cleanup: cleanupBundle, urlOrBundle } = await (0, setup_cache_1.bundleOnCliOrTakeServeUrl)({ fullPath: fullEntryPoint, remotionRoot, publicDir, onProgress: ({ copying, bundling }) => { aggregate.bundling = bundling; aggregate.copyingState = copying; updateRenderProgress({ newline: false, printToConsole: true, }); }, indentOutput: indent, logLevel, onDirectoryCreated: (dir) => { (0, cleanup_before_quit_1.registerCleanupJob)(`Delete ${dir}`, () => { renderer_1.RenderInternals.deleteDirectory(dir); }); }, quietProgress: updatesDontOverwrite, quietFlag: (0, parsed_cli_1.quietFlagProvided)(), outDir: null, // Not needed for still gitSource: null, bufferStateDelayInMilliseconds: null, maxTimelineTracks: null, publicPath, audioLatencyHint, experimentalClientSideRenderingEnabled, askAIEnabled, keyboardShortcutsEnabled, }); const server = await renderer_1.RenderInternals.prepareServer({ offthreadVideoThreads: offthreadVideoThreads !== null && offthreadVideoThreads !== void 0 ? offthreadVideoThreads : renderer_1.RenderInternals.DEFAULT_RENDER_FRAMES_OFFTHREAD_VIDEO_THREADS, indent, port, remotionRoot, logLevel, webpackConfigOrServeUrl: urlOrBundle, offthreadVideoCacheSizeInBytes, binariesDirectory, forceIPv4: false, }); addCleanupCallback(`Close server`, () => server.closeServer(false)); addCleanupCallback(`Cleanup bundle`, () => cleanupBundle()); const puppeteerInstance = await browserInstance; addCleanupCallback(`Close browser`, () => puppeteerInstance.close({ silent: false })); const { compositionId, config, reason, argsAfterComposition } = await (0, get_composition_with_dimension_override_1.getCompositionWithDimensionOverride)({ height, width, args: remainingArgs, compositionIdFromUi, browserExecutable, chromiumOptions, envVariables, indent, serializedInputPropsWithCustomSchema, port, puppeteerInstance, serveUrlOrWebpackUrl: urlOrBundle, timeoutInMilliseconds: puppeteerTimeout, logLevel, server, offthreadVideoCacheSizeInBytes, offthreadVideoThreads, binariesDirectory, onBrowserDownload, chromeMode, mediaCacheSizeInBytes, }); const { format: imageFormat, source } = (0, determine_image_format_1.determineFinalStillImageFormat)({ cliFlag: (_a = parsed_cli_1.parsedCli['image-format']) !== null && _a !== void 0 ? _a : null, configImageFormat: (_b = config_1.ConfigInternals.getUserPreferredStillImageFormat()) !== null && _b !== void 0 ? _b : null, downloadName: null, outName: (0, user_passed_output_location_1.getUserPassedOutputLocation)(argsAfterComposition, outputLocationFromUi), isLambda: false, fromUi: imageFormatFromUi, }); const relativeOutputLocation = (0, user_passed_output_location_1.getOutputLocation)({ compositionId, defaultExtension: imageFormat, args: argsAfterComposition, type: 'asset', outputLocationFromUi, compositionDefaultOutName: config.defaultOutName, }); const absoluteOutputLocation = (0, get_cli_options_1.getAndValidateAbsoluteOutputFile)(relativeOutputLocation, overwrite, logLevel); const exists = (0, node_fs_1.existsSync)(absoluteOutputLocation); (0, node_fs_1.mkdirSync)(node_path_1.default.join(absoluteOutputLocation, '..'), { recursive: true, }); (0, progress_bar_1.printFact)('info')({ indent, left: 'Composition', link: 'https://remotion.dev/docs/terminology/composition', logLevel, right: [compositionId, isVerbose ? `(${reason})` : null] .filter(truthy_1.truthy) .join(' '), color: 'gray', }); (0, progress_bar_1.printFact)('info')({ indent, left: 'Format', logLevel, right: [imageFormat, isVerbose ? `(${source})` : null] .filter(truthy_1.truthy) .join(' '), color: 'gray', }); (0, progress_bar_1.printFact)('info')({ indent, left: 'Output', logLevel, right: relativeOutputLocation, color: 'gray', }); const renderStart = Date.now(); aggregate.rendering = { frames: 0, doneIn: null, totalFrames: 1, timeRemainingInMilliseconds: null, }; updateRenderProgress({ newline: false, printToConsole: true, }); const onDownload = (0, make_on_download_1.makeOnDownload)({ downloads: aggregate.downloads, indent, logLevel, updateRenderProgress, updatesDontOverwrite, isUsingParallelEncoding: false, }); const { onArtifact } = (0, on_artifact_1.handleOnArtifact)({ artifactState: aggregate.artifactState, compositionId, onProgress: (progress) => { aggregate.artifactState = progress; updateRenderProgress({ newline: false, printToConsole: true, }); }, }); await renderer_1.RenderInternals.internalRenderStill({ composition: config, frame: stillFrame, output: absoluteOutputLocation, serveUrl: urlOrBundle, jpegQuality, envVariables, imageFormat, serializedInputPropsWithCustomSchema, chromiumOptions, timeoutInMilliseconds: puppeteerTimeout, scale, browserExecutable, overwrite, onDownload, port, puppeteerInstance, server, cancelSignal, indent, onBrowserLog: null, logLevel, serializedResolvedPropsWithCustomSchema: no_react_1.NoReactInternals.serializeJSONWithSpecialTypes({ indent: undefined, staticBase: null, data: config.props, }).serializedString, offthreadVideoCacheSizeInBytes, binariesDirectory, onBrowserDownload, onArtifact, chromeMode, offthreadVideoThreads, mediaCacheSizeInBytes, onLog: ({ logLevel: logLogLevel, previewString, tag }) => { (0, add_log_to_aggregate_progress_1.addLogToAggregateProgress)({ logs: aggregate.logs, logLogLevel, previewString, tag, logLevel, }); updateRenderProgress({ newline: false, printToConsole: true, }); }, licenseKey: null, isProduction: null, }); aggregate.rendering = { frames: 1, doneIn: Date.now() - renderStart, totalFrames: 1, timeRemainingInMilliseconds: null, }; updateRenderProgress({ newline: true, printToConsole: true, }); log_1.Log.info({ indent, logLevel }, chalk_1.chalk.blue(`${(exists ? '○' : '+').padEnd(progress_bar_1.LABEL_WIDTH)} ${(0, make_link_1.makeHyperlink)({ url: 'file://' + absoluteOutputLocation, text: relativeOutputLocation, fallback: relativeOutputLocation })}`)); }; exports.renderStillFlow = renderStillFlow;