Blumenthaler
Blumenthaler

Reputation: 51

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

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

Upvotes: 1

Views: 2520

Answers (1)

Marc
Marc

Reputation: 3876

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://stackoverflow.com/a/27573049/5781499

Let me know if you need any furthur help.

Upvotes: 4

Related Questions