'FFMPEG take 3 minutes to generate thumbanils

I am generating the sprite image (combined thumbnails/screenshots) using FLUENT-FFMPEG and node js, the image looks like this.

enter image description here

Here is my node js script for generating sprite images/thumbnails.

const ffmpegPath = require("@ffmpeg-installer/ffmpeg").path;
const ffmpegCommand = require("fluent-ffmpeg");
ffmpegCommand.setFfmpegPath(ffmpegPath);

let videoUrl =
  "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4";
const filename = `output_image`;

ffmpegCommand(videoUrl)
  .seekInput("00:00:01.000")
  .outputOptions([
    "-q:v",
    "8",
    "-frames:v",
    "1",
    "-vsync",
    "0",
    "-qscale",
    "50",
    "-vf",
    "fps=1/10,scale=128:72,tile=11x11",
  ])
  .addOption("-preset", "superfast")
  .on("error", (err) => {
    console.log("error", err);
    reject(err);
  })

  .save(`./tmp/${filename}.png`);

Unfortunately, it takes almost 3 minutes to generate this image which is so bad.

UPDATE

@kesh answer is working only with internal videos.

if I add the video URL as follows.

let videoUrl ="./videos/t.mp4";

then it takes less than 3 seconds to generate thumbnails.

but if I use an external URL as follows.

let videoUrl ="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4";

Weird, it takes too long to generate thumbnails more than 3 minutes depending on the video.

NOTE you can read full documentation here about FFmpeg and node js.

What do I need to change so that I can super fast generate my thumbnails?



Solution 1:[1]

tl;dr Use the -discard nokey input option

It takes so long because it's decoding all the video frames to cover 1210 seconds (~2 minutes of the content). ...well, I don't know exactly why your setup takes 3 minutes tho...

Anyway, starting with the fps filter is good to reduce the filtering load (scaling is only performed on the frames that you want to include) but it doesn't prevent all the frames to be decoded, only For the most of them to be thrown out (keeping only 1 out of 240).

One way (only way?) to prevent decoder to process all the frames is to tell it to ignore non-keyframes. The keyframe interval should be tight enough you'd still get the desired effect.

I've tested it with the following command:

ffmpeg -ss 1 -discard nokey -i "{inurl}" \
       -vf fps=1/10,scale=128:72,tile=11x11 \
       -an -frames:v 1 {outurl}

My (~10-years-old) PC took 36.3s without -discard nokey while it took only 2.7s with the option. (tested in Python)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1