Jul Pod
Jul Pod

Reputation: 396

ffmpeg - on end function probably not working correctly?

got this code to loop through some .mp4 files and create a screenshot of them:

files.forEach(file => {
    console.log(file);
    if(!fs.existsSync('img/' + file.replace('.mp4', '.png'))) {

        ffmpeg({ source: 'movies/' + file})
        .takeScreenshots({ timemarks: [ '50' ], size: '150x100' }, 'img/', function(err, filenames) {
        })
        .on('end', function() {      
          fs.rename('img/tn.png', 'img/' + file.replace('.mp4', '.png'), function(err) {if (err) console.log('Error: ' + err) }); 
          sleep(1000);  
      })   
      }    
});

Now i got the problem that it seems like that .on(end) is sometimes not working, Error: ENOENT: no such file or directory, rename

i think it´s because the process of saving the tn.png is slower than the renaming...

Upvotes: 0

Views: 1457

Answers (1)

Ashish Modi
Ashish Modi

Reputation: 7770

I wouldn't mix callback, sync, sleep and loop togather. You can use fs promise version to convert all your callback style to promise style. You could do sequentially or parallely.

Also, I would say convert the screenshot code to wrap in promise.

here is the code

const fs = require("fs").promises;

function takeScreenshot(file) {
  return new Promise((resolve, reject) => {
    ffmpeg({"source": `movies/${file}`})
      .takeScreenshots({"timemarks": ["50"], "size": "150x100"}, "img/", function (err, filenames) {
      })
      .on("end", function () {
        resolve();
      })
      .on("error", err => {
        reject(err);
      });
  });
}

// execute one by one
async function sequential(files) {
  for (const file of files) {
    const fileExists = await fs.stat(`img/${file.replace(".mp4", ".png")}`);
    if (fileExists) {
      await takeScreenshot(file);
      await fs.rename("img/tn.png", `img/${ file.replace(".mp4", ".png")}`);
    }
  }
}

// execute in parallel
async function parallel(files) {
  return Promise.all(files.map(async file => {
    const fileExists = await fs.stat(`img/${file.replace(".mp4", ".png")}`);
    if (fileExists) {
      await takeScreenshot(file);
      await fs.rename("img/tn.png", `img/${ file.replace(".mp4", ".png")}`);
    }
  }));
}

Hope this helps.

Upvotes: 1

Related Questions