test-card/av-sync/render-video.js

51 lines
1.5 KiB
JavaScript

import { Command } from 'commander';
import puppeteer from 'puppeteer';
import fs from 'fs';
const program = new Command();
program
.requiredOption('-o, --output <output>', 'Output directory')
.requiredOption('--fps <fps>', 'Frames per second')
.requiredOption('--cycles <cycles>', 'Number of cycles')
.requiredOption('--size <size>', 'Size of the output in pixels')
.requiredOption('--url <url>', 'URL to render')
.parse(process.argv);
const options = program.opts();
// mkdir p output path
if (!fs.existsSync(options.output)) {
fs.mkdirSync(options.output, { recursive: true });
}
const browser = await puppeteer.launch({
args: ['--no-sandbox']
});
const page = await browser.newPage();
await page.setViewport({ width: parseInt(options.size, 10), height: parseInt(options.size, 10) });
await page.goto(options.url);
await page.evaluate(async (fps) => {
// @ts-ignore
await window.setFps(fps);
}, options.fps);
const totalFrames = parseInt(options.fps) * parseInt(options.cycles);
const half = Math.floor(parseInt(options.fps) / 2);
for (let frame = 0; frame < totalFrames; frame++) {
let start = Date.now();
await page.evaluate(async (n) => {
// @ts-ignore
await window.setFrame(n);
}, frame + half);
const path = `${options.output}/${frame.toString().padStart(Math.log10(totalFrames) + 1, '0')}.png`;
await page.screenshot({ path, omitBackground: true });
let end = Date.now();
console.log(
`Captured frame ${frame + half}: ${frame + 1}/${totalFrames} (took ${end - start}ms)`
);
}
console.log('Done.');
await browser.close();