2

How can I pass a custom command to fluent-ffmpeg(https://www.npmjs.com/package/fluent-ffmpeg/v/1.7.0)? I just want to pass the command string. Something like

var command = FFmpeg("ffmpeg -i input.mp4 -i input.mp3 -c copy -map 0:v:0 -map 1:a:0 output.mp4")

I've seen the examples provided but seems that ffmpeg knowledge is required as to what is a filer, codec etc...

Lauren
  • 137
  • 2
  • 8
  • 1
    I have never used it, but it seems to me you need to send the FFmpeg constructor an object as shown on the npm page documentation, or set options with methods. The [github page](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg#readme) has more documentation. It is not exactly clear what your question is. – 2pha Jan 18 '20 at 23:45

4 Answers4

3

You just need to pass it into the outputOptions method.

const ffmpeg = require('fluent-ffmpeg');

ffmpeg()
  .input('input.mp4')
  .input('input.mp3')
  .outputOptions('-c copy -map 0:v:0 -map 1:a:0')
  .save('output.mp4');
wongz
  • 3,255
  • 2
  • 28
  • 55
1

Unfortunately at the time of writing this Fluent-ffmpeg still does not support custom complex FFMPEG attributes, so the only solutions are either forking it or resorting to ugly "hacks" that kind of defeat the primary purpose of this library (for most cases).

I'm using Fluent-ffmpeg with this "hack" only as a neat wrapper for handling multiple complex FFMPEG processes, with nice output/error/progress parsing.

const fluent = require('fluent-ffmpeg');

const executeFfmpeg = args => {
    let command = fluent().output(' '); // pass "Invalid output" validation
    command._outputs[0].isFile = false; // disable adding "-y" argument
    command._outputs[0].target = ""; // bypass "Unable to find a suitable output format for ' '"
    command._global.get = () => { // append custom arguments
        return typeof args === "string" ? args.split(' ') : args;
    };
    return command;
};

executeFfmpeg('-i input.mp4 -i input.mp3 -c copy -map 0:v:0 -map 1:a:0 output.mp4')
    .on('start', commandLine => console.log('start', commandLine))
    .on('codecData', codecData => console.log('codecData', codecData))
    .on('error', error => console.log('error', error))
    .on('stderr', stderr => console.log('stderr', stderr))
    .run();

NOTE: this solution does not support 'progress' event, but you can do it easily by parsing 'stderr' event with extractProgress method from fluent-ffmpeg/lib/options.js

Dušan Brejka
  • 802
  • 9
  • 18
1

The code below is what you need:

const ffmpeg = require('child_process').exec

ffmpeg("ffmpeg -i input.mp4 -i input.mp3 -c copy -map 0:v:0 -map 1:a:0 output.mp4")
0

Dušan Brejka's answer did the trick for me.

fluent-ffmeg handles progress with parseProgressLine at https://github.com/fluent-ffmpeg/node-fluent-ffmpeg/blob/12667091eeea09b0d6a55b87eb886aa131178608/lib/utils.js#L20

Here's my take on parsing progress. It also takes care of parsing numeric values.

    function handleProgress(progressLine: string): Record<string, string | number> {
      // Remove all spaces after = and trim.
      // each progress part is a key-value pai. ex: "frame=123", "time=01:23:45.67"
      const progressParts: string[] = progressLine
        .replace(/=\s+/g, "=")
        .trim()
        .split(" ");
    
      // build progress object
      const progress: Record<string, string | number> = {};
      for (const keyValuePair of progressParts) {
        const [key, value] = keyValuePair.split("=", 2);
        if (typeof value === "undefined") return null;
        const valueAsNumber = +value;
        progress[key] = !Number.isNaN(valueAsNumber) ? valueAsNumber : value;
      }
    
      // do something with progress object
      console.log(progress);
      return progress;
    }

Use with:

    executeFfmpeg(cmd)
      // attach handles
      .on("stderr", handleProgress)
      .run()
NoamR
  • 221
  • 1
  • 2
  • 10