74 lines
1.8 KiB
JavaScript
74 lines
1.8 KiB
JavaScript
/* eslint-disable no-bitwise */
|
|
const ffmpeg = require('fluent-ffmpeg');
|
|
const probe = require('ffmpeg-probe');
|
|
|
|
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])
|
|
.noAudio()
|
|
.outputFormat('webm')
|
|
.output(output)
|
|
.on('start', cmd => log && log({ cmd }))
|
|
.on('end', () => resolve())
|
|
.on('error', err => reject(err))
|
|
.run();
|
|
});
|
|
|
|
return result;
|
|
};
|