How to access webcam and take photo with JavaScript
Recently, computer vision has been a hot topic, which enable applications to deliver new, engaging user experiences. In order to bring computer vision to the browser, one of the key element is being able to access the webcam with JavaScript.
To contribute to the computer vision open source community, I had built a npm module called ‘webcam-easy‘, which provides an easy to use JavaScript module that can access webcam and take photo. You can try it yourself in the below demo.
Webcam-easy.js demo
If you are browsing through social media built in browsers, you would need to open the page in Sarafi (iPhone)/ Chrome (Android)
GitHub repository
You can download the complete code of the above demo in the link below:
You can easily add it as a module to your own app.
How to use webcam-easy.js
webcam-easy.js a JavaScript module I built for accessing webcam stream, it can allows us to capture a picture from the webcam. Below are the major features for webcam-easy.js:
- Streaming webcam on desktop computer or mobile
- Switch back or front cameras on mobile
- Take pictures and be able to download.
You can easily add it as a module to your own application. If you are building an web-app that need to access webcam in the browser, this is for you! I will show you step by step instruction below of how to use this module.
# Step 1 : Include webcam-easy.js
First of all, simply include the script webcam-easy.min.js
in the <head> section of the html file.
<html>
<head>
<script type="text/javascript" src="https://unpkg.com/webcam-easy/dist/webcam-easy.min.js"></script>
</head>
Or you can install it via npm for use in a TypeScript / ES6 project
npm install webcam-easy
import Webcam from 'webcam-easy';
# Step 2 : Place elements in HTML
The next thing we will need to do is to add the html elements below
- webcam video element
- canvas element for capture picture
- optional audio element for the snap sound
<video id="webcam" autoplay playsinline width="640" height="480"></video>
<canvas id="canvas" class="d-none"></canvas>
<audio id="snapSound" src="audio/snap.wav" preload = "auto"></audio>
# Step 3 : Initialize webcam object
Then, we will initialize the Webcam
object, the constructor accepts below parameters
- webcamElement – the webcam <video> html element
- facingMode – ‘user’ or ‘element’, default value is ‘user’
- canvasElement & snapSoundElement are optional
const webcamElement = document.getElementById('webcam');
const canvasElement = document.getElementById('canvas');
const snapSoundElement = document.getElementById('snapSound');
const webcam = new Webcam(webcamElement, 'user', canvasElement, snapSoundElement);
# Step 4 : Start Webcam
By calling the webcam.start()
function, the browser will ask user permission to access the camera, once it is allowed, it will start steaming the webcam to the video element.
webcam.start()
.then(result =>{
console.log("webcam started");
})
.catch(err => {
console.log(err);
});
# Step 5 : Snapshot
Just call webcam.snap()
function to capture snapshot of the webcam. The function returns a data URI
containing a representation of the image in the format of PNG. By setting the an html <a> link’s ‘href’ attribute to the image data return, the user can download and save the snapshot.
let picture = webcam.snap();
document.querySelector('#download-photo').href = picture;
# Step 6 : Stop webcam
You also want the user to be able to stop their webcam, simply call the webcam.stop()
function.
Mobile front & back camera support
webcam-easy.js not only work for desktop webcam, it also support mobile front and back camera as well. When you initialize the Webcam
object, you can pass the facingMode
parameter, while ‘user’ represent the front camera that facing the user, and ‘environment’ represent the back camera.
You can also call the webcam.flip()
to switch between front and back camera.
$('#cameraFlip').click(function() {
webcam.flip();
webcam.start();
});
How I implemented webcam-easy.js
Here, I would also like to share some technical details of how I implemented this JavaScript module. I had checkout some other open source webcam JS libraries, and find some works on desktop but not on mobile, some works only on front camera but not on rear camera, some is not mirroring the webcam… Below I am going to show you how I overcome those challenges.
Check browser support
Most of the modern browsers do support webcam access on desktop/laptop, but unfortunately, not including IE.
As of Chrome 47, the getUserMedia API cannot be called from insecure origins. It means for security reason, the url required to be in https protocol, http url can not access webcam.
Another important thing to know is on iPhone/iPad, only Safari can access webcam, all other browser apps like Chrome or other social media build in browsers can not access webcam. On Android phones, webcam works fine in Chrome app.
Get media devices and stream
All the functionalities are exposed by the MediaDevices object, which is returned by navigator.mediaDevices
. MediaDevices has two methods, enumerateDevices()
and getUserMedia()
.
enumerateDevices()
Returns a Promise giving access to an array of MediaDeviceInfo
objects for available devices. It not only contain video inputs, but also audio inputs. The MediaDeviceInfo
objects contains some valuable information, below are the properties of the object
- deviceId – an identifier for the represented device.
- groupId – a group identifier. Two devices have the same group identifier if they belong to the same physical device — for example a monitor with both a built-in camera and a microphone.
- kind – an enumerated value that is either
"videoinput"
,"audioinput"
or"audiooutput"
- label – a label describing this device (for example “Front camera”, “Back camera”).
If you only want to retrieve the video input, filter by the kind
property.
navigator.mediaDevices.enumerateDevices()
.then(getVideoInputs)
.catch(errorCallback);
function getVideoInputs(mediaDevices){
mediaDevices.forEach(mediaDevice => {
if (mediaDevice.kind === 'videoinput') {
this._webcamList.push(mediaDevice);
}
});
}
I find out that before the user grant permission to access the webcam, the MediaDeviceInfo
objects get return does not expose any information, both the deviceId and label would be empty.
getUserMedia()
Returns a Promise that gives access to a MediaStream
. And user will be prompt to grant access to webcam. Then you can set the video html element’s srcObject to be the stream, and call play() to start streaming the webcam.
navigator.mediaDevices.getUserMedia(this.getMediaConstraints())
.then(stream => {
this._webcamElement.srcObject = stream;
this._webcamElement.play();
})
.catch(error => {
//...
});
And make sure the video html element had include autoplay
and playsinline
property.
<video id="webcam" autoplay playsinline></video>
Mirror webcam
As an expected user experience, when you are streaming a user facing webcam, the image should mirror what’s captured. You can achieve this by apply the transform style.
if(this._facingMode == 'user'){
this._webcamElement.style.transform = "scale(-1,1)";
}
Conclusion
If you are building a computer vision web-app that need to access the webcam, consider using webcam-easy.js JavaScript module, it will save you a lot of time. Then you can do all sort of cool things like real-time face detection, real-time object tracking, motion detection…
Thank you for reading. If you like this article, please share on Facebook or Twitter. Let me know in the comment if you have any questions. Follow me on Medium, GitHub and Linkedin. Support me on Ko-fi.
62 Comments
Halo Mr Benson.
I used you demo in my project and it is ver good. I had difficulties to resize the image in order to easly save in a file. Can you halp me how to resize it please?
Hi,
You can have a look at the below function, it takes a data URI and returns the Data URI corresponding to the resized image at the wanted size.
function resizedataURL(datas, wantedWidth, wantedHeight)
{
var img = document.createElement(‘img’);
img.onload = function(){
var canvas = document.createElement(‘canvas’);
var ctx = canvas.getContext(‘2d’);
canvas.width = wantedWidth;
canvas.height = wantedHeight;
ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
var dataURI = canvas.toDataURL();
return dataURI;
};
img.src = datas;
}
Use it like that : resizedataURL(‘yourDataURIHere’, 50, 50);
It is the picture that is snapped I would like to resize, but have no idea how to know the url, to put in this function /
if you work on localhost (127.0.0.1), you should try to set up SSL on your localhost and then use https in your URL, it could be the reason that on mobile it treats http not safe and not allow it to access the camera.
Hi, It’s very helpful library.. i’m about to use this library in my Project.
It’s working on my Localhost but when i uploaded to my server then it’s giving error message :-
Fail to start camera, please allow permission to access camera.
If you are browsing through social media built in browsers, you would need to open the page in Sarafi (iPhone)/ Chrome (Android)
—
i’m accessing my server with IP.
can you please help me what i’m missing?
Hi, most likely it is because you are not accessing via https, the browser treats http not safe and not allow it to access the webcam.
Hi, Thanks a lot! It works now 🙂
one more thing, it’s not working on Chrome for IPHONE.
Is there any solution for this? or any reference how can i resolve this
i really appreciate
It work for me in chrome too.
Hi, for IPHONE, the only browser that can access camera is Safari, this is purely because Apple doesn’t not allow any other browser to access the camera.
Hi. Thanks for this great resource. I am trying to use this in my Express.JS project, which uses EJS as its view engine, and not HTML. EJS does not support the document.getElementById selector as well as the canvas element. Also I need to pass the captured shot through a route to upload to my database; how do you think I can implement this? Please is there a way you could help to work around this? So far, your solution is the best yet I have seen on the web, and I really want and need to implement it. Awaiting your reply!
Hi, thks for this post.
I got this error in IE 11:
SCRIPT1002: Error de sintaxis
webcam-easy.min.js (1,1)
Any suggestion ? thks
This is because IE 11 do not support ES6 import syntax. https://caniuse.com/#search=es6
IE is no longer a modern browser anymore, Microsoft had announced they no longer support IE.
IE is a time of past, Chrome and Safari is now more popular browsers now.
thank you for sharing this module, what if i use 2 web camera and want to capture and save to the file?
regards,
adhi
Hi Benson, thank you for this awesome plugin! One question, is there any way to change the image resolution when using snap() function?
How can I reduce the length of the image URI to pass it as a paramter in a POST request? I am currently getting a payload error when submitting the request.
Hello, how do you save the picture to app directory?
can i use this in the visual code studio
How to switch to back Camera on Windows 10 device (e.g. A surface)?I can not access the Front cam there. Is there a way to do this with this .js lib? P.S: Switch to front cam does not work in example too…
For mobile phones, the camera usually named with ‘Front Camera’ and ‘Back Camera’. For Windows 10 surface, they could came with different names. In the webcam-easy.js selectCamera() function, you can modify the .includes(‘font’) and .includes(‘back’) to the camera names of your Windows 10 device
Hello mr Benson, i’m enjoying your demo very much.. but have some difficulties implementing socket io. I would like to store captured image on server. Best Regards
Hello Mr. Benson,
thank you for the script. I want to ask how to display the full screen page?
Hi, to display full screen of your camera, you can modify the css of #webcam, with:100vw means full width of your screen, height:100vh means full height of your screen.
If I display controls, they appear backwards; i.e., the stop button appears on the right instead of the left. Playing with scale(-1,1) didn’t seem to work for me.
Hi Benson, thanks so much for this lovely JavaScript module, it’s exactly what I was looking for! Any advice on how I can use it and add a custom photo frame to the photo? So when the camera is active, you see the photo frame on the screen, and it saves the photo frame with the photo taken. Thanks in advance!
Hi, I would suggest to overlay the photo frame html element over the webcame video object use css, then when you capture the photo, you would need to use some js library like html2canvas https://html2canvas.hertzen.com/
I have a laptop with front and rear camera I can see the rear camera how can I access the front camera?
For mobile phones, the camera usually named with ‘Front Camera’ and ‘Back Camera’. For your laptop, they could came with different names. In the webcam-easy.js selectCamera() function, you can modify the .includes(‘font’) and .includes(‘back’) to the camera names of your cameras
Hello : this behaviour is broken on iOs phones and iOs pads. ( they are called cam1 and cam2 ) , the only way on iOs is ask in the video constraints ( with “exact” ) . And be careful there is a typo error in your lib on “environment”.
hi to you know, if this library is useful for IOS on mobile for rear cam too ? I can not change on start to enviroment. Have you experience
Hello thank you for this library : is there a way not to correlate the resolution of the screenshot, and the display size of the html element video ?
Actually the resolution of the screenshot is decided by the css rules of the video element height and width.
It should be independant, or customizable.
I try change canvas height and width but it doesn’t change the behaviour.
Hi, you can try setting the video constraints in the webcam-easy.js getMediaConstraints() function
https://github.com/webrtc/samples/blob/gh-pages/src/content/getusermedia/resolution/js/main.js
Hi, great work here!
I test drove it, is there a way to improve the quality of the photos taken? I have a good camera on my phone, it takes great pictures when using the default camera app but when I tried it with this the quality of the photos taken by webcam-easy is not that good.
Hi, you can try setting the video constraints in the webcam-easy.js getMediaConstraints() function, I had put links for the webcam resolution below
https://webrtc.github.io/samples/src/content/getusermedia/resolution/
https://github.com/webrtc/samples/blob/gh-pages/src/content/getusermedia/resolution/js/main.js
Hello, I have seen your good work but I am a beginner programmer. So I still can’t implement it on node js with hbs views. Can you help me with that ? Thank you
I can seem to get your demo file working all it does is start the camera switch – is there something I am doing wrong – sorry novice.
Great app and it worked as advertised. Thank you. One question… in addition to taking a picture I want an option to actually record the stream into a blob object, much like the short repeating clip you post on this page. Do you have a code snippet for that functionality?
Hi Benson,
I’ve been struggling with these basics for a couple hours. No matter what I get this error:
TypeError: Cannot read property ‘getUserMedia’ of undefined.
Your version works on all my computers. I get this error on all of mine.
Is there something I’m doing wrong here?: https://jsfiddle.net/bau2p7vq/10/
Thanks! Any help would be appreciated!
I tested your code on that link you provided with Chrome on windows, and the webcam stream do work
MUST USE httpSSSSSSSS It’s important to point out this detail. It will fail every time unless the url you are using includes this. This robbed me of 3 hours of my life.
That’s correct, I did mention that in the above article in the section of “Check browser support”
hello,
will this not work on http and is this only limited to https? I get a message when I run the app through a server . Fail to start camera please allow permission to access camera. Works only when we run the app on localhost .Any help?
Thanks,
jay
When you are accessing the camera on a public domain rather than localhost, it would require https. This is because modern browsers like Chrome, Safari, Firefox only allow https to access camera for security concern, you won’t find any javascript library that can access camera on http of a public domain.
Hello, does anyone has any code for the following:
Open the phone camera
scan QR code
Save details of the QR code on the database of the member.
Can anyone help?
Hi,
I am trying to use your library inside a Google Sheet to take a picture with a LOCAL WEBCAM or HTTP WEBCAM using Google Apps Script.
It is possible ? Or I must use local NodeJS installation ? Can you help me ?
I explain better, I want to make a DB of objects on GoogleSheet and save also a photo of the object using local webcam and save the jpg on a google sheet cell
Hello! Thank you for this amazing project. I want to use the camera without the mirror function. How do I implement this using the webcam.easy program without modifying the source file?
Thank you!
Hello Benson thanks for this awesome plugin. but i have a problem, each time i start the webcam it appears for some seconds and then the video disappears. I don’t know what is wrong
hello, please help me to add 5sec count down timer before it call webcam.snap() function, thanks
Hello,
I want to open my mobile camera with the highest resolution supported. Some mobile devices are capable of 2k whereas some are 4k. I want to make general function which will return highest possible resolution and open the camera with that configuration. Can I do that by using your module?
How would one get an image and upload it to a server?
Hi Benson, I am not able to take a snapshot using webcam.snap(). I want to save the snapshot in my local directory. How do I achieve this? Thanks.
So so I need to use the CDN or are the supplied files the full plugin?
I wish to access a webcam through an IP address which is other than the current system in a LAN. How can I?
This is not working even after following all the steps…the following error is appearing
typeError: Cannot set properties of undefined (setting ‘transform’)
at webcam-easy.min.js:1
Dear Mr. Benson,
we are using your Plug-In in a little warehouse where the Operators would like to catch the photo of packaging and products packaged in 500g,750g boxes.
We would need of IOS feature (with Safari) that uses the environment camera. The use of the front camera isn’t enough, and it is hard to apply in this case, unfortunately.
Could you help us in this direction ?
You can contact me directly in private if you prefer.
We are available to consider your specific development/support to introduce the feature.
Thanks a lot.
Roberto
how to add camraflip on webcam in asp.net
Hi, I am using a HTTPS secured URL but still it is showing me permission error when i am trying to open back camera by setting the facinngmode Enviroment .
It is working fine for the Front Camera only back camera is showing permission error in my android phone,
Fail to start camera, please allow permission to access camera.
If you are browsing through social media built in browsers, you would need to open the page in Safari (iPhone)/ Chrome (Android)
It is possible that you have not enabled the permission for the camera in your settings.
To enable the permission, go to Settings > Apps > [App Name] > Permissions > Camera and enable the permission.
Once you have enabled the permission, try opening the camera again.
Nice, I’ve just update some deps, and fixed webpack config.
https://github.com/bensonruan/webcam-easy/pull/47
Hi this is very good help.
But I want to just know how to allow webcam in CSP content security policy header.
I m not able to access webcam if I put csp default-src self
Thank you for your comment! I’m glad that you found the information helpful.
To allow access to the webcam in the Content Security Policy (CSP) header, you need to include the appropriate directive in your policy. The directive you are looking for is `media-src`.
By default, the `default-src` directive only allows resources to be loaded from the same origin. This means that if you include `default-src self` in your CSP header, it will block any requests to access the webcam.
To enable webcam access, you can modify your CSP header to include the `media-src` directive along with the `self` keyword. For example, you can set the CSP header as follows:
“`
Content-Security-Policy: default-src ‘self’; media-src ‘self’
“`
This will allow the browser to load media resources, including the webcam, from the same origin.
Please note that modifying the CSP header can have security implications, so it’s important to carefully consider the risks and test thoroughly before implementing any changes.
Hi, I’m using this fantastic plugin but it looks like it doesn’t works for Android devices or maybe I’m missing something.
It runs very well on iOS devices but when I try with an Android phone, I’m always getting the “notreadableerror could not start video source”. I wonder that it’s due to the multiple cameras of the phone. Any suggestion to fix this?
Thank you in advance