/** * 🖼️ 14 风格 × 100 = 1400 个 透明底 PNG 渲染脚本(512×512) * 读取 output/agent-avatars-png/avatars/{style}/{file}.svg, * Chrome headless 截图 → 透明背景 PNG(SVG 自带圆底,外部透明)。 * * 用法:node scripts/gen-avatars-png.js */ 'use strict'; const fs = require('fs'); const path = require('path'); const { spawn } = require('child_process'); const ROOT = path.resolve(__dirname, '..'); const SVG_ROOT = path.join(ROOT, 'output', 'agent-avatars-png', 'avatars'); const TMP_DIR = path.join(ROOT, 'output', '.tmp-av'); const CHROME = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'; const SIZE = 512; // —— 1. 收集全部 SVG 文件 —— const files = []; for (const dir of fs.readdirSync(SVG_ROOT, { withFileTypes: true })) { if (!dir.isDirectory()) continue; for (const f of fs.readdirSync(path.join(SVG_ROOT, dir.name))) { if (f.endsWith('.svg')) files.push(path.join(dir.name, f)); } } files.sort(); console.log('📦 待渲染 SVG:' + files.length + ' 个'); // —— 2. 生成 HTML(透明背景 + SVG 居中,放大到 SIZE)—— fs.mkdirSync(TMP_DIR, { recursive: true }); const jobs = files.map((rel, i) => { const svg = fs.readFileSync(path.join(SVG_ROOT, rel), 'utf8'); const html = `
${svg.replace('`; const hf = path.join(TMP_DIR, 'a' + i + '.html'); fs.writeFileSync(hf, html, 'utf8'); return { hf, out: path.join(SVG_ROOT, rel.replace(/\.svg$/, '.png')) }; }); // —— 3. 并发截图(透明底)—— function shot(job) { return new Promise((res) => { const p = spawn(CHROME, [ '--headless=new', '--disable-gpu', '--hide-scrollbars', '--default-background-color=00000000', '--force-device-scale-factor=1', '--window-size=' + SIZE + ',' + SIZE, '--virtual-time-budget=600', '--screenshot=' + job.out, 'file:///' + job.hf.replace(/\\/g, '/') ], { stdio: 'ignore' }); p.on('close', () => res()); p.on('error', () => res()); }); } (async () => { let done = 0, t0 = Date.now(); const CONC = 8; for (let s = 0; s < jobs.length; s += CONC) { const batch = jobs.slice(s, s + CONC); await Promise.all(batch.map(shot)); done += batch.length; if (done % 200 === 0 || done === jobs.length) { console.log(`⏳ ${done}/${jobs.length} ${((Date.now() - t0) / 1000).toFixed(1)}s`); } } fs.rmSync(TMP_DIR, { recursive: true, force: true }); console.log('🎉 完成 → 透明底 PNG(512×512),与 SVG 同目录'); })();