首页 > 解决方案 > ffmpeg - 结束功能可能无法正常工作?

问题描述

让这段代码遍历一些 .mp4 文件并创建它们的屏幕截图:

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);  
      })   
      }    
});

现在我遇到了一个问题,似乎 .on(end) 有时不起作用,错误: ENOENT:没有这样的文件或目录,重命名

我认为这是因为保存 tn.png 的过程比重命名要慢...

标签: javascriptnode.jsffmpeg

解决方案


我不会将回调、同步、睡眠和循环混合在一起。您可以使用fsPromise 版本将所有回调样式转换为 Promise 样式。您可以按顺序或并行进行。

另外,我会说将屏幕截图代码转换为承诺。

这是代码

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")}`);
    }
  }));
}

希望这可以帮助。


推荐阅读