96 lines
2.4 KiB
Text
96 lines
2.4 KiB
Text
// api_v1/scanner/thumbs.js
|
|
const sharp = require('sharp');
|
|
const { exec } = require('child_process');
|
|
const path = require('path');
|
|
|
|
function deriveCastPathFromAvg(thumbAvgPath) {
|
|
if (!thumbAvgPath) return null;
|
|
|
|
// Caso standard: IMG_0241_avg.jpg -> IMG_0241_cast.jpg
|
|
if (thumbAvgPath.toLowerCase().endsWith('_avg.jpg')) {
|
|
return thumbAvgPath.replace(/_avg\.jpg$/i, '_cast.jpg');
|
|
}
|
|
|
|
// Fallback generico
|
|
const ext = path.extname(thumbAvgPath);
|
|
const base = thumbAvgPath.slice(0, -ext.length);
|
|
return `${base}_cast.jpg`;
|
|
}
|
|
|
|
// Video: lascia solo avg + min
|
|
function createVideoThumbnail(videoPath, thumbMinPath, thumbAvgPath) {
|
|
return new Promise((resolve) => {
|
|
const cmd = `
|
|
ffmpeg -y -i "${videoPath}" -ss 00:00:01.000 -vframes 1 "${thumbAvgPath}" &&
|
|
ffmpeg -y -i "${thumbAvgPath}" -vf "scale=100:-1" "${thumbMinPath}"
|
|
`;
|
|
|
|
exec(cmd, () => resolve());
|
|
});
|
|
}
|
|
|
|
// Foto: min + avg + cast
|
|
async function createThumbnails(filePath, thumbMinPath, thumbAvgPath, thumbCastPath) {
|
|
try {
|
|
const finalCastPath = thumbCastPath || deriveCastPathFromAvg(thumbAvgPath);
|
|
|
|
// 1) MIN: 100px
|
|
await sharp(filePath)
|
|
.rotate()
|
|
.resize({
|
|
width: 100,
|
|
height: 100,
|
|
fit: 'inside',
|
|
withoutEnlargement: true,
|
|
})
|
|
.jpeg({
|
|
quality: 75,
|
|
progressive: false,
|
|
optimizeCoding: true,
|
|
})
|
|
.toFile(thumbMinPath);
|
|
|
|
// 2) AVG: 400px
|
|
await sharp(filePath)
|
|
.rotate()
|
|
.resize({
|
|
width: 400,
|
|
fit: 'inside',
|
|
withoutEnlargement: true,
|
|
})
|
|
.jpeg({
|
|
quality: 78,
|
|
progressive: false,
|
|
optimizeCoding: true,
|
|
})
|
|
.toFile(thumbAvgPath);
|
|
|
|
// 3) CAST: max 4K TV, dentro 3840x2160, senza crop
|
|
// 3) CAST: metà del 4K → 1920x1080, senza crop
|
|
if (finalCastPath) {
|
|
await sharp(filePath)
|
|
.rotate()
|
|
.resize({
|
|
width: 1920,
|
|
height: 1080,
|
|
fit: 'inside',
|
|
withoutEnlargement: true,
|
|
fastShrinkOnLoad: true,
|
|
})
|
|
.jpeg({
|
|
quality: 85,
|
|
progressive: false,
|
|
optimizeCoding: true,
|
|
})
|
|
.toFile(finalCastPath);
|
|
}
|
|
|
|
} catch (err) {
|
|
console.error('Errore creazione thumbnails:', err.message, filePath);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
createVideoThumbnail,
|
|
createThumbnails,
|
|
};
|