import { Command } from 'commander'; import puppeteer from 'puppeteer'; import fs from 'fs'; const program = new Command(); program .requiredOption('-o, --output ', 'Output directory') .requiredOption('--fps ', 'Frames per second') .requiredOption('--cycles ', 'Number of cycles') .requiredOption('--size ', 'Size of the output in pixels') .requiredOption('--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); for (let frame = 0; frame < totalFrames; frame++) { let start = Date.now(); await page.evaluate(async (n) => { // @ts-ignore await window.setFrame(n); }, frame); 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 + 1}/${totalFrames} (took ${end - start}ms)`); } console.log('Done.'); await browser.close();