Nodejs: generating thumbnail image from video buffer (not file path)
Asked Answered
D

1

1

I have a Node API that accepts video files uploaded via client-side FormData. The result is a req.file object:

{
  fieldname: 'media',
  originalname: 'IMG_6288.MOV',
  encoding: '7bit',
  mimetype: 'video/quicktime',
  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 ed db 13 6d 64 61 74 21 20 03 40 68 1c 21 4e e6 ff f9 80 e7 ff ... 32390609 more bytes>,
  size: 32390659
}

I am trying to create a thumbnail image from a given frame in the video file. However, almost everything I find on thumbnail generation (i.e. ffmpeg) requires a path in order to process the video, which is not provided.

Is there a way to create a thumbnail image without the file path? Perhaps from the provided buffer, either directly or by converting it into a stream first?

TIA for your help

Derk answered 3/11, 2021 at 14:6 Comment(3)
You can pipe/write that file/data to stdin on the ffmpeg process. With this you dont have to write the file the filesystem. All "in-memory".Ozzie
@Ozzie could you provide an example? Pretty new to video processing/ffmpegDerk
sorry for the long wait. I have posted a posssible solution.Ozzie
O
4

I got it workin with the following code. This is not perfect and throws sometimes a EPIPE error, because ffmpeg close stdin to fast, but its working & a solid base for your use case:

const { exec } = require("child_process");
const fs = require("fs");

// this (data) is your input file, that you pipe into ffmepg
const data = fs.readFileSync("./input.avi");
console.log("input data read, size:", data.length);



const ffmpeg = exec(`ffmpeg -ss 00:10:00 -y -f avi -i pipe: -vframes 1 output.jpg`);

ffmpeg.on("error", (err) => {
    console.log("FFMEPG-ERROR", err)
});

ffmpeg.on("close", (code) => {
    console.log("ffmepg exited", code);
});

ffmpeg.stdin.on("error", (err) => {
    if (err.code === "EPIPE") {

        // ignore EPIPE error
        // throws sometimes a EPIPE error, ignore as long ffmpeg exit with code 0

    } else {
        console.log("ffmepg stdin error", err);
    }
});

ffmpeg.stdin.write(data);

Basicly spawn ffmepg, to read from stdin, -i pipe: or -i -, and start pumping data into stdin.

To test the ffmpeg command, you can ran the command below. This creates a thumbnail at 10sec of the input data. Keep in mind to adjust the file type (-f option) to match your input data, since ffmepg cant autodetect it when it reads from stdin. The -y flag is to override a allready existing output file.

cat input.avi | ffmpeg -ss 00:10:00 -y -f avi -i pipe: -vframes 1 output.jpg

Some people mention to use -ss as the first option to seek faster, but it has no effect on my test. You can read here more: https://mcmap.net/q/127157/-how-to-extract-1-screenshot-for-a-video-with-ffmpeg-at-a-given-time

Let me know if you need any furthur help.

Ozzie answered 23/11, 2021 at 19:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.