Files
ElyOffice/site/video/opening/render.mjs
T

58 lines
2.5 KiB
JavaScript

// Renders the opening's global frames to PNG, manifest and preview.
import { spawnSync } from "node:child_process";
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { chromium } from "../scenes/node_modules/playwright/index.mjs";
import { createServer } from "vite";
const here = dirname(fileURLToPath(import.meta.url));
const site = resolve(here, "../..");
const extra = resolve(here, "../out/extra");
const dir = join(extra, "opening");
const PAGES = 6;
const server = await createServer({ root: site, configFile: false, logLevel: "error", server: { port: 0 } });
await server.listen();
const url = `${server.resolvedUrls.local[0]}video/opening/index.html`;
const browser = await chromium.launch();
/** A film-sized page; any page error stops the run. */
async function open() {
const page = await browser.newPage({ viewport: { width: 1920, height: 1080 }, deviceScaleFactor: 1 });
page.on("pageerror", (e) => {
throw e;
});
await page.goto(url, { waitUntil: "networkidle" });
return page;
}
const pages = await Promise.all(Array.from({ length: PAGES }, open));
const { first, end } = await pages[0].evaluate(() => ({ first: window.opening.first, end: window.opening.end }));
const only = process.argv.slice(2).map(Number);
const frames = only.length ? only : Array.from({ length: end - first }, (_, i) => first + i);
if (!only.length) rmSync(dir, { recursive: true, force: true });
mkdirSync(dir, { recursive: true });
const queue = [...frames];
await Promise.all(
pages.map(async (page) => {
for (let f = queue.shift(); f !== undefined; f = queue.shift()) {
await page.evaluate((f) => window.opening.render(f), f);
await page.screenshot({ path: join(dir, `${String(f).padStart(5, "0")}.png`) });
}
}),
);
await browser.close();
await server.close();
if (!only.length) {
const manifest = { name: "opening", first, count: end - first, fps: 30, kind: "base" };
writeFileSync(join(dir, "manifest.json"), JSON.stringify(manifest, null, 1));
const args = ["-y", "-v", "error", "-framerate", "30", "-start_number", String(first), "-i", join(dir, "%05d.png")];
args.push("-c:v", "libx264", "-preset", "slow", "-crf", "16", "-pix_fmt", "yuv420p", "-movflags", "+faststart");
const run = spawnSync("ffmpeg", [...args, join(extra, "opening.mp4")], { stdio: "inherit" });
if (run.status !== 0) throw new Error("ffmpeg failed");
console.log(`opening: frames ${first}..${end - 1} (${end - first})`);
}