feat: experimental video preview generator in webm form
This commit is contained in:
parent
a790d7749e
commit
24157dd1b9
|
@ -0,0 +1,74 @@
|
|||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const probe = require('ffmpeg-probe');
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
module.exports = async opts => {
|
||||
const {
|
||||
log = noop,
|
||||
|
||||
// general output options
|
||||
quality = 2,
|
||||
width,
|
||||
height,
|
||||
input,
|
||||
output,
|
||||
|
||||
numFrames,
|
||||
numFramesPercent = 0.05
|
||||
} = opts;
|
||||
|
||||
const info = await probe(input);
|
||||
// const numFramesTotal = parseInt(info.streams[0].nb_frames, 10);
|
||||
const { avg_frame_rate: avgFrameRate, duration } = info.streams[0];
|
||||
const [frames, time] = avgFrameRate.split('/').map(e => parseInt(e, 10));
|
||||
|
||||
const numFramesTotal = (frames / time) * duration;
|
||||
|
||||
let numFramesToCapture = numFrames || numFramesPercent * numFramesTotal;
|
||||
numFramesToCapture = Math.max(1, Math.min(numFramesTotal, numFramesToCapture)) | 0;
|
||||
const nthFrame = (numFramesTotal / numFramesToCapture) | 0;
|
||||
|
||||
const result = {
|
||||
output,
|
||||
numFrames: numFramesToCapture
|
||||
};
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
let scale = null;
|
||||
|
||||
if (width && height) {
|
||||
result.width = width | 0;
|
||||
result.height = height | 0;
|
||||
scale = `scale=${width}:${height}`;
|
||||
} else if (width) {
|
||||
result.width = width | 0;
|
||||
result.height = ((info.height * width) / info.width) | 0;
|
||||
scale = `scale=${width}:-1`;
|
||||
} else if (height) {
|
||||
result.height = height | 0;
|
||||
result.width = ((info.width * height) / info.height) | 0;
|
||||
scale = `scale=-1:${height}`;
|
||||
} else {
|
||||
result.width = info.width;
|
||||
result.height = info.height;
|
||||
}
|
||||
|
||||
const filter = [`select=not(mod(n\\,${nthFrame}))`, scale].filter(Boolean).join(',');
|
||||
|
||||
ffmpeg(input)
|
||||
.outputOptions(['-vsync', 'vfr'])
|
||||
.outputOptions(['-q:v', quality, '-vf', filter])
|
||||
.outputOption('-an')
|
||||
.outputFormat('webm')
|
||||
.output(output)
|
||||
.on('start', cmd => log && log({ cmd }))
|
||||
.on('end', () => resolve())
|
||||
.on('error', err => reject(err))
|
||||
.run();
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
|
@ -2,7 +2,7 @@ const jetpack = require('fs-jetpack');
|
|||
const path = require('path');
|
||||
const sharp = require('sharp');
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const generatePreview = require('ffmpeg-generate-video-preview');
|
||||
const previewUtil = require('./PreviewUtil');
|
||||
|
||||
const log = require('./Log');
|
||||
|
||||
|
@ -17,7 +17,7 @@ class ThumbUtil {
|
|||
static generateThumbnails(filename) {
|
||||
const ext = path.extname(filename).toLowerCase();
|
||||
const output = `${filename.slice(0, -ext.length)}.png`;
|
||||
const previewOutput = `${filename.slice(0, -ext.length)}.gif`;
|
||||
const previewOutput = `${filename.slice(0, -ext.length)}.webm`;
|
||||
|
||||
if (ThumbUtil.imageExtensions.includes(ext)) return this.generateThumbnailForImage(filename, output);
|
||||
if (ThumbUtil.videoExtensions.includes(ext)) return this.generateThumbnailForVideo(filename, previewOutput);
|
||||
|
@ -38,7 +38,7 @@ class ThumbUtil {
|
|||
.toFile(path.join(ThumbUtil.thumbPath, output));
|
||||
}
|
||||
|
||||
static generateThumbnailForVideo(filename, output) {
|
||||
static async generateThumbnailForVideo(filename, output) {
|
||||
const filePath = path.join(__dirname, '..', '..', '..', process.env.UPLOAD_FOLDER, filename);
|
||||
|
||||
ffmpeg(filePath)
|
||||
|
@ -60,10 +60,11 @@ class ThumbUtil {
|
|||
.on('error', error => log.error(error.message));
|
||||
|
||||
try {
|
||||
generatePreview({
|
||||
await previewUtil({
|
||||
input: filePath,
|
||||
width: 150,
|
||||
output: path.join(ThumbUtil.videoPreviewPath, output)
|
||||
output: path.join(ThumbUtil.videoPreviewPath, output),
|
||||
log: console.log
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
|
Loading…
Reference in New Issue