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

如何用fluent-ffmpeg处理Multer接收的视频Buffer并输出Buffer?

如何用fluent-ffmpeg接收Buffer并完成转码输出?

我需要实现的流程是:用Multer接收iPhone端Alamofire发送的MOV格式视频Buffer,将其作为fluent-ffmpeg的输入完成转码,转码后输出Buffer再上传至S3。目前已接近实现,但不确定fluent-ffmpeg是否支持直接传入Buffer。服务部署在Heroku上,使用最新版ffmpeg的buildpack。

现有代码

const multer = require('multer')
const upload = multer({ limits: { fieldSize: 100_000_000 } })
app.post('/create', upload.single('video'), async function (request, response, next) {
  let data = request.body
  console.log(data) // 打印 [Object: null prototype] { param1: '' }
  let bufferStream = new stream.PassThrough();
  console.log(request.file.buffer) // 打印 '<Buffer 00 00 00 14 66 74 79 70 71 74 20 20 00 00 00 00 71 74 20 20 00 00 00 08 77 69 64 65 01 0e 28 55 6d 64 61 74 21 20 03 40 68 1c 21 4e ff 3c 59 96 7c 82 ... 17718642 more bytes>'

  new ffmpeg({
    source: stream.Readable.from(request.file.buffer, { objectMode: false })
  })
  // .format('mp4')
  .on('error', function (err) {
    console.log(`Error: ${err}`)
  })
  .on('progress', function (progress) {
    console.log("progress")
  })
  .on('end', function () {
    console.log('Formatting finished!');
    console.log("after");
  })
  .writeToStream(bufferStream);

  // 读取直通流
  const buffers = [];
  bufferStream.on('data', function (buf) {
    buffers.push(buf);
  });
  bufferStream.on('end', function () {
    const outputBuffer = Buffer.concat(buffers);
  // 使用outputBuffer
  });
  console.log("Added.")
  response.send("Success")
});

未添加.format('mp4')时的报错输出

2022-09-03T13:12:24.194384+00:00 heroku[router]: at=info method=POST path="/createBusiness" host=sparrow-testing.herokuapp.com request_id=2774a4ec-e21e-4c2f-8086-460a4cba7d1d fwd="74.71.236.5" dyno=web.1 connect=0ms service=13157ms status=200 bytes=762 protocol=https
2022-09-03T13:12:24.186257+00:00 app[web.1]: [Object: null prototype] { title: '' }
2022-09-03T13:12:24.187296+00:00 app[web.1]: <Buffer 00 00 00 14 66 74 79 70 71 74 20 20 00 00 00 00 71 74 20 20 00 00 00 08 77 69 64 65 01 0e 28 55 6d 64 61 74 21 20 03 40 68 1c 21 4e ff 3c 59 96 7c 82 ... 17718642 more bytes>
2022-09-03T13:12:24.189891+00:00 app[web.1]: Added.
2022-09-03T13:12:24.891564+00:00 app[web.1]: Error: Error: ffmpeg exited with code 1: pipe:1: Invalid argument

添加.format('mp4')时的报错输出

2022-09-03T13:17:07.380415+00:00 app[web.1]: [Object: null prototype] { title: '' }
2022-09-03T13:17:07.381335+00:00 app[web.1]: <Buffer 00 00 00 14 66 74 79 70 71 74 20 20 00 00 00 00 71 74 20 20 00 00 00 08 77 69 64 65 01 0e 28 55 6d 64 61 74 21 20 03 40 68 1c 21 4e ff 3c 59 96 7c 82 ... 17718642 more bytes>
2022-09-03T13:17:07.384047+00:00 app[web.1]: Added.
2022-09-03T13:17:07.388457+00:00 heroku[router]: at=info method=POST path="/createBusiness" host=sparrow-testing.herokuapp.com request_id=84e69ead-09b1-4668-8fc8-b9fc9d5f229d fwd="74.71.236.5" dyno=web.1 connect=0ms service=13079ms status=200 bytes=762 protocol=https
2022-09-03T13:17:08.339746+00:00 app[web.1]: Error: Error: ffmpeg exited with code 1: Conversion failed!

注:我的uploadFile函数工作正常,其他场景直接传入request.file.buffer即可,但此处需要转码后的Buffer


已尝试的修改

按照建议修改了Multer配置,将文件保存到本地目录,再用文件路径作为ffmpeg输入:

修改后的Multer初始化代码

multer({ limits: { fieldSize: 100_000_000 }, dest: "uploads/" })

修改后的ffmpeg代码

new ffmpeg({
  source: request.file.path // request.file.path为Multer生成的本地文件路径
})
.format('mp4')

此时的request.file信息

{
  fieldname: 'video',
  originalname: 'video',
  encoding: '7bit',
  mimetype: 'clientMime',
  destination: 'uploads/',
  filename: '08d5d3bbdcf1ac29fb97800136a306e9',
  path: 'uploads/08d5d3bbdcf1ac29fb97800136a306e9',
  size: 1567480
}

仍然报错

Error: ffmpeg exited with code 1: Conversion failed!

解决方案

  1. 明确指定输入格式
    从request.file的mimetype为clientMime可以看出,请求没有正确传递视频的MIME类型,导致ffmpeg无法识别输入格式。需要手动指定输入为MOV格式:

    // 本地文件方式
    new ffmpeg({ source: request.file.path })
      .inputFormat('mov')
      .format('mp4')
      .on('error', err => console.error('转码错误:', err))
      .on('end', () => console.log('转码完成'))
      .writeToStream(bufferStream);
    
    // 直接用Buffer转流的方式
    const inputStream = stream.Readable.from(request.file.buffer);
    ffmpeg(inputStream)
      .inputFormat('mov')
      .format('mp4')
      .on('error', err => console.error('转码错误:', err))
      .pipe(bufferStream); // 用pipe替代writeToStream,更稳定
    
  2. 确保本地存储目录存在
    如果用本地文件方式,Heroku的临时目录不会自动创建uploads/,需要启动时手动创建:

    const fs = require('fs');
    const path = require('path');
    const uploadDir = path.join(__dirname, 'uploads');
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }
    
  3. 开启ffmpeg调试日志排查问题
    添加调试参数查看具体错误原因:

    new ffmpeg({ source: request.file.path })
      .addOption('-v', 'debug')
      .inputFormat('mov')
      .format('mp4')
      // ...其他配置
    
  4. 验证ffmpeg编码支持
    确保Heroku上的ffmpeg支持H.264编码(MP4常用编码),可以通过执行ffmpeg -codecs查看支持的编码列表,确认h264在其中。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 18:54:26