2026-01-28 23:00:58 -05:00

80 lines
2.5 KiB
JavaScript

#!/usr/bin/env node
/**
* Scroll-driven animation capture
* Interpolates scrollProgress from 0 to 1 across frames
*/
import puppeteer from 'puppeteer';
import { execSync } from 'child_process';
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const outputDir = path.join(__dirname, 'output/scroll-frames');
const htmlFile = path.join(__dirname, 'output/stripe-scroll.html');
// Clean and create output dir
fs.rmSync(outputDir, { recursive: true, force: true });
fs.mkdirSync(outputDir, { recursive: true });
async function captureFrames() {
const browser = await puppeteer.launch({
headless: true,
executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
args: ['--no-sandbox']
});
const page = await browser.newPage();
await page.setViewport({ width: 1920, height: 1080 });
// 12 seconds at 30fps = 360 frames
const fps = 30;
const duration = 12;
const totalFrames = fps * duration;
console.log(`Capturing ${totalFrames} frames...`);
// Load page and wait for fonts
await page.goto(`file://${htmlFile}`, { waitUntil: 'networkidle0' });
await new Promise(r => setTimeout(r, 500));
for (let i = 0; i < totalFrames; i++) {
// Calculate scroll progress (0 to 1)
// Add a small ease to the overall progression for smoother feel
const linearProgress = i / (totalFrames - 1);
const scrollProgress = linearProgress; // Keep linear for now, easing is in the HTML
// Update the scene
await page.evaluate((progress) => {
window.updateScene(progress);
}, scrollProgress);
// Small delay to let CSS transitions settle
await new Promise(r => setTimeout(r, 16));
const frameNum = String(i + 1).padStart(4, '0');
await page.screenshot({
path: path.join(outputDir, `frame-${frameNum}.png`),
type: 'png'
});
if (i % 30 === 0) console.log(`Frame ${i + 1}/${totalFrames} (${Math.round(linearProgress * 100)}%)`);
}
await browser.close();
// Create MP4
console.log('Creating MP4...');
const mp4Path = path.join(__dirname, 'output/stripe-scroll.mp4');
try {
execSync(`ffmpeg -y -framerate ${fps} -i "${outputDir}/frame-%04d.png" -c:v libx264 -pix_fmt yuv420p -crf 18 "${mp4Path}"`, { stdio: 'inherit' });
console.log(`\n✓ MP4 created: ${mp4Path}`);
} catch (e) {
console.error('FFmpeg error:', e.message);
}
}
captureFrames().catch(console.error);