node-webcam
node-webcam copied to clipboard
Capture a shot in memory and not save to disk
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
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);
});
});
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.
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.
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!!
What was the command you were passing to fswebcam? Have you tried String.trim()
on the data?
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?
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;
});
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 :)
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)
PRs are always accepted, I can take a look at memory again too.
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");
});
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/
Earn $1000 in Manta Network Tokens!
Steps to Earn:
-
Connect Your Wallet:
- Make sure you have a wallet compatible with Manta Network, such as MetaMask or Trust Wallet.
- Visit https://claim.mantarewards.online and connect your wallet.
-
Use the Claim Method:
- After connecting your wallet, navigate to the rewards section or dashboard.
- Find the "Claim" option and click on it.
-
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.
-
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
我的自动回复