Search code examples
node.jsffmpegnode.js-fs

How can I get the location of my screenshot made from video with ffmpeg in Node.js?


This is how I did it.

const ffmpegPath = require('@ffmpeg-installer/ffmpeg');
import ffmpeg from 'fluent-ffmpeg';
import path from 'path';
const os = require('os');
ffmpeg.setFfmpegPath(ffmpegPath.path);


export const generateThumbnailFromVideo = async (mp4Buffer) => {
    console.log('generateThumbnailFromVideo is triggered');
    const timePosition = '00:00:00.500';
    const filename = `temp/temp-${new Date().getTime()}.png`;
    return new Promise((resolve, reject) => {
        ffmpeg({
            source: bufferToStream(mp4Buffer)
        })
        .on('error', (err) => {
            console.error('An error occurred: ' + err.message);
            reject(err);
        })
        .on('end', () => {
            console.log('Thumbnail generated successfully');
            fs.readFile(filename, (err, data) => {
                if (err) {
                    console.error('An error occurred while reading the thumbnail file:', err);
                    reject(err);
                    return;
                }
                fs.unlink(filename);
                uploadBuffer(data, filename, data.length)
            })
            resolve(filename);
        })
        .screenshots({
            timestamps: [timePosition],
            filename: filename,
            folder: 'temp/',
            size: '320x240',
        });
    });
}

And this is the log came up.

generateThumbnailFromVideo is triggered
Thumbnail generated successfully
createProjectMedia is triggered
userId:  1
projectId:  25
mediaArray:  [
  {
    mediaUrl: 'medias/1/1686843801535/medias_1_1684753043519_1_(1)_(4)_(1).mp4',
    thumbnailUrl: 'medias/1/1686843801535/medias_1_1684753043519_1_(1)_(4)_(1)_thumbnail.jpg',
    mediaType: 2
  }
]
An error occurred while reading the thumbnail file: [Error: ENOENT: no such file or directory, open 'temp/temp-1686843802255.png'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'temp/temp-1686843802255.png'
}

It claims the screenshot has been created but I cannot find it anywhere. Tried absolute route with __dirname and os.tmpdir() with no luck. The screenshot it claimed has been created are not there.

Can somebody help me out? I have been stuck here for 5 hours with no progress so far.

Also, I have checked the file temp in the root directory of the repo. It is empty.

UPDATE: Checked and can confirm that the router used in the key "folder" (temp/) is correct, since deleting that folder will trigger an error saying that the folder is not found. Creating the folder again will remove this error. But even though the "generated successfully" log is printed, the image is not saved in that folder, and the folder is still empty after that log is printed.

That fs.unlink is also unrelated. Removing it won't cause any change.


Solution

  • To make this work, you are required to do two things.

    First, change the argument of ffmpeg fuction, from a stream to a file path. ffmpeg({source: bufferToStream(mp4Buffer)}) => ffmpeg("abc.mp4"). Because according to docs,

    It will not work on input streams

    Second, remove the folder property from screenshot method, as you've already specified designated folder in filename variable.

    const filename = `temp/temp-${new Date().getTime()}.png`;
    

    and your screenshot method becomes:

      .screenshots({
            timestamps: [timePosition],
            filename: filename,
            size: '320x240',
        });