0

Goal

I have a video and an image (a template for the video) that I'm trying to combine into one output video (1080w x 1920h - 9:16 aspect ratio).

  • Input video - 1920x1080
  • Input image - 1080x1920
  • Output video - 1080x1920

This image shows what I'm trying to accomplish. The two orange sections are the input image - it's a single .png with a transparent section in the middle for the video.

As mentioned in the title, I'm trying to accomplish this using FFMPEG. More specifically, I'm using the fluent-ffmpeg npm package.

Current Status

I can read in both inputs just fine but I have issues getting the two to play nicely with one another.

If I get the overlay working then my output video is 1920x1080 instead of 1080x1920.

If I get the output video dimensions right, then the video is either stretched or I get errors adding my overlay.

Code

Here's what I have at the moment. I'm happy to answer any questions. Thank you in advance for taking a look :)

var ffmpeg = require('fluent-ffmpeg');
var command = ffmpeg();
var timemark = null;

command
  .on('end', onEnd )
  .on('progress', onProgress)
  .on('error', onError)
  .input('./input-video.mp4')
  .input('./template.png')
  .complexFilter([
    {
      filter: 'scale',
      options: { width: 1080, height: 1920 }
    },
    // {
    //   filter: 'overlay',
    //   options: { x: 100, y: 100 }
    // },
  ])
  .outputFps(30)
  .output('./output-video.mp4')
  .run();

/* Misc */

function onProgress(progress){
  if (progress.timemark != timemark) {
    timemark = progress.timemark;
    console.log('Time mark: ' + timemark + "...");
  }
}

function onError(err, stdout, stderr) {
  console.log('Cannot process video: ' + err.message);
}

function onEnd() {
  console.log('Finished processing');
}
clo5ure
  • 90
  • 14
  • Sounds like you need to scale the input video first to width of 1080 before adding the image as second input. Normally the command is: `ffmpeg -i input-video.mp4 -vf scale=1080:-1 -i template.png -filter_complex "overlay=100:100" output-video.mp4` so you will have to find a way to set **video filter** on 1st input before doing **complex filter** when using Fluent-FFmpeg. – VC.One Jun 26 '21 at 13:52

1 Answers1

0

Thanks to user Voldrix_Suroku on Reddit I was able to figure this out.

To avoid being a DenverCoder9 the CLI command to get this to work is:

ffmpeg -i input-video.mp4 -i template.png -filter_complex "[0:V]scale=1080:-1,pad=0:1920:0:(oh-ih)/2[vid];[vid][1:v]overlay" output-video.mp4

And if you're using fluent-ffmpeg like I am, the full code is below:

var ffmpeg = require('fluent-ffmpeg');
var command = ffmpeg();
var timemark = null;

command
  .on('end', onEnd )
  .on('progress', onProgress)
  .on('error', onError)
  .input('./input-video.mp4')
  .input('./template.png')
  .complexFilter([
    "[0:V]scale=1080:-1,pad=0:1920:0:(oh-ih)/2[vid];[vid][1:v]overlay"
  ])
  .outputFps(30)
  .output('./output-video.mp4')
  .run();

/* Misc */

function onProgress(progress){
  if (progress.timemark != timemark) {
    timemark = progress.timemark;
    console.log('Time mark: ' + timemark + "...");
  }
}

function onError(err, stdout, stderr) {
  console.log('Cannot process video: ' + err.message);
}

function onEnd() {
  console.log('Finished processing');
}
clo5ure
  • 90
  • 14