You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Node.js中为FFmpeg实现视频编码队列?

解决方案:实现FFmpeg转码任务的串行执行

你的问题核心在于forEach是同步遍历逻辑,会一次性触发所有异步转码任务,导致FFmpeg同时占用过多系统资源引发报错。要实现任务串行执行(一个完成后再启动下一个),可以通过「将回调风格的转码函数改为Promise风格」,配合async/await和for...of循环来实现。

步骤1:将covertVideo改为Promise风格

把原来的回调写法替换为Promise,这样可以用await等待转码完成:

const Ffmpeg = require("fluent-ffmpeg");

function covertVideo(filename) {
  return new Promise((resolve, reject) => {
    const ffmpeg = new Ffmpeg(filename);
    ffmpeg.setFfmpegPath(pathToFfmpeg)
      .addOptions("-threads 1")
      .fps(23)
      .complexFilter([
        "scale=w='if(gt(a,0.75),240,trunc(320*a/2)*2)':h='if(lt(a,0.75),320,trunc(240/a/2)*2)',pad=w=240:h=320:x='if(gt(a,0.75),0,(240-iw)/2)':y='if(lt(a,0.75),0,(320-ih)/2)':color=black[scaled]"
      ])
      .on('error', function(err) {
        console.log(`转码出错:${filename} - ${err.message}`);
        reject(false);
      })
      .on('end', function() {
        console.log(`转码完成:${filename}`);
        resolve(true);
      })
      .save(`./tmp/${filename}`);
  });
}

步骤2:用async/await + for...of实现串行遍历

替换原来的forEach,用for...of循环逐个处理视频,确保上一个转码完成后再启动下一个:

async function processVideos(videos) {
  for (const video of videos) {
    // 注意:根据你的videos数组结构取文件名,比如video是字符串则直接用,是对象则取video.filename
    const filename = video;
    try {
      const result = await covertVideo(filename);
      // 这里添加转码完成后的逻辑,比如记录结果、更新状态等
      if (result) {
        console.log(`处理成功:${filename}`);
      }
    } catch (err) {
      console.log(`处理失败:${filename}`);
    }
  }
}

// 启动批量处理
processVideos(videos);

补充:可选的并发控制

如果不想完全串行,而是想同时处理N个任务(比如2个),可以用分批处理的方式:

async function processVideosInBatches(videos, batchSize = 2) {
  for (let i = 0; i < videos.length; i += batchSize) {
    const batch = videos.slice(i, i + batchSize);
    await Promise.all(
      batch.map(video => covertVideo(video))
    );
    console.log(`完成一批转码,共${batch.length}个文件`);
  }
}

// 启动分批处理
processVideosInBatches(videos, 2);

关键说明

  • forEach不支持异步等待:它会同步遍历数组,立即执行所有回调,完全不管里面的异步操作何时完成,因此会一次性启动所有FFmpeg进程,导致资源耗尽。
  • Promise + async/await:通过Promise包装异步转码操作,用await强制等待当前任务完成后再执行下一个,从根源上避免了并发过载问题。

内容的提问来源于stack exchange,提问作者Hall45

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 07:18:12