Files
infiplot-web/scripts/optimize-home-images.mjs
DESKTOP-I1T6TF3\Q bed4dc5a8f feat(web): gender-differentiated 4:5 covers + per-card styleGuide prebake
- Regenerate 60 covers (30 male + 30 female) via FLUX with story-specific
  prompts, replacing the prior gender-shared set
- Crop covers to 4:5 (960×1200) via sharp attention cover; matches new
  homepage card aspectRatio
- Persist all 60 prompts to public/home/prompts.json so the prebake step
  can reuse the cover's exact visual anchor (per-card styleGuide) and the
  first-act scene visually carries over from the poster the player clicked
- Restore /play?card= prebaked instant-play path on homepage card click
- Add OpenAI-compatible image route in ai-client for non-Runware endpoints
- Hide Next.js dev indicators globally; tweak F-key fullscreen label

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 02:26:35 +08:00

52 lines
1.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* Compresses the freshly generated public/home/*.png into much
* smaller .webp files alongside them, then deletes the originals.
* Crops each image to a 4:5 vertical aspect ratio (matching the homepage
* StoryCard layout in app/page.tsx) using sharp's smart-attention cover
* strategy, so the most salient subject stays in frame. Output webps
* target 960×1200 at quality 78.
*/
import { readdirSync, statSync, unlinkSync } from "node:fs";
import { resolve, dirname, extname, basename } from "node:path";
import { fileURLToPath } from "node:url";
import sharp from "sharp";
const __dirname = dirname(fileURLToPath(import.meta.url));
const DIR = resolve(__dirname, "..", "public", "home");
// 4:5 final, 1200 long edge → 960×1200
const TARGET_W = 960;
const TARGET_H = 1200;
const QUALITY = 78;
const files = readdirSync(DIR).filter((f) => f.toLowerCase().endsWith(".png"));
let totalIn = 0;
let totalOut = 0;
for (const f of files) {
const inPath = resolve(DIR, f);
const outPath = resolve(DIR, basename(f, extname(f)) + ".webp");
const inSize = statSync(inPath).size;
totalIn += inSize;
await sharp(inPath)
.resize({
width: TARGET_W,
height: TARGET_H,
fit: "cover",
position: sharp.strategy.attention,
})
.webp({ quality: QUALITY, effort: 5 })
.toFile(outPath);
const outSize = statSync(outPath).size;
totalOut += outSize;
console.log(`${f.padEnd(16)} ${(inSize / 1024).toFixed(0).padStart(5)} KB → ${(outSize / 1024).toFixed(0).padStart(4)} KB`);
unlinkSync(inPath);
}
console.log(
`\nTotal: ${(totalIn / 1024 / 1024).toFixed(1)} MB → ${(totalOut / 1024 / 1024).toFixed(2)} MB`,
);