Browse Source

fix resizeMode cover issue with on resolutions (do calculations in JS instead of ffmpeg)

new-features-2020
Mikael Finstad 6 years ago
parent
commit
f27d44168a
  1. 4
      examples/pip.json5
  2. 44
      sources/videoFrameSource.js

4
examples/pip.json5

@ -1,14 +1,14 @@
{
outPath: './pip.mp4',
width: 1280, height: 720, fps: 30,
enableFfmpegLog: true,
defaults: {
layer: { fontPath: './assets/Patua_One/PatuaOne-Regular.ttf' },
},
clips: [
{ duration: 4, layers: [
{ type: 'rainbow-colors' },
{ type: 'video', path: './assets/tungestolen.mp4', resizeMode: 'contain', width: 0.4, height: 0.4, top: 0.05, left: 0.95, originY: 'top', originX: 'right' },
{ type: 'video', path: './assets/tungestolen.mp4', resizeMode: 'cover', width: 0.3, height: 0.4, top: 0.05, left: 0.95, originY: 'top', originX: 'right' },
{ type: 'video', path: './assets/tungestolen.mp4', resizeMode: 'cover', width: 0.4, height: 0.2, top: 0.05, left: 0.05, originY: 'top', originX: 'left' },
{ type: 'title', position: 'bottom', text: 'Picture-in-Picture' }
] },
],

44
sources/videoFrameSource.js

@ -14,14 +14,15 @@ module.exports = async ({ width: canvasWidth, height: canvasHeight, channels, fr
const left = leftRel * canvasWidth;
const top = topRel * canvasHeight;
const ratioW = requestedWidth / inputWidth;
const ratioH = requestedHeight / inputHeight;
const inputAspectRatio = inputWidth / inputHeight;
let targetWidth = requestedWidth;
let targetHeight = requestedHeight;
let scaleFilter;
if (['contain', 'contain-blur'].includes(resizeMode)) {
const ratioW = requestedWidth / inputWidth;
const ratioH = requestedHeight / inputHeight;
const inputAspectRatio = inputWidth / inputHeight;
if (ratioW > ratioH) {
targetHeight = requestedHeight;
targetWidth = Math.round(requestedHeight * inputAspectRatio);
@ -29,15 +30,27 @@ module.exports = async ({ width: canvasWidth, height: canvasHeight, channels, fr
targetWidth = requestedWidth;
targetHeight = Math.round(requestedWidth / inputAspectRatio);
}
}
const frameByteSize = targetWidth * targetHeight * channels;
scaleFilter = `scale=${targetWidth}:${targetHeight}`;
} else if (resizeMode === 'cover') {
let scaledWidth;
let scaledHeight;
// TODO assert that we have read the correct amount of frames
if (ratioW > ratioH) {
scaledWidth = requestedWidth;
scaledHeight = Math.round(requestedWidth / inputAspectRatio);
} else {
scaledHeight = requestedHeight;
scaledWidth = Math.round(requestedHeight * inputAspectRatio);
}
const buf = Buffer.allocUnsafe(frameByteSize);
let length = 0;
// let inFrameCount = 0;
// TODO improve performance by crop first, then scale?
scaleFilter = `scale=${scaledWidth}:${scaledHeight},crop=${targetWidth}:${targetHeight}`;
} else { // 'stretch'
scaleFilter = `scale=${targetWidth}:${targetHeight}`;
}
if (verbose) console.log(scaleFilter);
let ptsFilter = '';
if (speedFactor !== 1) {
@ -45,10 +58,13 @@ module.exports = async ({ width: canvasWidth, height: canvasHeight, channels, fr
ptsFilter = `setpts=${speedFactor}*PTS,`;
}
let scaleFilter;
if (['stretch', 'contain', 'contain-blur'].includes(resizeMode)) scaleFilter = `scale=${targetWidth}:${targetHeight}`;
// Cover: https://unix.stackexchange.com/a/192123
else scaleFilter = `scale=(iw*sar)*max(${targetWidth}/(iw*sar)\\,${targetHeight}/ih):ih*max(${targetWidth}/(iw*sar)\\,${targetHeight}/ih),crop=${targetWidth}:${targetHeight}`;
const frameByteSize = targetWidth * targetHeight * channels;
// TODO assert that we have read the correct amount of frames
const buf = Buffer.allocUnsafe(frameByteSize);
let length = 0;
// let inFrameCount = 0;
// https://forum.unity.com/threads/settings-for-importing-a-video-with-an-alpha-channel.457657/
const streams = await readFileStreams(ffprobePath, path);

Loading…
Cancel
Save