silvester-23/bin/compress_s3.js

107 lines
2.8 KiB
JavaScript

import { Client } from "minio";
import sharp from "sharp"
import {config} from "dotenv"
config()
// Retrieve MinIO details from environment variables
const minioEndpoint = process.env["S3_ENDPOINT_URL"] || "your-minio-endpoint";
const minioAccessKey = process.env["S3_ACCESS_KEY"] || "your-access-key";
const minioSecretKey = process.env["S3_SECRET_ACCESS_KEY"] || "your-secret-key";
const minioBucketName = "silvester23";
const minioClient = new Client({
endPoint: minioEndpoint,
accessKey: minioAccessKey,
secretKey: minioSecretKey,
});
const objects = [];
const objectStream = minioClient.listObjects(minioBucketName);
for await (const obj of objectStream) {
objects.push(obj);
}
async function compressObject(pngBuffer, fileName, format) {
const newFilePath = `${fileName.slice(0, -4)}.${format}`;
let buffer;
switch (format) {
case "webp":
buffer = await sharp(pngBuffer).webp({ quality: 80 }).toBuffer();
break;
case "jpg":
buffer = await sharp(pngBuffer).jpeg({ quality: 80 }).toBuffer();
break;
case "avif":
buffer = await sharp(pngBuffer).avif({ quality: 80 }).toBuffer();
break;
default:
throw new Error(`Unknown format ${format}`);
}
// Upload the JPG buffer back to the same MinIO bucket
await minioClient.putObject(minioBucketName, newFilePath, buffer, {
'Content-Type': 'image/' + format,
});
console.log(`Uploaded ${newFilePath} to MinIO`);
}
async function fetchBuffer(objectName) {
const chunks = [];
return new Promise((res, rej) => {
minioClient.getObject(minioBucketName,objectName, function (err, dataStream) {
if (err) {
return console.log(err)
}
dataStream.on('data', function (chunk) {
chunks.push(chunk);
})
dataStream.on('end', function () {
res(Buffer.concat(chunks))
})
dataStream.on('error', function (err) {
console.log(err)
rej(err)
})
})
})
}
const pngs = objects.filter((o) => o.name.endsWith(".png"));
console.log(`Found ${pngs.length} PNGs`);
for (const obj of pngs) {
const pngFilePath = obj.name;
const jpgFilePath = pngFilePath.slice(0, -4) + ".jpg";
const avifFilePath = pngFilePath.slice(0, -4) + ".avif";
const webpFilePath = pngFilePath.slice(0, -4) + ".webp";
const hasJpg = objects.some((o) => o.name === jpgFilePath);
const hasAvif = objects.some((o) => o.name === avifFilePath);
const hasWebp = objects.some((o) => o.name === webpFilePath);
if(hasAvif && hasJpg && hasWebp) {
continue;
}
const pngBuffer = await fetchBuffer(pngFilePath);
if(!hasJpg) {
await compressObject(pngBuffer, pngFilePath, "jpg");
}
if(!hasAvif) {
await compressObject(pngBuffer, pngFilePath, "avif");
}
if(!hasWebp) {
await compressObject(pngBuffer, pngFilePath, "webp");
}
}