UNPKG

ffcreatorlite

Version:

FFCreatorLite is a lightweight and flexible short video production library

115 lines (100 loc) 3.08 kB
'use strict'; /** * toZoomFilter - Convert to zoom filter function * * ####Note: * Fix ffmpeg zoompan jiggle bug. * https://superuser.com/questions/1112617/ffmpeg-smooth-zoompan-with-no-jiggle/1112680#1112680 * * * @function */ const forEach = require('lodash/forEach'); const Ease = require('../math/ease'); const Utils = require('../utils/utils'); const AniFilter = require('./anifilter'); const FilterUtil = require('../utils/filter'); const toZoomFilter = conf => { let { from = 1, to, showType, time, delay, add, ing = false, size, pad, ease = 'linear' } = conf; let zoom, elsestr, filter; let maxScale = 1; let x = 'iw/2-(iw/zoom/2)'; let y = 'ih/2-(ih/zoom/2)'; // reset from to value if (from < 1 && pad) { to = (1 / from) * to; from = 1; } const fps = conf.rootConf.getVal('fps'); const frames = fps * time; const delayFrames = fps * delay; // (max>=x>=min) const coodi = `between(on,${delayFrames - 1},${delayFrames + frames})`; // Is it continuous animation or single easing animation if (ing) { if (!to) to = from + add * frames; zoom = `${from}+${add}*(on-${delayFrames})`; } else { zoom = Ease.getVal(ease, from, to - from, frames, delayFrames).replace(/t/gi, 'on'); } //- elsestr = `if(lte(on,_delay_),${to},_else_)`; let z = `if(${coodi}\,${zoom}\,_else_${to}_else_)`; z = Utils.replacePlusMinus(z); //- maxScale = Math.max(from, to); const padFilter = FilterUtil.createPadFilter(maxScale); const scaleFilter = FilterUtil.createScaleFilter(4000); const zoomFilter = FilterUtil.createZoomFilter({ x, y, z, s: size, fps, d: frames }); filter = pad ? `${padFilter},${scaleFilter},${zoomFilter}` : `${scaleFilter},${zoomFilter}`; return new AniFilter({ filter, showType, name: 'zoompan', type: 'string', data: { time, delay: delayFrames, elsestr, z }, }); }; /** * create new zoompan filter * if(a<t<b, T1, if(t<c, C1, if(c<t<d, T2, C2))) * @private */ const mergeIntoNewZoompanFilter = tfilters => { const elseReg = /\_else\_/gi; const delayReg = /\_delay\_/gi; const elseNelse = /\_else\_[0-9a-z]*\_else\_/gi; let zoom = ''; let elsez; // if(lte(t,_delay_),${to.x},_else_) forEach(tfilters, (aniFilter, index) => { const data = aniFilter.data; const delay = data.delay; const z = data.z; const filter = aniFilter.filter; if (index > 0) { elsez = elsez.replace(delayReg, delay).replace(elseReg, z); zoom = zoom.replace(elseNelse, elsez); } else { zoom = String(filter); elsez = data.elsestr; } }); zoom = zoom.replace(elseReg, ''); return new AniFilter({ filter: zoom, name: 'zoompan', type: 'string', }); }; /** * Replace placeholder characters in the filter field * @private */ const replaceZoomFilter = aniFilter => { const elseReg = /\_else\_/gi; let filter = aniFilter.filter; filter = String(filter).replace(elseReg, ''); aniFilter.filter = filter; }; module.exports = { toZoomFilter, mergeIntoNewZoompanFilter, replaceZoomFilter };