UNPKG

@remotion/renderer

Version:

Render Remotion videos using Node.js or Bun

1,789 lines (1,758 loc) 680 kB
import { createRequire } from "node:module"; var __defProp = Object.defineProperty; var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true, configurable: true, set: (newValue) => all[name] = () => newValue }); }; var __require = /* @__PURE__ */ createRequire(import.meta.url); // vendor/yauzl-patched/pend.js var require_pend = __commonJS((exports, module) => { module.exports = Pend; function Pend() { this.pending = 0; this.max = Infinity; this.listeners = []; this.waiting = []; this.error = null; } Pend.prototype.go = function(fn) { if (this.pending < this.max) { pendGo(this, fn); } else { this.waiting.push(fn); } }; Pend.prototype.wait = function(cb) { if (this.pending === 0) { cb(this.error); } else { this.listeners.push(cb); } }; Pend.prototype.hold = function() { return pendHold(this); }; function pendHold(self) { self.pending += 1; var called = false; return onCb; function onCb(err) { if (called) throw new Error("callback called twice"); called = true; self.error = self.error || err; self.pending -= 1; if (self.waiting.length > 0 && self.pending < self.max) { pendGo(self, self.waiting.shift()); } else if (self.pending === 0) { var listeners = self.listeners; self.listeners = []; listeners.forEach(cbListener); } } function cbListener(listener) { listener(self.error); } } function pendGo(self, fn) { fn(pendHold(self)); } }); // vendor/yauzl-patched/fd-slicer.js var require_fd_slicer = __commonJS((exports) => { var fs5 = __require("fs"); var util = __require("util"); var stream = __require("stream"); var Readable = stream.Readable; var Writable = stream.Writable; var PassThrough = stream.PassThrough; var Pend = require_pend(); var EventEmitter2 = __require("events").EventEmitter; exports.createFromBuffer = createFromBuffer; exports.createFromFd = createFromFd; exports.BufferSlicer = BufferSlicer; exports.FdSlicer = FdSlicer; util.inherits(FdSlicer, EventEmitter2); function FdSlicer(fd, options2) { options2 = options2 || {}; EventEmitter2.call(this); this.fd = fd; this.pend = new Pend; this.pend.max = 1; this.refCount = 0; this.autoClose = !!options2.autoClose; } FdSlicer.prototype.read = function(buffer, offset, length, position, callback) { var self = this; self.pend.go(function(cb) { fs5.read(self.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) { cb(); callback(err, bytesRead, buffer2); }); }); }; FdSlicer.prototype.write = function(buffer, offset, length, position, callback) { var self = this; self.pend.go(function(cb) { fs5.write(self.fd, buffer, offset, length, position, function(err, written, buffer2) { cb(); callback(err, written, buffer2); }); }); }; FdSlicer.prototype.createReadStream = function(options2) { return new ReadStream(this, options2); }; FdSlicer.prototype.createWriteStream = function(options2) { return new WriteStream(this, options2); }; FdSlicer.prototype.ref = function() { this.refCount += 1; }; FdSlicer.prototype.unref = function() { var self = this; self.refCount -= 1; if (self.refCount > 0) return; if (self.refCount < 0) throw new Error("invalid unref"); if (self.autoClose) { fs5.close(self.fd, onCloseDone); } function onCloseDone(err) { if (err) { self.emit("error", err); } else { self.emit("close"); } } }; util.inherits(ReadStream, Readable); function ReadStream(context, options2) { options2 = options2 || {}; Readable.call(this, options2); this.context = context; this.context.ref(); this.start = options2.start || 0; this.endOffset = options2.end; this.pos = this.start; this._destroyed = false; } ReadStream.prototype._read = function(n) { var self = this; if (self._destroyed) return; var toRead = Math.min(self._readableState.highWaterMark, n); if (self.endOffset != null) { toRead = Math.min(toRead, self.endOffset - self.pos); } if (toRead <= 0) { self._destroyed = true; self.push(null); self.context.unref(); return; } self.context.pend.go(function(cb) { if (self._destroyed) return cb(); var buffer = Buffer.allocUnsafe(toRead); fs5.read(self.context.fd, buffer, 0, toRead, self.pos, function(err, bytesRead) { if (self._destroyed) return cb(); if (err) { self.destroy(err); } else if (bytesRead === 0) { self._destroyed = true; self.push(null); self.context.unref(); } else { self.pos += bytesRead; self.push(buffer.slice(0, bytesRead)); } cb(); }); }); }; ReadStream.prototype.destroy = function(err) { if (err == null && !this.readableEnded) { err = new Error("stream _destroyed"); } return Readable.prototype.destroy.call(this, err); }; ReadStream.prototype._destroy = function(err, cb) { if (!this._destroyed) { this._destroyed = true; this.context.unref(); } cb(err); }; util.inherits(WriteStream, Writable); function WriteStream(context, options2) { options2 = options2 || {}; Writable.call(this, options2); this.context = context; this.context.ref(); this.start = options2.start || 0; this.endOffset = options2.end == null ? Infinity : +options2.end; this.bytesWritten = 0; this.pos = this.start; this._destroyed = false; this.on("finish", this.destroy.bind(this)); } WriteStream.prototype._write = function(buffer, encoding, callback) { var self = this; if (self._destroyed) return; if (self.pos + buffer.length > self.endOffset) { var err = new Error("maximum file length exceeded"); err.code = "ETOOBIG"; self.destroy(); callback(err); return; } self.context.pend.go(function(cb) { if (self._destroyed) return cb(); fs5.write(self.context.fd, buffer, 0, buffer.length, self.pos, function(err2, bytes) { if (err2) { self.destroy(); cb(); callback(err2); } else { self.bytesWritten += bytes; self.pos += bytes; self.emit("progress"); cb(); callback(); } }); }); }; WriteStream.prototype._destroy = function(err, cb) { if (!this._destroyed) { this._destroyed = true; this.context.unref(); } cb(err); }; util.inherits(BufferSlicer, EventEmitter2); function BufferSlicer(buffer, options2) { EventEmitter2.call(this); options2 = options2 || {}; this.refCount = 0; this.buffer = buffer; this.maxChunkSize = options2.maxChunkSize || Number.MAX_SAFE_INTEGER; } BufferSlicer.prototype.read = function(buffer, offset, length, position, callback) { if (!(0 <= offset && offset <= buffer.length)) throw new RangeError("offset outside buffer: 0 <= " + offset + " <= " + buffer.length); if (position < 0) throw new RangeError("position is negative: " + position); if (offset + length > buffer.length) { length = buffer.length - offset; } if (position + length > this.buffer.length) { length = this.buffer.length - position; } if (length <= 0) { setImmediate(function() { callback(null, 0); }); return; } this.buffer.copy(buffer, offset, position, position + length); setImmediate(function() { callback(null, length); }); }; BufferSlicer.prototype.write = function(buffer, offset, length, position, callback) { buffer.copy(this.buffer, position, offset, offset + length); setImmediate(function() { callback(null, length, buffer); }); }; BufferSlicer.prototype.createReadStream = function(options2) { options2 = options2 || {}; var readStream = new PassThrough(options2); readStream._destroyed = false; readStream.start = options2.start || 0; readStream.endOffset = options2.end; readStream.pos = readStream.endOffset || this.buffer.length; var entireSlice = this.buffer.slice(readStream.start, readStream.pos); var offset = 0; while (true) { var nextOffset = offset + this.maxChunkSize; if (nextOffset >= entireSlice.length) { if (offset < entireSlice.length) { readStream.write(entireSlice.slice(offset, entireSlice.length)); } break; } readStream.write(entireSlice.slice(offset, nextOffset)); offset = nextOffset; } readStream.end(); readStream._destroy = function(err, cb) { readStream._destroyed = true; PassThrough.prototype._destroy.call(readStream, err, cb); }; return readStream; }; BufferSlicer.prototype.createWriteStream = function(options2) { var bufferSlicer = this; options2 = options2 || {}; var writeStream = new Writable(options2); writeStream.start = options2.start || 0; writeStream.endOffset = options2.end == null ? this.buffer.length : +options2.end; writeStream.bytesWritten = 0; writeStream.pos = writeStream.start; writeStream._destroyed = false; writeStream._write = function(buffer, encoding, callback) { if (writeStream._destroyed) return; var end = writeStream.pos + buffer.length; if (end > writeStream.endOffset) { var err = new Error("maximum file length exceeded"); err.code = "ETOOBIG"; writeStream._destroyed = true; callback(err); return; } buffer.copy(bufferSlicer.buffer, writeStream.pos, 0, buffer.length); writeStream.bytesWritten += buffer.length; writeStream.pos = end; writeStream.emit("progress"); callback(); }; writeStream._destroy = function(err, cb) { writeStream._destroyed = true; cb(err); }; return writeStream; }; BufferSlicer.prototype.ref = function() { this.refCount += 1; }; BufferSlicer.prototype.unref = function() { this.refCount -= 1; if (this.refCount < 0) { throw new Error("invalid unref"); } }; function createFromBuffer(buffer, options2) { return new BufferSlicer(buffer, options2); } function createFromFd(fd, options2) { return new FdSlicer(fd, options2); } }); // vendor/yauzl-patched/buffer-crc32.js var require_buffer_crc32 = __commonJS((exports, module) => { var Buffer2 = __require("buffer").Buffer; var CRC_TABLE = [ 0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, 1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223, 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989, 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161, 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567, 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 936918000, 2847714899, 3736837829, 1202900863, 817233897, 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117 ]; if (typeof Int32Array !== "undefined") { CRC_TABLE = new Int32Array(CRC_TABLE); } function ensureBuffer(input) { if (Buffer2.isBuffer(input)) { return input; } var hasNewBufferAPI = typeof Buffer2.alloc === "function" && typeof Buffer2.from === "function"; if (typeof input === "number") { return hasNewBufferAPI ? Buffer2.alloc(input) : new Buffer2(input); } else if (typeof input === "string") { return hasNewBufferAPI ? Buffer2.from(input) : new Buffer2(input); } else { throw new Error("input must be buffer, number, or string, received " + typeof input); } } function bufferizeInt(num) { var tmp = ensureBuffer(4); tmp.writeInt32BE(num, 0); return tmp; } function _crc32(buf, previous) { buf = ensureBuffer(buf); if (Buffer2.isBuffer(previous)) { previous = previous.readUInt32BE(0); } var crc = ~~previous ^ -1; for (var n = 0;n < buf.length; n++) { crc = CRC_TABLE[(crc ^ buf[n]) & 255] ^ crc >>> 8; } return crc ^ -1; } function crc32() { return bufferizeInt(_crc32.apply(null, arguments)); } crc32.signed = function() { return _crc32.apply(null, arguments); }; crc32.unsigned = function() { return _crc32.apply(null, arguments) >>> 0; }; module.exports = crc32; }); // src/index.ts import execa2 from "execa"; // src/assets/download-file.ts import { createWriteStream } from "node:fs"; // src/ensure-output-directory.ts import fs from "node:fs"; import path from "node:path"; var ensureOutputDirectory = (outputLocation) => { const dirName = path.dirname(outputLocation); if (!fs.existsSync(dirName)) { fs.mkdirSync(dirName, { recursive: true }); } }; // src/chalk/is-color-supported.ts import * as tty from "tty"; var isColorSupported = () => { const env = process.env || {}; const isForceDisabled = "NO_COLOR" in env; if (isForceDisabled) { return false; } const isForced = "FORCE_COLOR" in env; if (isForced) { return true; } const isWindows = process.platform === "win32"; const isCompatibleTerminal = tty?.isatty?.(1) && env.TERM && env.TERM !== "dumb"; const isCI = "CI" in env && (("GITHUB_ACTIONS" in env) || ("GITLAB_CI" in env) || ("CIRCLECI" in env)); return isWindows || isCompatibleTerminal || isCI; }; // src/chalk/index.ts var chalk = (() => { const colors = { enabled: () => isColorSupported(), visible: true, styles: {}, keys: {} }; const ansi = (st) => { const open = `\x1B[${st.codes[0]}m`; const close = `\x1B[${st.codes[1]}m`; const regex = new RegExp(`\\u001b\\[${st.codes[1]}m`, "g"); st.wrap = (input, newline) => { if (input.includes(close)) input = input.replace(regex, close + open); const output = open + input + close; return newline ? output.replace(/\r*\n/g, `${close}$&${open}`) : output; }; return st; }; const wrap = (sty, input, newline) => { return sty.wrap?.(input, newline); }; const style = (input, stack) => { if (input === "" || input === null || input === undefined) return ""; if (colors.enabled() === false) return input; if (colors.visible === false) return ""; let str = String(input); const nl = str.includes(` `); let n = stack.length; while (n-- > 0) str = wrap(colors.styles[stack[n]], str, nl); return str; }; const define = (name, codes, type) => { colors.styles[name] = ansi({ name, codes }); const keys = colors.keys[type] || (colors.keys[type] = []); keys.push(name); Reflect.defineProperty(colors, name, { configurable: true, enumerable: true, set(value) { colors.alias?.(name, value); }, get() { const color = (input) => style(input, color.stack); Reflect.setPrototypeOf(color, colors); color.stack = this.stack ? this.stack.concat(name) : [name]; return color; } }); }; define("reset", [0, 0], "modifier"); define("bold", [1, 22], "modifier"); define("dim", [2, 22], "modifier"); define("italic", [3, 23], "modifier"); define("underline", [4, 24], "modifier"); define("inverse", [7, 27], "modifier"); define("hidden", [8, 28], "modifier"); define("strikethrough", [9, 29], "modifier"); define("black", [30, 39], "color"); define("red", [31, 39], "color"); define("green", [32, 39], "color"); define("yellow", [33, 39], "color"); define("blue", [34, 39], "color"); define("magenta", [35, 39], "color"); define("cyan", [36, 39], "color"); define("white", [37, 39], "color"); define("gray", [90, 39], "color"); define("grey", [90, 39], "color"); define("bgBlack", [40, 49], "bg"); define("bgRed", [41, 49], "bg"); define("bgGreen", [42, 49], "bg"); define("bgYellow", [43, 49], "bg"); define("bgBlue", [44, 49], "bg"); define("bgMagenta", [45, 49], "bg"); define("bgWhite", [47, 49], "bg"); define("blackBright", [90, 39], "bright"); define("redBright", [91, 39], "bright"); define("greenBright", [92, 39], "bright"); define("yellowBright", [93, 39], "bright"); define("blueBright", [94, 39], "bright"); define("magentaBright", [95, 39], "bright"); define("whiteBright", [97, 39], "bright"); define("bgBlackBright", [100, 49], "bgBright"); define("bgRedBright", [101, 49], "bgBright"); define("bgGreenBright", [102, 49], "bgBright"); define("bgYellowBright", [103, 49], "bgBright"); define("bgBlueBright", [104, 49], "bgBright"); define("bgMagentaBright", [105, 49], "bgBright"); define("bgWhiteBright", [107, 49], "bgBright"); colors.alias = (name, color) => { const fn = colors[color]; if (typeof fn !== "function") { throw new TypeError("Expected alias to be the name of an existing color (string) or a function"); } if (!fn.stack) { Reflect.defineProperty(fn, "name", { value: name }); colors.styles[name] = fn; fn.stack = [name]; } Reflect.defineProperty(colors, name, { configurable: true, enumerable: true, set(value) { colors.alias?.(name, value); }, get() { const col = (input) => style(input, col.stack); Reflect.setPrototypeOf(col, colors); col.stack = this.stack ? this.stack.concat(fn.stack) : fn.stack; return col; } }); }; return colors; })(); // src/log-level.ts var logLevels = ["trace", "verbose", "info", "warn", "error"]; var getNumberForLogLevel = (level) => { return logLevels.indexOf(level); }; var isValidLogLevel = (level) => { return getNumberForLogLevel(level) > -1; }; var isEqualOrBelowLogLevel = (currentLevel, level) => { return getNumberForLogLevel(currentLevel) <= getNumberForLogLevel(level); }; // src/repro.ts import { execSync } from "node:child_process"; import fs3, { rmSync } from "node:fs"; import os from "node:os"; import path3 from "node:path"; import { VERSION } from "remotion/version"; // src/find-closest-package-json.ts import fs2 from "node:fs"; import path2 from "node:path"; var recursionLimit = 5; var findClosestPackageJson = () => { let currentDir = process.cwd(); let possiblePackageJson = ""; for (let i = 0;i < recursionLimit; i++) { possiblePackageJson = path2.join(currentDir, "package.json"); const exists = fs2.existsSync(possiblePackageJson); if (exists) { return possiblePackageJson; } currentDir = path2.dirname(currentDir); } return null; }; var findRemotionRoot = () => { const closestPackageJson = findClosestPackageJson(); if (closestPackageJson === null) { return process.cwd(); } return path2.dirname(closestPackageJson); }; // src/is-serve-url.ts var isServeUrl = (potentialUrl) => { if (typeof potentialUrl === "undefined") { throw new Error("serveUrl is undefined"); } if (potentialUrl.startsWith("www.") || potentialUrl.includes("amazonaws.com")) { return true; } return potentialUrl.startsWith("https://") || potentialUrl.startsWith("http://"); }; // src/repro.ts var REPRO_DIR = ".remotionrepro"; var LOG_FILE_NAME = "logs.txt"; var INPUT_DIR = "bundle"; var OUTPUT_DIR = "output"; var LINE_SPLIT = ` `; var getZipFileName = (name) => `remotion-repro-${name}-${Date.now()}.zip`; var readyDirSync = (dir) => { let items; try { items = fs3.readdirSync(dir); } catch { return fs3.mkdirSync(dir, { recursive: true }); } items.forEach((item) => { item = path3.join(dir, item); fs3.rmSync(item, { recursive: true, force: true }); }); }; var zipFolder = ({ sourceFolder, targetZip, indent, logLevel }) => { const platform = os.platform(); try { Log.info({ indent, logLevel }, "+ Creating reproduction ZIP"); if (platform === "win32") { execSync(`powershell.exe Compress-Archive -Path "${sourceFolder}" -DestinationPath "${targetZip}"`); } else { execSync(`zip -r "${targetZip}" "${sourceFolder}"`); } rmSync(sourceFolder, { recursive: true }); Log.info({ indent, logLevel }, `${chalk.blue(`+ Repro: ${targetZip}`)}`); } catch (error) { Log.error({ indent, logLevel }, `Failed to zip repro folder, The repro folder is ${sourceFolder}. You can try manually zip it.`); Log.error({ indent, logLevel }, error); } }; var reproWriter = (name) => { const root = findRemotionRoot(); const reproFolder = path3.join(root, REPRO_DIR); const logPath = path3.join(reproFolder, LOG_FILE_NAME); const zipFile = path3.join(root, getZipFileName(name)); readyDirSync(reproFolder); const reproLogWriteStream = fs3.createWriteStream(logPath, { flags: "a" }); const serializeArgs = (args) => JSON.stringify(args); const writeLine = (level, ...args) => { if (!args.length) return; const startTime = new Date().toISOString(); const line = `[${startTime}] ${level} ${serializeArgs(args)}`; reproLogWriteStream.write(line + LINE_SPLIT); }; const start = ({ serveUrl, serializedInputPropsWithCustomSchema, serializedResolvedPropsWithCustomSchema }) => { const isServe = isServeUrl(serveUrl); if (!isServe) { const inputDir = path3.resolve(reproFolder, INPUT_DIR); readyDirSync(inputDir); fs3.cpSync(serveUrl, inputDir, { recursive: true }); } const serializedProps = path3.resolve(reproFolder, "input-props.json"); fs3.writeFileSync(serializedProps, serializedInputPropsWithCustomSchema); const serializedResolvedProps = path3.resolve(reproFolder, "resolved-props.json"); fs3.writeFileSync(serializedResolvedProps, serializedResolvedPropsWithCustomSchema); writeLine("info", [`Args: ${JSON.stringify(process.argv)}`]); writeLine("info", [`Node/Bun version: ${process.version}`]); writeLine("info", [`OS: ${process.platform}-${process.arch}`]); writeLine("info", [`Serve URL: ${serveUrl}`]); writeLine("info", [`Remotion version: ${VERSION}`]); }; const onRenderSucceed = ({ indent, logLevel, output }) => { return new Promise((resolve, reject) => { try { if (output) { const outputDir = path3.resolve(reproFolder, OUTPUT_DIR); readyDirSync(outputDir); const fileName = path3.basename(output); const targetPath = path3.join(outputDir, fileName); fs3.copyFileSync(output, targetPath); } disableRepro(); reproLogWriteStream.end(() => { reproLogWriteStream.close(() => { zipFolder({ sourceFolder: reproFolder, targetZip: zipFile, indent, logLevel }); resolve(); }); }); } catch (error) { Log.error({ indent: false, logLevel }, `repro render success error:`); Log.error({ indent: false, logLevel }, error); reject(error); } }); }; return { start, writeLine, onRenderSucceed }; }; var reproWriteInstance = null; var getReproWriter = () => { if (!reproWriteInstance) { throw new Error("reproWriteInstance is not initialized"); } return reproWriteInstance; }; var writeInRepro = (level, ...args) => { if (isReproEnabled()) { getReproWriter().writeLine(level, ...args); } }; var shouldRepro = false; var enableRepro = ({ serveUrl, compositionName, serializedInputPropsWithCustomSchema, serializedResolvedPropsWithCustomSchema }) => { shouldRepro = true; reproWriteInstance = reproWriter(compositionName); getReproWriter().start({ serveUrl, serializedInputPropsWithCustomSchema, serializedResolvedPropsWithCustomSchema }); }; var disableRepro = () => { shouldRepro = false; }; var isReproEnabled = () => shouldRepro; // src/truthy.ts function truthy(value) { return Boolean(value); } // src/logger.ts var INDENT_TOKEN = chalk.gray("│"); var verboseTag = (str) => { return isColorSupported() ? chalk.bgBlack(` ${str} `) : `[${str}]`; }; var Log = { formatLogs: (logLevel, options2, args) => { return [ options2.indent ? INDENT_TOKEN : null, options2.tag ? verboseTag(options2.tag) : null ].filter(truthy).concat(args.map((a) => { if (logLevel === "warn") { return chalk.yellow(a); } if (logLevel === "error") { return chalk.red(a); } if (logLevel === "verbose" || logLevel === "trace") { return chalk.gray(a); } return a; })); }, trace: (options2, ...args) => { writeInRepro("trace", ...args); if (isEqualOrBelowLogLevel(options2.logLevel, "trace")) { if (args.length === 0) { return process.stdout.write(` `); } return console.log(...Log.formatLogs("trace", options2, args)); } }, verbose: (options2, ...args) => { writeInRepro("verbose", ...args); if (isEqualOrBelowLogLevel(options2.logLevel, "verbose")) { if (args.length === 0) { return process.stdout.write(` `); } return console.log(...Log.formatLogs("verbose", options2, args)); } }, info: (options2, ...args) => { writeInRepro("info", ...args); if (isEqualOrBelowLogLevel(options2.logLevel, "info")) { if (args.length === 0) { return process.stdout.write(` `); } return console.log(...Log.formatLogs("info", options2, args)); } }, warn: (options2, ...args) => { writeInRepro("warn", ...args); if (isEqualOrBelowLogLevel(options2.logLevel, "warn")) { if (args.length === 0) { return process.stdout.write(` `); } return console.warn(...Log.formatLogs("warn", options2, args)); } }, error: (options2, ...args) => { writeInRepro("error", ...args); if (isEqualOrBelowLogLevel(options2.logLevel, "error")) { if (args.length === 0) { return process.stdout.write(` `); } return console.error(...Log.formatLogs("error", options2, args)); } } }; // src/assets/read-file.ts import https from "https"; import http from "node:http"; // src/redirect-status-codes.ts var redirectStatusCodes = [301, 302, 303, 307, 308]; // src/assets/read-file.ts var getClient = (url) => { if (url.startsWith("https://")) { return https.get; } if (url.startsWith("http://")) { return http.get; } throw new Error(`Can only download URLs starting with http:// or https://, got "${url}"`); }; var readFileWithoutRedirect = (url) => { return new Promise((resolve, reject) => { const client = getClient(url); const req = client(url, typeof Bun === "undefined" ? { headers: { "user-agent": "Mozilla/5.0 (@remotion/renderer - https://remotion.dev)" } } : {}, (res) => { resolve({ request: req, response: res }); }); req.on("error", (err) => { req.destroy(); return reject(err); }); }); }; var readFile = async (url, redirectsSoFar = 0) => { if (redirectsSoFar > 10) { throw new Error(`Too many redirects while downloading ${url}`); } const { request, response } = await readFileWithoutRedirect(url); if (redirectStatusCodes.includes(response.statusCode)) { if (!response.headers.location) { throw new Error(`Received a status code ${response.statusCode} but no "Location" header while calling ${response.headers.location}`); } const { origin } = new URL(url); const redirectUrl = new URL(response.headers.location, origin).toString(); request.destroy(); response.destroy(); return readFile(redirectUrl, redirectsSoFar + 1); } if (response.statusCode >= 400) { const body = await tryToObtainBody(response); request.destroy(); response.destroy(); throw new Error([ `Received a status code of ${response.statusCode} while downloading file ${url}.`, body ? `The response body was:` : null, body ? `---` : null, body ? body : null, body ? `---` : null ].filter(truthy).join(` `)); } return { request, response }; }; var tryToObtainBody = async (file) => { const success = new Promise((resolve) => { let data = ""; file.on("data", (chunk) => { data += chunk; }); file.on("end", () => { resolve(data); }); file.on("error", () => resolve(data)); }); let timeout = null; const body = await Promise.race([ success, new Promise((resolve) => { timeout = setTimeout(() => { resolve(null); }, 5000); }) ]); if (timeout) { clearTimeout(timeout); } return body; }; // src/assets/download-file.ts var CANCELLED_ERROR = "cancelled"; var incorrectContentLengthToken = "Download finished with"; var noDataSentToken = "but the server sent no data for"; var downloadFileWithoutRetries = ({ onProgress, url, to: toFn, abortSignal }) => { return new Promise((resolve, reject) => { let rejected = false; let resolved = false; let timeout; const resolveAndFlag = (val) => { abortSignal.removeEventListener("abort", onAbort); resolved = true; resolve(val); if (timeout) { clearTimeout(timeout); } }; const rejectAndFlag = (err) => { abortSignal.removeEventListener("abort", onAbort); if (timeout) { clearTimeout(timeout); } reject(err); rejected = true; }; const refreshTimeout = () => { if (timeout) { clearTimeout(timeout); } timeout = setTimeout(() => { if (resolved) { return; } rejectAndFlag(new Error(`Tried to download file ${url}, ${noDataSentToken} 20 seconds`)); }, 20000); }; refreshTimeout(); let finishEventSent = false; let closeConnection = () => { return; }; const onAbort = () => { rejectAndFlag(new Error(CANCELLED_ERROR)); closeConnection(); }; abortSignal.addEventListener("abort", onAbort); readFile(url).then(({ response, request }) => { closeConnection = () => { request.destroy(); response.destroy(); }; if (abortSignal.aborted) { onAbort(); return; } const contentDisposition = response.headers["content-disposition"] ?? null; const contentType = response.headers["content-type"] ?? null; const to = toFn(contentDisposition, contentType); ensureOutputDirectory(to); const sizeHeader = response.headers["content-length"]; const totalSize = typeof sizeHeader === "undefined" ? null : Number(sizeHeader); const writeStream = createWriteStream(to); let downloaded = 0; writeStream.on("close", () => { if (rejected) { return; } if (!finishEventSent) { onProgress?.({ downloaded, percent: 1, totalSize: downloaded }); } refreshTimeout(); return resolveAndFlag({ sizeInBytes: downloaded, to }); }); writeStream.on("error", (err) => rejectAndFlag(err)); response.on("error", (err) => { closeConnection(); rejectAndFlag(err); }); response.pipe(writeStream).on("error", (err) => rejectAndFlag(err)); response.on("data", (d) => { refreshTimeout(); downloaded += d.length; refreshTimeout(); const percent = totalSize === null ? null : downloaded / totalSize; onProgress?.({ downloaded, percent, totalSize }); if (percent === 1) { finishEventSent = true; } }); response.on("close", () => { if (totalSize !== null && downloaded !== totalSize) { rejectAndFlag(new Error(`${incorrectContentLengthToken} ${downloaded} bytes, but expected ${totalSize} bytes from 'Content-Length'.`)); } writeStream.close(); closeConnection(); }); }).catch((err) => { rejectAndFlag(err); }); }); }; var downloadFile = async (options2, retries = 2, attempt = 1) => { try { const res = await downloadFileWithoutRetries(options2); return res; } catch (err) { const { message } = err; if (message === CANCELLED_ERROR) { throw err; } if (message === "aborted" || message.includes("ECONNRESET") || message.includes(incorrectContentLengthToken) || message.includes(noDataSentToken) || message.includes("503") || message.includes("502") || message.includes("504") || message.includes("500")) { if (retries === 0) { throw err; } Log.warn({ indent: options2.indent, logLevel: options2.logLevel }, `Downloading ${options2.url} failed (will retry): ${message}`); const backoffInSeconds = (attempt + 1) ** 2; await new Promise((resolve) => { setTimeout(() => resolve(), backoffInSeconds * 1000); }); return downloadFile(options2, retries - 1, attempt + 1); } throw err; } }; // src/browser.ts var DEFAULT_BROWSER = "chrome"; // src/browser/assert.ts var assert = (value, message) => { if (!value) { throw new Error(message); } }; // src/browser/BrowserPage.ts import { NoReactInternals as NoReactInternals2 } from "remotion/no-react"; // src/format-logs.ts import { NoReactInternals } from "remotion/no-react"; var formatRemoteObject = (remoteObject) => { if (remoteObject.preview) { return formatObjectPreview(remoteObject.preview); } if (remoteObject.type === "string") { const isDelayRenderClear = remoteObject.value.includes(NoReactInternals.DELAY_RENDER_CLEAR_TOKEN); if (isDelayRenderClear) { return chalk.gray(`${remoteObject.value}`); } return `${remoteObject.value}`; } if (remoteObject.type === "number") { return chalk.yellow(`${remoteObject.value}`); } if (remoteObject.type === "bigint") { return chalk.yellow(`${remoteObject.description}`); } if (remoteObject.type === "boolean") { return chalk.yellow(`${remoteObject.value}`); } if (remoteObject.type === "function") { return chalk.cyan(String(remoteObject.description)); } if (remoteObject.type === "object") { if (remoteObject.subtype === "null") { return `null`; } return chalk.reset(`Object`); } if (remoteObject.type === "symbol") { return chalk.green(`${remoteObject.description}`); } if (remoteObject.type === "undefined") { return chalk.gray(`undefined`); } throw new Error("unhandled remote object"); }; var formatObjectPreview = (preview) => { if (typeof preview === "undefined") { return ""; } if (preview.type === "object") { if (preview.subtype === "date") { return chalk.reset(`Date { ${chalk.magenta(String(preview.description))} }`); } const properties = preview.properties.map((property) => { return chalk.reset(`${property.name}: ${formatProperty(property)}`); }); if (preview.subtype === "array") { if (preview.overflow) { return chalk.reset(`[ ${preview.properties.map((p) => formatProperty(p)).join(", ")}, …]`); } return chalk.reset(`[ ${preview.properties.map((p) => formatProperty(p)).join(", ")} ]`); } if (preview.subtype === "arraybuffer") { return chalk.reset(String(preview.description)); } if (preview.subtype === "dataview") { return chalk.reset(String(preview.description)); } if (preview.subtype === "generator") { return chalk.reset(String(preview.description)); } if (preview.subtype === "iterator") { return chalk.reset(String(preview.description)); } if (preview.subtype === "map") { return chalk.reset(String(preview.description)); } if (preview.subtype === "node") { return chalk.magenta(`<${preview.description}>`); } if (preview.subtype === "null") { return chalk.white(String(preview.description)); } if (preview.subtype === "promise") { return chalk.reset(String(preview.description)); } if (preview.subtype === "proxy") { return chalk.reset(String(preview.description)); } if (preview.subtype === "regexp") { return chalk.red(String(preview.description)); } if (preview.subtype === "set") { return chalk.reset(String(preview.description)); } if (preview.subtype === "typedarray") { return chalk.reset(String(preview.description)); } if (preview.subtype === "error") { return chalk.reset(String(preview.description)); } if (preview.subtype === "wasmvalue") { return chalk.reset(String(preview.description)); } if (preview.subtype === "weakmap") { return chalk.reset(String(preview.description)); } if (preview.subtype === "weakset") { return chalk.reset(String(preview.description)); } if (preview.subtype === "webassemblymemory") { return chalk.reset(String(preview.description)); } if (properties.length === 0) { return chalk.reset("{}"); } if (preview.overflow) { return chalk.reset(`{ ${properties.join(", ")}, …}`); } return chalk.reset(`{ ${properties.join(", ")} }`); } return ""; }; var formatProperty = (property) => { if (property.type === "string") { return chalk.green(`"${property.value}"`); } if (property.type === "object") { if (!property.subtype && property.value === "Object") { return chalk.reset(`{…}`); } if (property.subtype === "date") { return chalk.reset(`Date { ${chalk.magenta(String(property.value))} }`); } if (property.subtype === "arraybuffer") { return chalk.reset(`${property.value}`); } if (property.subtype === "array") { return chalk.reset(`${property.value}`); } if (property.subtype === "dataview") { return chalk.reset(`${property.value}`); } if (property.subtype === "error") { return chalk.reset(`${property.value}`); } if (property.subtype === "generator") { return chalk.reset(`[generator ${property.value}]`); } if (property.subtype === "iterator") { return chalk.reset(`${property.value}`); } if (property.subtype === "map") { return chalk.reset(`${property.value}`); } if (property.subtype === "node") { return chalk.reset(`${property.value}`); } if (property.subtype === "null") { return chalk.white(`${property.value}`); } if (property.subtype === "promise") { return chalk.reset(`${property.value}`); } if (property.subtype === "proxy") { return chalk.reset(`${property.value}`); } if (property.subtype === "regexp") { return chalk.reset(`${property.value}`); } if (property.subtype === "set") { return chalk.reset(`${property.value}`); } if (property.subtype === "typedarray") { return chalk.reset(`${property.value}`); } if (property.subtype === "wasmvalue") { return chalk.reset(`${property.value}`); } if (property.subtype === "webassemblymemory") { return chalk.reset(`${property.value}`); } if (property.subtype === "weakmap") { return chalk.reset(`${property.value}`); } if (property.subtype === "weakset") { return chalk.reset(`${property.value}`); } return chalk.reset(`${property.value}`); } if (property.type === "accessor") { return chalk.gray(`get()`); } if (property.type === "bigint") { return chalk.yellow(`${property.value}`); } if (property.type === "boolean") { return chalk.yellow(`${property.value}`); } if (property.type === "function") { return chalk.cyan(`Function`); } if (property.type === "number") { return chalk.yellow(`${property.value}`); } if (property.type === "symbol") { return chalk.green(`${property.value}`); } if (property.type === "undefined") { return chalk.gray(`undefined`); } throw new Error("unexpected property type " + JSON.stringify(property)); }; // src/browser/ConsoleMessage.ts class ConsoleMessage { type; text; args; previewString; #stackTraceLocations; logLevel; tag; constructor({ type, text, args, stackTraceLocations, previewString, logLevel, tag }) { this.type = type; this.text = text; this.args = args; this.previewString = previewString; this.#stackTraceLocations = stackTraceLocations; this.logLevel = logLevel; this.tag = tag; } stackTrace() { return this.#stackTraceLocations; } } // src/browser/mitt/index.ts function mitt(all) { all = all || new Map; return { all, on: (type, handler) => { const handlers = all?.get(type); const added = handlers?.push(handler); if (!added) { all?.set(type, [handler]); } }, off: (type, handler) => { const handlers = all?.get(type); if (handlers) { handlers.splice(handlers.indexOf(handler) >>> 0, 1); } }, emit: (type, evt) => { (all?.get(type) || []).slice().forEach((handler) => { handler(evt); }); (all?.get("*") || []).slice().forEach((handler) => { handler(type, evt); }); } }; } // src/browser/EventEmitter.ts class EventEmitter { emitter; eventsMap = new Map; constructor() { this.emitter = mitt(this.eventsMap); } on(event, handler) { this.emitter.on(event, handler); return this; } off(event, handler) { this.emitter.off(event, handler); return this; } addListener(event, handler) { this.on(event, handler); return this; } emit(event, eventData) { this.emitter.emit(event, eventData); return this.eventListenersCount(event) > 0; } once(event, handler) { const onceHandler = (eventData) => { handler(eventData); this.off(event, onceHandler); }; return this.on(event, onceHandler); } listenerCount(event) { return this.eventListenersCount(event); } removeAllListeners(event) { if (event) { this.eventsMap.delete(event); } else { this.eventsMap.clear(); } return this; } eventListenersCount(event) { return this.eventsMap.get(event)?.length || 0; } } // src/browser/Errors.ts class CustomError extends Error { constructor(message) { super(message); this.name = this.constructor.name; Error.captureStackTrace(this, this.constructor); } } class TimeoutError extends CustomError { } class ProtocolError extends CustomError { code; originalMessage = ""; } // src/browser/Connection.ts var ConnectionEmittedEvents = { Disconnected: Symbol("Connection.Disconnected") }; class Connection extends EventEmitter { transport; #lastId = 0; #sessions = new Map; #closed = false; #callbacks = new Map; constructor(transport) { super(); this.transport = transport; this.transport.onmessage = this.#onMessage.bind(this); this.transport.onclose = this.#onClose.bind(this); } static fromSession(session) { return session.connection(); } session(sessionId) { return this.#sessions.get(sessionId) || null; } send(method, ...paramArgs) { const params = paramArgs.length ? paramArgs[0] : undefined; const id = this._rawSend({ method, params }); return new Promise((resolve, reject) => { this.#callbacks.set(id, { resolve, reject, method, returnSize: true, stack: new Error().stack ?? "", fn: method + JSON.stringify(params) }); }); } _rawSend(message) { const id = ++this.#lastId; const stringifiedMessage = JSON.stringify({ ...message, id }); this.transport.send(stringifiedMessage); return id; } #onMessage(message) { const object = JSON.parse(message); if (object.method === "Target.attachedToTarget") { const { sessionId } = object.params; const session = new CDPSession(this, object.params.targetInfo.type, sessionId); this.#sessions.set(sessionId, session); this.emit("sessionattached", session); const parentSession = this.#sessions.get(object.sessionId); if (parentSession) { parentSession.emit("sessionattached", session); } } else if (object.method === "Target.detachedFromTarget") { const session = this.#sessions.get(object.params.sessionId); if (session) { session._onClosed(); this.#sessions.delete(object.params.sessionId); this.emit("sessiondetached", session); const parentSession = this.#sessions.get(object.sessionId); if (parentSession) { parentSession.emit("sessiondetached", session); } } } if (object.sessionId) { const session = this.#sessions.get(object.sessionId); if (session) { session._onMessage(object, message.length); } } else if (object.id) { const callback = this.#callbacks.get(object.id); if (callback) { this.#callbacks.delete(object.id); if (object.error) { callback.reject(createProtocolError(callback.method, object)); } else if (callback.returnSize) { callback.resolve({ value: object.result, size: message.length }); } else { callback.resolve(object.result); } } } else { this.emit(object.method, object.params); } } #onClose() { if (this.#closed) { return; } this.transport.onmessage = undefined; this.transport.onclose = undefined; for (const callback of this.#callbacks.values()) { callback.reject(rewriteError(new ProtocolError, `Protocol error (${callback.method}): Target closed. https://www.remotion.dev/docs/target-closed`)); } this.#callbacks.clear(); for (const session of this.#sessions.values()) { session._onClosed(); } this.#sessions.clear(); this.emit(ConnectionEmittedEvents.Disconnected); } dispose() { this.#onClose(); this.transport.close(); } async createSession(targetInfo) { const { value: { sessionId } } = await this.send("Target.attachToTarget", { targetId: targetInfo.targetId, flatten: true }); const session = this