2020-07-02 02:11:51 +02:00
|
|
|
const jetpack = require('fs-jetpack');
|
|
|
|
const path = require('path');
|
|
|
|
const sharp = require('sharp');
|
|
|
|
const ffmpeg = require('fluent-ffmpeg');
|
2020-07-02 22:42:44 +02:00
|
|
|
const previewUtil = require('./videoPreview/FragmentPreview');
|
2020-07-02 02:11:51 +02:00
|
|
|
|
2020-07-02 02:42:20 +02:00
|
|
|
const log = require('./Log');
|
2020-07-02 02:11:51 +02:00
|
|
|
|
|
|
|
class ThumbUtil {
|
2020-07-02 02:42:20 +02:00
|
|
|
static imageExtensions = ['.jpg', '.jpeg', '.gif', '.png', '.webp'];
|
2020-07-08 01:32:12 +02:00
|
|
|
|
2020-07-02 02:42:20 +02:00
|
|
|
static videoExtensions = ['.webm', '.mp4', '.wmv', '.avi', '.mov'];
|
|
|
|
|
2020-07-08 01:32:12 +02:00
|
|
|
static thumbPath = path.join(__dirname, '../../../', process.env.UPLOAD_FOLDER, 'thumbs');
|
|
|
|
|
|
|
|
static squareThumbPath = path.join(__dirname, '../../../', process.env.UPLOAD_FOLDER, 'thumbs', 'square');
|
|
|
|
|
|
|
|
static videoPreviewPath = path.join(__dirname, '../../../', process.env.UPLOAD_FOLDER, 'thumbs', 'preview');
|
2020-07-02 02:42:20 +02:00
|
|
|
|
2020-07-02 02:11:51 +02:00
|
|
|
static generateThumbnails(filename) {
|
|
|
|
const ext = path.extname(filename).toLowerCase();
|
|
|
|
const output = `${filename.slice(0, -ext.length)}.png`;
|
2020-07-02 19:13:05 +02:00
|
|
|
const previewOutput = `${filename.slice(0, -ext.length)}.webm`;
|
2020-07-02 02:42:20 +02:00
|
|
|
|
2020-07-08 01:32:12 +02:00
|
|
|
if (ThumbUtil.imageExtensions.includes(ext)) return ThumbUtil.generateThumbnailForImage(filename, output);
|
|
|
|
if (ThumbUtil.videoExtensions.includes(ext)) return ThumbUtil.generateThumbnailForVideo(filename, previewOutput);
|
2020-07-02 02:11:51 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
static async generateThumbnailForImage(filename, output) {
|
2020-07-02 02:42:20 +02:00
|
|
|
const filePath = path.join(__dirname, '..', '..', '..', process.env.UPLOAD_FOLDER, filename);
|
|
|
|
|
|
|
|
const file = await jetpack.readAsync(filePath, 'buffer');
|
2020-07-02 02:11:51 +02:00
|
|
|
await sharp(file)
|
|
|
|
.resize(64, 64)
|
|
|
|
.toFormat('png')
|
2020-07-02 02:42:20 +02:00
|
|
|
.toFile(path.join(ThumbUtil.squareThumbPath, output));
|
2020-07-02 02:11:51 +02:00
|
|
|
await sharp(file)
|
|
|
|
.resize(225, null)
|
|
|
|
.toFormat('png')
|
2020-07-02 02:42:20 +02:00
|
|
|
.toFile(path.join(ThumbUtil.thumbPath, output));
|
2020-07-02 02:11:51 +02:00
|
|
|
}
|
|
|
|
|
2020-07-02 19:13:05 +02:00
|
|
|
static async generateThumbnailForVideo(filename, output) {
|
2020-07-02 02:42:20 +02:00
|
|
|
const filePath = path.join(__dirname, '..', '..', '..', process.env.UPLOAD_FOLDER, filename);
|
|
|
|
|
|
|
|
ffmpeg(filePath)
|
2020-07-02 02:11:51 +02:00
|
|
|
.thumbnail({
|
|
|
|
timestamps: [0],
|
|
|
|
filename: '%b.png',
|
2020-07-02 02:42:20 +02:00
|
|
|
folder: ThumbUtil.squareThumbPath,
|
2020-07-08 01:32:12 +02:00
|
|
|
size: '64x64',
|
2020-07-02 02:11:51 +02:00
|
|
|
})
|
2020-07-08 01:32:12 +02:00
|
|
|
.on('error', (error) => log.error(error.message));
|
2020-07-02 02:42:20 +02:00
|
|
|
|
|
|
|
ffmpeg(filePath)
|
2020-07-02 02:11:51 +02:00
|
|
|
.thumbnail({
|
|
|
|
timestamps: [0],
|
|
|
|
filename: '%b.png',
|
2020-07-02 02:42:20 +02:00
|
|
|
folder: ThumbUtil.thumbPath,
|
2020-07-08 01:32:12 +02:00
|
|
|
size: '150x?',
|
2020-07-02 02:11:51 +02:00
|
|
|
})
|
2020-07-08 01:32:12 +02:00
|
|
|
.on('error', (error) => log.error(error.message));
|
2020-07-02 02:42:20 +02:00
|
|
|
|
|
|
|
try {
|
2020-07-02 19:13:05 +02:00
|
|
|
await previewUtil({
|
2020-07-02 02:42:20 +02:00
|
|
|
input: filePath,
|
|
|
|
width: 150,
|
2020-07-02 19:13:05 +02:00
|
|
|
output: path.join(ThumbUtil.videoPreviewPath, output),
|
2020-07-08 01:32:12 +02:00
|
|
|
log: log.debug,
|
2020-07-02 02:42:20 +02:00
|
|
|
});
|
|
|
|
} catch (e) {
|
2020-07-08 01:32:12 +02:00
|
|
|
log.error(e);
|
2020-07-02 02:42:20 +02:00
|
|
|
}
|
2020-07-02 02:11:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static getFileThumbnail(filename) {
|
2020-07-04 22:18:51 +02:00
|
|
|
// TODO: refactor so we don't do the same compare multiple times (poor cpu cycles)
|
2020-07-02 02:11:51 +02:00
|
|
|
if (!filename) return null;
|
|
|
|
const ext = path.extname(filename).toLowerCase();
|
2020-07-02 02:42:20 +02:00
|
|
|
if (!ThumbUtil.imageExtensions.includes(ext) && !ThumbUtil.videoExtensions.includes(ext)) return null;
|
2020-07-04 22:18:51 +02:00
|
|
|
if (ThumbUtil.imageExtensions.includes(ext)) return { thumb: `${filename.slice(0, -ext.length)}.png` };
|
2020-07-08 01:32:12 +02:00
|
|
|
if (ThumbUtil.videoExtensions.includes(ext)) {
|
2020-07-04 22:18:51 +02:00
|
|
|
return {
|
|
|
|
thumb: `${filename.slice(0, -ext.length)}.png`,
|
2020-07-08 01:32:12 +02:00
|
|
|
preview: `${filename.slice(0, -ext.length)}.webm`,
|
2020-07-04 22:18:51 +02:00
|
|
|
};
|
2020-07-08 01:32:12 +02:00
|
|
|
}
|
2020-07-02 02:11:51 +02:00
|
|
|
}
|
2020-07-02 02:42:20 +02:00
|
|
|
|
2020-07-08 01:32:12 +02:00
|
|
|
static async removeThumbs({ thumb, preview }) {
|
|
|
|
if (thumb) {
|
|
|
|
await jetpack.removeAsync(path.join(ThumbUtil.thumbPath, thumb));
|
|
|
|
await jetpack.removeAsync(path.join(ThumbUtil.squareThumbPath, thumb));
|
|
|
|
}
|
|
|
|
if (preview) {
|
|
|
|
await jetpack.removeAsync(path.join(ThumbUtil.videoPreviewPath, preview));
|
|
|
|
}
|
2020-07-02 02:42:20 +02:00
|
|
|
}
|
2020-07-02 02:11:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = ThumbUtil;
|