Merge Multiple Videos using node fluent ffmpeg
Asked Answered
M

5

10

requirement is to read all the files in the directory and merge them. I am using node fluent-ffmpeg to achieve this. First of all reading all the files in the directory appending concatenating the string by adding .input.

var finalresult="E:/ETV/videos/finalresult.mp4"
outputresult : It consists of all the files read in the directory.

/*Javascript*/
MergeVideo(outputresult);
function MergeVideo(outputresult){
console.log("in merge video");
var videostring = "";

for(i=1;i<5;i++)
    {
videostring = videostring+".input("+"'"+outputresult[i]+"'"+")";
}
console.log("Video String"+videostring);
    var proc = ffmpeg()+videostring
    .on('end', function() {
      console.log('files have  succesfully Merged');
        })
    .on('error', function(err) {
      console.log('an error happened: ' + err.message);
    })
    .mergeToFile(finalresult);
}

It gives the following error:

TypeError: Object .input('ETV 22-02-2015 1-02-25 AM.mp4').input('ETV 22-02-2015
9-33-15 PM.mp4').input('ETV 22-02-2015 9-32-46 AM.mp4').input('ETV 22-02-2015 8-
32-44 AM.mp4') has no method 'on'
    at MergeVideo (D:\Development\Node\node-fluent-ffmpeg-master\node-fluent-ffm
peg-master\examples\demo.js:140:6)
    at Object.<anonymous> (D:\Development\Node\node-fluent-ffmpeg-master\node-fl
uent-ffmpeg-master\examples\demo.js:129:1)
    at Module._compile (module.js:456:26)

Any help is appreciated.

Mimamsa answered 5/3, 2015 at 12:25 Comment(0)
M
21

Try this

var fluent_ffmpeg = require("fluent-ffmpeg");

var mergedVideo = fluent_ffmpeg();
var videoNames = ['./video1.mp4', './video2.mp4'];

videoNames.forEach(function(videoName){
    mergedVideo = mergedVideo.addInput(videoName);
});

mergedVideo.mergeToFile('./mergedVideo.mp4', './tmp/')
.on('error', function(err) {
    console.log('Error ' + err.message);
})
.on('end', function() {
    console.log('Finished!');
});
Mild answered 8/7, 2015 at 8:17 Comment(4)
I am getting invalid input index error when invoking mergeToFile method. can you let me know any aspect to be verified?Kapor
getting Cannot find a matching stream for unlabeled input pad 3 on filter Parsed_concat_0Leonleona
@Mild please help meLeonleona
Does it work in 2022? I've only changed var fluent_ffmepg to import and function(~) to arrow function. but It doesn't work for meAffer
A
3
var fluent_ffmpeg = require("fluent-ffmpeg");

var mergedVideo = fluent_ffmpeg();
var videoNames = ['./video1.mp4', './video2.mp4'];

videoNames.forEach(function(videoName){
    mergedVideo = mergedVideo.addInput(videoName);
});

mergedVideo.mergeToFile('./mergedVideo.mp4', './tmp/')
.on('error', function(err) {
    console.log('Error ' + err.message);
})
.on('end', function() {
    console.log('Finished!');
});

This issue happening getting Cannot find a matching stream for unlabeled input pad 3 on filter Parsed_concat_0

Because one of the file doesn't have audio in it.

Antibaryon answered 10/3, 2022 at 12:53 Comment(0)
S
1

answered here: adding silent audio in ffmpeg

i tried to use fluent-ffmpeg but couldn't make it :/ After hours of debugging I switched to the native solution.

Select answered 18/4, 2022 at 13:47 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewEcclesia
L
0

Well, this library is bugged and nobody should use it.

Here's an example code you can use. It's very simple. It doesn't work.

ffmpeg(firstFile).input(secondFile).save(outPath)

Both files are in mp4 format. It's wicked. Don't use it.

Another problem I had was instantiating class of that library. Apparently the creator didn't know how to use export properly.

Lepanto answered 12/6, 2024 at 23:23 Comment(0)
W
0

this code puts everything in 1 format and glues it together. Receives an array of file paths and unsupported permissions as input

const fs = require("fs");
const path = require("path");
const ffmpeg = require("fluent-ffmpeg");
const { execSync } = require("child_process");

const unsupportedFilesExtname = [".avi", ".mov"];
const mockData = ["./3.mov", "./1.mp4", "./2.avi"];

async function checkNeedConvert(arrayFiles) {
  const unsupportedFiles = arrayFiles
    .map((el) => {
      if (unsupportedFilesExtname.includes(path.extname(el))) {
        return el;
      } else {
        return null;
      }
    })
    .filter(Boolean);

  await convertUnsupported(unsupportedFiles);
  await mergeAllVideos(arrayFiles);
}

function mergeAllVideos(arrayFiles) {
  const pathToTextFile = "./dataForMerge.txt";
  arrayFiles.forEach((element) => {
    const filePathWithChangeFormat = element.replace(
      path.extname(element),
      ".mp4"
    );
    fs.appendFileSync(
      pathToTextFile,
      `file ${path.resolve(filePathWithChangeFormat)}\n`
    );
  });
  execSync(
    `ffmpeg -f concat -safe 0 -i ./dataForMerge.txt -c copy output_demuxer.mp4`
  );
}

function convertUnsupported(unsupportedFiles) {
  return new Promise((resolve) => {
    unsupportedFiles
      .reduce(async (prevPromise, currentPath) => {
        await prevPromise;

        const filePathMp4 = currentPath.replace(
          path.extname(currentPath),
          ".mp4"
        );

        const process = new ffmpeg();

        return await new Promise((res, rej) => {
          process
            .input(currentPath)
            .addOutputOptions(
              "-movflags +frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov"
            )
            .format("mp4")
            .output(filePathMp4)
            .on("end", () => {
              res();
            })
            .on("error", (err) => {
              rej();
            })
            .run();
        });
      }, Promise.resolve())
      .then(() => {
        resolve();
      });
  });
}

(async () => {
 await checkNeedConvert(mockData);
})();
Willin answered 5/8, 2024 at 11:26 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.