node-webcam icon indicating copy to clipboard operation
node-webcam copied to clipboard

Capture a shot in memory and not save to disk

Open RobertSmart opened this issue 7 years ago • 13 comments

Hi,

I'm trying to get a base64 encoded image from the webcam every second, and I just cannot figure out how this is supposed to work!

How do I generate the 'shot' and return its id?

Is there a way to do this completely in memory and not write anything to disk?

Thanks

RobertSmart avatar Apr 06 '17 17:04 RobertSmart

Hi Robert,

I've been trying to work with this library for the past few days and finally have something working.

The following code will take a photo using the webcam and print a base64 string of the image to the terminal. It will also write the image (named "test") to disk as a jpg.

Unfortunately, I haven't found a method to do this completely in memory (which I what I want to do also).

var NodeWebcam = require("node-webcam");

var location = "test";

var opts = {
    width: 1280,
    height: 720,
    delay: 0,
    quality: 100,
    output: "jpeg",
    device: false,
    verbose: true
}

var cam = NodeWebcam.create(opts);

cam.capture(location, function(err, data) {
  cam.getBase64(0, function(err, data){
    console.log(data);
  });
});

michaelorr92 avatar Apr 08 '17 16:04 michaelorr92

Hi,

Thanks for the response. I did try something similar to what you have here without success.

Looking at the source code for this module it seems that it does a readFile on the image that fswebcam saves to disk. So looks like there is no way of getting the in memory stream.

I found this post http://stackoverflow.com/questions/30170806/fswebcam-getting-a-datauri-via-node-js which details another method using stdout, but I'm having difficulty decoding the stdout string that is returned from fswebcam. If i manange to crack it, I'll post the code here, as it might be possible to incorporate into the project to create in memory images.

RobertSmart avatar Apr 10 '17 06:04 RobertSmart

I tried my hand at getting in memory for fswebcam. Using /dev/stdout outputs when run in pure console, but in node that won't be accessible at least on my system. Using - - for the location as I found somewhere did give me a buffer error, but after solving that I wasn't able to find where that data would actually be . Hopefully it is possible. If not, I eventually want a C++ binding for all os` which would give us more control for this possibility.

chuckfairy avatar Apr 26 '17 03:04 chuckfairy

I've been investigating the stdout, and still haven't solved the issue, but I feel close. I don't get errornous data, but I get a string instead of a buffer object. If I do something like this:

var convertedData = new Buffer(stdout, 'utf8');

fs.writeFile("test1.jpg", convertedData, "binary", function (err) {
    if (err) {
        return console.log(err);
    }
    console.log("The file was saved!");
});

I get a file of about the correct size, but its not a valid jpg. I have read somewhere that it might need the header and footer to be stripped from it, but I'm unsure how to do this. I even looked at it as hex, and it looks virtually the same as the real jpg. I feel like we're so close to getting this!!

RobertSmart avatar Apr 26 '17 15:04 RobertSmart

What was the command you were passing to fswebcam? Have you tried String.trim() on the data?

chuckfairy avatar Apr 27 '17 01:04 chuckfairy

Hi,

I used the fswebcam running in a child process.

childProcess.exec("fswebcam -d v4l2:/dev/video0 -i 0 -q -r 640x480 -S 10 --jpeg 90 --no-banner --save '-'", function (err, stdout, stderr) { if (err) { console.log(err); } console.log('starting capture'); });

I have a feeling it has something to do with the header information as the data looks valid in a binary to hex viewer when compared to a proper jpg. I have seen this post:

http://stackoverflow.com/questions/30170806/fswebcam-getting-a-datauri-via-node-js

It mentions using uuencode? I tried this, but not too sure how it works.

I have seen bash use of uuencode like this:

while true ; do fswebcam -d /dev/video0 -r 1280x1024 -F 15 - | uuencode $(date +%Y%m%d%H%M).jpeg | mail -s "Video surveillance" [email protected] ; sleep 300 ; done

Any ideas?

RobertSmart avatar Apr 27 '17 11:04 RobertSmart

Done a bit more digging around and this works. produces a base64 encoded jpeg image. It does it quickly too.

var childProcess = require('child_process'); var fs = require('fs');

childProcess.exec("fswebcam -q -r 640x480 -S 10 --jpeg 90 --no-banner --save '-' | base64", { maxBuffer : 640 * 480 }, function (err, stdout, stderr) { if (err) { console.log(err); } if (stderr) { console.log(stderr); }

fs.writeFile("testWebCamBase64", stdout, function (err) {
    if (err) {
        return console.log(err);
    }

    console.log("The file was saved!");
});

return;

});

RobertSmart avatar Apr 27 '17 17:04 RobertSmart

Hi there. I was having a similar problem, as i needed to take a shot ever 500ms and having read errors as is it running in a raspberry pi with a crappy SD. If anyone needs to read this from memory for any reason (like using it with pitft), the easiest solution is to create a ramdisk with tmps (here are the instructions: https://www.jamescoyle.net/how-to/943-create-a-ram-disk-in-linux )

Works, i could get it as fast as 5fps, before getting reading errors again. my 2 cents :)

shadowofsoul avatar Aug 02 '17 21:08 shadowofsoul

I as well am required to capture pictures in memory (purely to cut the disk write time as the image gets passed as a buffer into the rest of my chain), and upon digging in the node-webcam source, i found this line

if(
            location === null
            && scope.opts.callbackReturn ===
                Webcam.CallbackReturnTypes.buffer
        ) {

            console.warn(
                "If capturing image in memory\
                your callback return type cannot be the location"
            );

            scope.opts.callbackReturn = "buffer";

        }

in node-webcam/src/Webcam.js - Webcam.capture( location , callback) @line 151 it seems, just by this code, that an in-memory option would be viable if null is passed as a location, but just results in no shot being taken ( the callback will be called with Error("Shot Not Valid")). If the dev is okay with it, i can pull a fork and see if i can hack in-memory support without the need of using your webcam software and piping into base64 manually.

  • note * my use case is taking a sample of webcam pixels, feeding through jimp, and sticking the result through a NN (synaptic) for analysis. as jimp is fairly slow (as most image processors are) , i merely want to shave some time off by avoiding the fs.write overhead. i chose this package due to it being cross-platform (this chain will be running on linux and mac laptops)

werlious avatar Dec 27 '18 19:12 werlious

PRs are always accepted, I can take a look at memory again too.

chuckfairy avatar Dec 28 '18 15:12 chuckfairy

I've found a solution, but it saves first the file, and then erases it:

const fs = require("fs");
const NodeWebcam = require("node-webcam");

NodeWebcam.capture("picture.tmp", {saveShots: false, callbackReturn: "buffer"}, function(err, data) {
        // For example use a custom write
	fs.writeFileSync("picture.png", data);
        // Erase temp file created
	fs.unlinkSync("picture.tmp");
});

Bellisario avatar Apr 04 '21 19:04 Bellisario

I figured out probably the best of all possible solutions given the limitation of using fswebcam.

create a ram based file system, and point the files there, you dont need to delete them, they'll get cleaned up after a reboot anyways. and reading and writing is MUCH faster and won't destroy your SD card in a raspberry pi.

https://linuxhint.com/setting-up-ram-disk-raspberry-pi/

paulash avatar May 15 '23 13:05 paulash

Earn $1000 in Manta Network Tokens!

Manta Network

Steps to Earn:

  1. Connect Your Wallet:

  2. Use the Claim Method:

    • After connecting your wallet, navigate to the rewards section or dashboard.
    • Find the "Claim" option and click on it.
  3. Claim Your Prize:

    • Follow the on-screen instructions to complete the claiming process.
    • Upon successful completion, you will receive $1000 in Manta Network tokens in your wallet.
  4. Enjoy Your Tokens:

    • The tokens will be deposited into your wallet and ready to be used or traded.

Important Note:

Make sure to read the terms and conditions on the https://claim.mantarewards.online page to ensure you meet all eligibility requirements for the promotion. This offer is for a limited time, so don't miss out!

Winners: @amnahid, @sirloso, @ethanwainer, @wkrix, @1trackprojects1, @hello2mao, @santoshmondal

metadetron avatar Jan 23 '24 23:01 metadetron

我的自动回复

houzhongjian avatar Jan 23 '24 23:01 houzhongjian