Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capture a shot in memory and not save to disk #10

Open
RobertSmart opened this issue Apr 6, 2017 · 13 comments
Open

Capture a shot in memory and not save to disk #10

RobertSmart opened this issue Apr 6, 2017 · 13 comments

Comments

@RobertSmart
Copy link

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

@michaelorr92
Copy link

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);
  });
});

@RobertSmart
Copy link
Author

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.

@chuckfairy
Copy link
Owner

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 chuckfairy changed the title How does this work? Capture a shot in memory and not save to disk Apr 26, 2017
@RobertSmart
Copy link
Author

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!!

@chuckfairy
Copy link
Owner

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

@RobertSmart
Copy link
Author

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" me@gmail.com ; sleep 300 ; done

Any ideas?

@RobertSmart
Copy link
Author

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;

});

@shadowofsoul
Copy link

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 :)

@werlious
Copy link

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)

@chuckfairy
Copy link
Owner

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

@Bellisario
Copy link

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");
});

@paulash
Copy link

paulash commented May 15, 2023

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/

@metadetron
Copy link

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

@houzhongjian
Copy link

houzhongjian commented Jan 23, 2024 via email

Repository owner deleted a comment from Idris933 Mar 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants