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

使用fluent-ffmpeg在AWS Lambda中处理视频并上传S3遇报错求助

解决 Error: Stream yields empty buffer 问题

我一眼就看出问题所在了——你直接把 command.pipe() 返回的流传给了回调,但 fluent-ffmpeg 的视频处理是异步流式操作,这时候流还没生成任何有效数据,上传到 S3 自然就会得到空缓冲区错误。ImageMagick 处理图片时同步性更强,所以没暴露这个问题,但视频处理逻辑得适配异步流的特性。

下面给你调整后的代码,我会标注关键改动点:

方案一:内存收集完整Buffer(适合中小视频)

先修改 resizeVideo 函数,我们需要监听 FFmpeg 的流事件,收集所有处理后的视频数据,等全部处理完成后再回调:

function resizeVideo(response, callback) {
  try {
    let command = ffmpeg(response.Body);
    let chunks = [];

    command.size('50%')
      .on('data', (chunk) => {
        // 逐段收集处理后的视频数据
        chunks.push(chunk);
      })
      .on('end', () => {
        // 所有数据收集完成后,合并成完整Buffer
        const buffer = Buffer.concat(chunks);
        callback(null, response, buffer);
      })
      .on('error', (err) => {
        console.log('video resize error-------------------------');
        console.log(err);
        callback(err);
      });
  } catch (e) {
    console.log('video resize error-------------------------');
    console.log(e);
    callback('Video resize error');
  }
}

然后修正 uploadBuffer 里的变量错误(原来的imageName未定义,应该用srcKey),同时确保错误能正确传递给异步流程:

function uploadBuffer(response, buffer, next) {
  // Upload to s3
  let resizedVideoName = "resized/" + srcKey; // 替换未定义的imageName
  s3.putObject({
    Bucket: srcBucket,
    Key: resizedVideoName,
    Body: buffer,
    ContentType: response.ContentType
  }, function(err, data) {
    if (err) {
      console.log(err, err.stack);
      return next(err); // 出错时必须把err传给next,否则异步流程会误判为成功
    } else {
      console.log('video resized-----------------------');
      next(null, response, buffer);
    }
  });
}

方案二:流式上传(适合大视频,避免内存溢出)

如果你的场景里有超大视频,用内存Buffer合并会有内存压力,建议直接把FFmpeg的输出流传给S3,全程流式处理:

function resizeVideo(response, callback) {
  try {
    let command = ffmpeg(response.Body);
    // 直接返回FFmpeg处理后的流
    const processedStream = command.size('50%').pipe();
    callback(null, response, processedStream);
  } catch (e) {
    console.log('video resize error-------------------------');
    console.log(e);
    callback('Video resize error');
  }
}

// 对应修改上传函数,直接传流作为Body
function uploadBuffer(response, stream, next) {
  let resizedVideoName = "resized/" + srcKey;
  s3.putObject({
    Bucket: srcBucket,
    Key: resizedVideoName,
    Body: stream, // 直接使用处理后的流
    ContentType: response.ContentType
  }, function(err, data) {
    if (err) {
      console.log(err, err.stack);
      return next(err);
    } else {
      console.log('video resized-----------------------');
      next(null);
    }
  });
}

核心逻辑说明

FFmpeg处理视频是异步的流式过程,不能像处理图片那样同步获取结果。必须通过监听流的data/end事件收集数据,或者直接传递流给S3完成流式上传,这样才能保证拿到完整的处理后视频数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:07:49