Buffer 作为 Fluent-ffmpeg 的输入和输出

nic*_*ng2 5 javascript mp4 video-streaming node.js fluent-ffmpeg

下面看起来很多,但主要只是输出。

我正在尝试使用 multer (通过 iPhone 上的 Alamofire 发送包含视频(.mov 格式)的请求)作为输入的缓冲区,然后我希望它作为缓冲区输出,然后将结果发送到S3。我想我已经很接近了,但我不认为 Fluent-ffmpeg 可以传入缓冲区。这是使用此构建包部署在 Heroku 上的: https: //github.com/jonathanong/heroku-buildpack-ffmpeg-latest。 ……​ 我如何正确地传递它?

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) // prints [Object: null prototype] { param1: '' }
  let bufferStream = new stream.PassThrough();
  console.log(request.file.buffer) // prints '<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);

  // Read the passthrough stream
  const buffers = [];
  bufferStream.on('data', function (buf) {
    buffers.push(buf);
  });
  bufferStream.on('end', function () {
    const outputBuffer = Buffer.concat(buffers);
  // use outputBuffer
  });
  console.log("Added.")
  response.send("Success")
});
Run Code Online (Sandbox Code Playgroud)

输出如下所示(不带 .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
2022-09-03T13:12:24.891570+00:00 app[web.1]: 
Run Code Online (Sandbox Code Playgroud)

此输出是您使用 .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!
2022-09-03T13:17:08.339783+00:00 app[web.1]: 
Run Code Online (Sandbox Code Playgroud)

我的 uploadFile 函数工作正常,因为我在其他地方使用它 - 通常,我只是传入 request.file.buffer,但这里它需要是 ffmpeg 转换后的缓冲区

编辑:

根据 Heiko 的建议,我尝试将 multer 初始化更改为

multer({ limits: { fieldSize: 100_000_000 }, dest: "uploads/" })
Run Code Online (Sandbox Code Playgroud)

以及我传递给 ffmpeg 的源

new ffmpeg({
  source: request.file.path // request.file.path seems to be a path of a Multer-generated file, I'd assume the one I'm sending to the server
})
.format('mp4')
Run Code Online (Sandbox Code Playgroud)

但它仍然出错

Error: ffmpeg exited with code 1: Conversion failed!
Run Code Online (Sandbox Code Playgroud)

当 request.file 是:

{
  fieldname: 'video',
  originalname: 'video',
  encoding: '7bit',
  mimetype: 'clientMime',
  destination: 'uploads/',
  filename: '08d5d3bbdcf1ac29fb97800136a306e9',
  path: 'uploads/08d5d3bbdcf1ac29fb97800136a306e9',
  size: 1567480
}
Run Code Online (Sandbox Code Playgroud)

Ala*_*ine 0

我尝试使用你的代码,得到相同的结果。搜索了一段时间后,我找到了解释。

嗯,问题出在 MP4 和流媒体上。

我不是视频专家,但似乎在操作 MP4 文件时,ffmpeg 需要查找文件,而查找本质上与流不兼容。

因此,您需要从 ffmpeg 输出一个文件系统文件(使用后删除该文件使其成为临时文件),然后根据您的需要使用该文件。

为了获得有关 ffmpeg 错误的更多调试信息,您需要修改错误事件侦听器代码,如下所示:

// .format('mp4')
  .on('error', function (err, stdout, stderr) {
    console.log(Error: ${err})
    console.log('Stdout: %o', stdout);
    console.log('Stderr: %o', stderr);
  })
  .on('progress', function (progress) {
Run Code Online (Sandbox Code Playgroud)

您将在执行 ffmpeg 进程的 stderr 日志时看到。

您可以在这里确认这一点:

/sf/answers/2777598281/

https://superuser.com/a/760287