Files
haiyushuke-website/scripts/optimize-hero-banner.mjs

75 lines
1.7 KiB
JavaScript
Raw Normal View History

2026-06-19 18:18:11 +08:00
/**
* public/banner.mp4 banner.source.mp4压成首屏 Hero 尺寸
* 用法pnpm run optimize:banner
* 可选把未压缩母带重命名为 banner.source.mp4脚本会优先读取它并写回 banner.mp4
*/
import { execFileSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import ffmpegPath from "ffmpeg-static";
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
const publicDir = path.join(root, "public");
const sourceCandidates = [
path.join(publicDir, "banner.source.mp4"),
path.join(publicDir, "banner.mp4"),
];
const input = sourceCandidates.find((p) => fs.existsSync(p));
if (!input || !ffmpegPath) {
console.error("缺少 banner.mp4 / banner.source.mp4 或 ffmpeg 二进制。");
process.exit(1);
}
const outMp4 = path.join(publicDir, "banner.mp4");
const outWebm = path.join(publicDir, "banner.webm");
const tmpMp4 = path.join(publicDir, "banner.opt.mp4");
const scale = "scale=1920:-2";
const common = ["-y", "-i", input, "-an", "-vf", scale, "-pix_fmt", "yuv420p"];
console.log(`输入: ${input}`);
execFileSync(
ffmpegPath,
[
...common,
"-c:v",
"libx264",
"-preset",
"slow",
"-crf",
"28",
"-movflags",
"+faststart",
tmpMp4,
],
{ stdio: "inherit" },
);
execFileSync(
ffmpegPath,
[
...common,
"-c:v",
"libvpx-vp9",
"-crf",
"35",
"-b:v",
"0",
"-row-mt",
"1",
outWebm,
],
{ stdio: "inherit" },
);
fs.copyFileSync(tmpMp4, outMp4);
fs.unlinkSync(tmpMp4);
for (const f of [outMp4, outWebm]) {
const kb = (fs.statSync(f).size / 1024).toFixed(1);
console.log(`${path.basename(f)}: ${kb} KiB`);
}