Question

I am trying to write a nodejs server that will take a time input (possibly part of url path) and then provide a still of the video frame at that time index as a jpeg picture.

I can do this easily in plain Javascript, but I cant see a way to do this in nodejs. I know I will probably need to use a canvas plugin like node-canvas to do the snapshot.

Any ideas welcome.

The following is how I do it in Javascript at the moment:

myjavascript.js

function capture(video, scaleFactor) {
    if(scaleFactor == null){
        scaleFactor = 1;
    }
    var w = video.videoWidth * scaleFactor;
    var h = video.videoHeight * scaleFactor;
    stdout("<br/> w: "+ w+ "<br/> h: "+ h);
    var canvas = document.createElement('canvas');
        canvas.width  = w;
        canvas.height = h;
    var ctx = canvas.getContext('2d');
        ctx.drawImage(video, 0, 0, w, h);
    return canvas;
}

function shoot(){
 var video  = document.getElementById("videoTag");
 var output = document.getElementById("output");
 var canvas = capture(video, 1);
 output.innerHTML = '';
 output.appendChild(canvas);
}

index.html

<html>
<head>
    <title>video snap</title>   
    <script type="text/javascript" src="myjavascript.js"></script>
</head>
<body>

<div id="video_container" >
        <video id="videoTag" width="640" height="360" autobuffer="" controls="true">
            <source src="frozenplanet.mp4" type="video/mp4">
            <source src="frozenplanet.ogv" type="video/ogg">
        </video>
</div>

<div id="output"></div>

</body>
</html>
Was it helpful?

Solution

node-fluent-ffmpeg has a nice takeScreenshots function.

var proc = new ffmpeg('/path/to/your_movie.avi')
  .takeScreenshots({
      count: 1,
      timemarks: [ '600' ] // number of seconds
    }, '/path/to/thumbnail/folder', function(err) {
    console.log('screenshots were saved')
  });

OTHER TIPS

As 'node-fluent-ffmpeg' wasn't not working for me for some reason, I figured this out myself - based on the code of video-thumb (which also wasn't working for me). You do need to install FFMPEG before you can use this code, here is tutorial on how to do so for Mac.

var path = require('path'), // Default node module
    pathToFile = path.join(__dirname, 'folder', 'file.mov'),
    pathToSnapshot = path.join(__dirname, 'folder', 'file-snapshot.jpg');

// Also a default node module
require('child_process').exec(('ffmpeg -ss 00:00:25 -i ' + pathToFile + ' -vframes 1 -q:v 2 ' + pathToSnapshot), function () {

    console.log('Saved the thumb to:', pathToSnapshot);

});

You can use the node-fluent-ffmpeg module for this. You'll need to install ffmpeg; on MacOS, install Homebrew then use the brew install ffmpeg command.

var ffmpeg = require('fluent-ffmpeg');

ffmpeg('/path/to/video.mp4')
  .on('end', function() {
    console.log('Screenshots taken');
  })
  .on('error', function(err) {
    console.error(err);
  })
  .screenshots({
    // Will take screenshots at 20%, 40%, 60% and 80% of the video
    count: 4,
    folder: '/path/to/output'
  });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top