Radespy
Radespy

Reputation: 456

Unable to serially execute ```execFile()``` with ```ffmpeg-static-electron``` binary Electron

I'm trying to split a number of .mp4 videos into .jpg images.

The set up is using electron-react-app. I have used a preload script to enable access to limited functions with the React components.

Problem: Unable to serially execute the call to execFile() on an array of video file names. The first video file is being successfully converted but can't get the remaining videos to convert despite using promises.

Function in pre-load script (accessed in React component):

const ffmpeg = require("ffmpeg-static-electron")
const { execFile } = require("child_process");
...
{split: (tempReviewFolderPath, filename) => {
    execFile(`${ffmpeg.path}`, [
      "-i",
      `${path.join(tempReviewFolderPath, filename)}`,
      "-vf",
      "fps=3",
      `${path.join(tempReviewFolderPath, "image-%d.jpg")}`,
    ]),
      (error, stdout, stderr) => {
        if (error) {
          console.log(error);
        } else {
          console.log(stdout, stderr);
        }
      };
  }
}

React component:

tempReviewFolderPath is the filepath to the folder contaning the videos.

filenamesArray is an array containing video filename strings.

"main_process:video_to_split" is the channel used in electron ipc which takes (channel, callback) as args.

useEffect(() => {
("main_process:video_to_split", 

 ({ tempReviewFolderPath, filenamesArray }) => {
        try {
          Promise.all(
            filenamesArray.map((filename) => {
              return new Promise((resolve) => {
                preLoad.split(tempReviewFolderPath, filename);
                resolve(filename);
              });
            })
          ).catch(console.error);
        } catch (error) {
          console.log(error);
        }
      })

}, []}

This only splits the first video.

I've also tried:-

pre-load script

const execFile = require("util").promisify(require("child_process").execFile);

{split: async (tempReviewFolderPath, filename) => {
    await execFile(`${ffmpeg.path}`, [
      "-i",
      `${path.join(tempReviewFolderPath, filename)}`,
      "-vf",
      "fps=3",
      `${path.join(tempReviewFolderPath, "image-%d.jpg")}`,
    ]),
      (error, stdout, stderr) => {
        if (error) {
          console.log(error);
        } else {
          console.log(stdout, stderr);
        }
      };
  }
}

React component:

useEffect(() => {
("main_process:video_to_split", 

 ( tempReviewFolderPath, filenamesArray }) => {
        try {
              preLoad.split(tempReviewFolderPath, filename);
             } catch (error) {
          console.log(error);
        }
      })

}, []}

Lastly (out of desperation) :

useEffect(() => {
  ("main_process:video_to_split", 

({ tempReviewFolderPath, filenamesArray }) => {
        let filename1 = filenamesArray[0];
        let filename2 = filenamesArray[1];

        try {
          preLoad.split(tempReviewFolderPath, filename1);
          preLoad.split(tempReviewFolderPath, filename2);
        } catch (error) {
          console.log(error);
        }
      }

)

Again, same problem - only the first video is split.

What am I doing wrong ?

Many thanks.

Upvotes: 0

Views: 225

Answers (1)

Radespy
Radespy

Reputation: 456

Found solution:

Problem related to "image-%d.jpg" which was simply being overwritten on each iteration by map.

Solution: just added index and changed function.

filenamesArray.map((filename, index) => {
          return new Promise((res, rej) => {
            api_link.split(tempReviewFolderPath, filename, index);
            res(filename);
          });
        });

Upvotes: 1

Related Questions