import { spawn } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import process from "node:process"; import { fileURLToPath } from "node:url"; const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); function parseArgs(argv) { const args = {}; for (let index = 0; index < argv.length; index += 1) { const current = argv[index]; if (current.startsWith("--")) { args[current.slice(2)] = argv[index + 1]; index += 1; } } return args; } function fail(message) { console.error(message); process.exit(1); } const args = parseArgs(process.argv.slice(2)); const propsPath = args.props ? path.resolve(rootDir, args.props) : null; const outputPath = args.output ? path.resolve(rootDir, args.output) : null; if (!propsPath || !fs.existsSync(propsPath)) { fail("Missing or unreadable --props JSON file."); } if (!outputPath || path.extname(outputPath).toLowerCase() !== ".mp4") { fail("Missing --output MP4 path."); } const props = JSON.parse(fs.readFileSync(propsPath, "utf8")); fs.mkdirSync(path.dirname(outputPath), { recursive: true }); const preview = String(args.preview || "").toLowerCase() === "true"; const scale = args.scale ? String(args.scale) : null; const remotionCli = path.join( rootDir, "node_modules", "@remotion", "cli", "remotion-cli.js", ); if (!fs.existsSync(remotionCli)) { fail("Local Remotion CLI was not found. Run npm install first."); } const plan = props.plan ?? props; if (preview && plan && typeof plan === "object") { plan.preview_quality = true; fs.writeFileSync(propsPath, JSON.stringify(props, null, 2)); } const format = (plan?.video_format || plan?.format || "").toLowerCase().trim(); const compositionId = format === "16:9" || format === "landscape" || format === "16-9" ? "ExplainerVideo" : format === "9:16" || format === "vertical" || format === "9-16" ? "ExplainerVideoVertical" : plan?.video_format === "9:16" || plan?.visual_style === "anime_visual_explainer" || plan?.style === "anime_visual_explainer" ? "ExplainerVideoVertical" : "ExplainerVideo"; const renderArgs = [ remotionCli, "render", "src/remotion/GeneratedVideoRoot.tsx", compositionId, outputPath, "--props", propsPath, ]; if (scale) { renderArgs.push("--scale", scale); } const child = spawn( process.execPath, renderArgs, { cwd: rootDir, shell: false, stdio: "inherit", }, ); child.on("exit", (code) => { process.exit(code ?? 1); }); child.on("error", (error) => { console.error(error); process.exit(1); });