#!/usr/bin/env node /* ========================================================================== 预览帧:hv shot -------------------------------------------------------------------------- 改完组件先抽几帧看看,比直接渲染整条快一个数量级。 底层用的是渲染引擎自带的 snapshot,它按时间点精确抽帧, 还会顺便输出一张 contact sheet 拼图方便一次看完。 用法: hv 看帧 <项目名> [--时间 1,3,5] [--数 5] [--缩放 .editor] [--输出 目录] ========================================================================== */ import path from "node:path"; import fs from "node:fs"; import { fileURLToPath } from "node:url"; import { execFileSync } from "node:child_process"; const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); export async function shotCLI(argv) { const arg = (k) => { const i = argv.indexOf(k); return i >= 0 ? argv[i + 1] : undefined; }; const name = argv[0]; if (!name) { console.log("用法: hv 看帧 <项目名> [--时间 1,3,5] [--数 5] [--缩放 .editor] [--输出 目录]"); process.exit(1); } const dir = path.join(ROOT, "projects", name); if (!fs.existsSync(dir)) { console.error(`✗ 项目不存在:${name}`); process.exit(1); } if (!fs.existsSync(path.join(dir, "index.html"))) { console.error("✗ 还没有 index.html,先执行 hv build"); process.exit(1); } const at = arg("--时间") || arg("--at"); const count = arg("--数") || arg("--frames") || "5"; const zoom = arg("--缩放") || arg("--zoom"); const outDir = arg("--输出") || arg("--output") || path.join(dir, "snapshots"); const bin = path.join(ROOT, "node_modules/.bin/hyperframes"); const argvHf = ["snapshot", dir, "--output", outDir]; if (at) argvHf.push("--at", at, "--no-end"); else argvHf.push("--frames", count); if (zoom) argvHf.push("--zoom", zoom); console.log(`正在抽帧:${name} ${at ? `时间点 ${at}s` : `${count} 帧`}`); try { const out = execFileSync(fs.existsSync(bin) ? bin : "npx", argvHf, { encoding: "utf8", maxBuffer: 32 * 1024 * 1024, }); process.stdout.write(out); } catch (e) { if (e.stdout) process.stdout.write(e.stdout); if (e.stderr) process.stderr.write(e.stderr); process.exit(1); } console.log(`\n看图目录:${outDir.replace(ROOT + "/", "")}`); console.log(`${C("contact-sheet.jpg")} 是所有帧的拼图,一张看完整条时间轴。\n`); } const C = (s) => `\x1b[36m${s}\x1b[0m`; if (import.meta.url === `file://${process.argv[1]}`) { try { await shotCLI(process.argv.slice(2)); } catch (e) { console.error("✗ " + e.message); process.exit(1); } }