folx-tv/server/image-optimizer.ts
sebastjanartic 3c23a20652 Automatically optimize uploaded images for faster loading
Add image optimization module using sharp to automatically convert uploaded images to WebP format, generate thumbnails, and delete originals.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 517dfa7b-26ac-463d-a6e1-a58c6df97188
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 3972346d-247c-4913-af41-cab40bf9aec3
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/517dfa7b-26ac-463d-a6e1-a58c6df97188/drGbo1a
Replit-Helium-Checkpoint-Created: true
2026-02-28 21:12:36 +00:00

38 lines
1.1 KiB
TypeScript

import sharp from "sharp";
import path from "path";
import fs from "fs";
const uploadDir = path.join(process.cwd(), "client/public/uploads");
export async function optimizeImage(filePath: string): Promise<{ webp: string; thumb: string }> {
const ext = path.extname(filePath);
const baseName = path.basename(filePath, ext);
const webpPath = path.join(uploadDir, `${baseName}.webp`);
const thumbPath = path.join(uploadDir, `${baseName}-thumb.webp`);
const image = sharp(filePath);
const metadata = await image.metadata();
const width = metadata.width || 1200;
await sharp(filePath)
.resize({ width: Math.min(width, 1200), withoutEnlargement: true })
.webp({ quality: 80 })
.toFile(webpPath);
await sharp(filePath)
.resize({ width: 400, withoutEnlargement: true })
.webp({ quality: 65 })
.toFile(thumbPath);
if (filePath !== webpPath && ext.toLowerCase() !== ".webp") {
fs.unlinkSync(filePath);
}
console.log(`[image-optimizer] Optimized: ${baseName}.webp (full + thumb)`);
return {
webp: `/uploads/${baseName}.webp`,
thumb: `/uploads/${baseName}-thumb.webp`,
};
}