使用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
相关产品推荐
相关产品推荐

