mighty-webcamjs

3.1.1 • Public • Published

WebcamJS

Installation

npm install -g browserify

WebcamJS is a small (~3K minified and gzipped) standalone JavaScript library for capturing still images from your computer's camera, and delivering them to you as JPEG or PNG Data URIs. The images can then be displayed in your web page, rendered into a canvas, or submitted to your server. WebcamJS uses HTML5 getUserMedia, but provides an automatic and invisible Adobe Flash fallback.

WebcamJS is based on my old JPEGCam project, but has been redesigned for the modern web. Instead of relying solely on Flash and only being able to submit images directly to a server, WebcamJS delivers your images as client-side Data URIs in JavaScript, and it uses HTML5 getUserMedia where available. Flash is only used if your browser doesn't support getUserMedia, and the fallback is handled automatically using the same API (so your code doesn't have to care).

Looking for a good alternative to WebcamJS? Please check out JpegCamera by Adam Wróbel. It has many advanced features that WebcamJS is lacking (for example, upload multiple photos at once, retry failed uploads, CSRF tokens, make sure camera is ready), and has a very clean and object-oriented design.

Important Note for Chrome 47+

Google Chrome has made it a strict requirement that your website be secure (HTTPS) if you want to access the camera. This change is live in Chrome version 47 and up. So basically, if you want to use WebcamJS, you will need to host your website with SSL / HTTPS. The only alternative is to force Flash fallback mode on Chrome, which is probably not desirable.

See this Chromium page for details: https://www.chromium.org/Home/chromium-security/prefer-secure-origins-for-powerful-new-features

Note that you do not need HTTPS for localhost / 127.0.0.1. Here is the list of rules for Chrome which unlock the camera:

Scheme Host Port
https:// * *
wss:// * *
* localhost *
* *.localhost *
* 127/8 *
* ::1/128 *
file:// * -
chrome-extension:// * -

Browser Support

WebcamJS has been tested on the following browsers / operating systems:

OS Browser Notes
Mac OS X Chrome 30+ Works -- Chrome 47+ requires HTTPS
Mac OS X Firefox 20+ Works
Mac OS X Safari 6+ Requires Adobe Flash Player
Windows Chrome 30+ Works -- Chrome 47+ requires HTTPS
Windows Firefox 20+ Works
Windows IE 9 Requires Adobe Flash Player
Windows IE 10 Requires Adobe Flash Player
Windows IE 11 Requires Adobe Flash Player

Demos

Here are some live demos showcasing various features of the library:

Demo Link Description
Basic Demo Demonstrates a basic 320x240 image capture.
Large Demo Demonstrates capturing a large 640x480 image, but showing a live preview at 320x240.
Crop Demo Demonstrates cropping a 240x240 square out of the center of a 320x240 webcam image.
Large Crop Demo Demonstrates a large 480x480 square crop, from a 640x480 image capture, with a 240x240 live preview.
HD Demo Demonstrates a 720p HD (1280x720) image capture (only supported by some webcams).
SFX Demo Demonstrates a camera shutter sound effect at capture time.
Flash Demo Demonstrates forcing Adobe Flash fallback mode.
Freeze Demo Demonstrates freezing / previewing a snapshot before saving it.
Mirror Demo Demonstrates flipping the image horizontally (mirror mode).
Full Combo Demo A full combination demo showcasing all features.

Open Source

WebcamJS is open source, MIT licensed, and available on GitHub:

https://github.com/jhuckaby/webcamjs

QuickStart Guide

Host the webcam.js and webcam.swf files on your web server (both in the same directory), and drop in this HTML snippet:

    <script src="webcam.js"></script> 
 
    <div id="my_camera" style="width:320px; height:240px;"></div>
    <div id="my_result"></div>
 
    <script language="JavaScript">
        Webcam.attach( document.querySelector('#my_camera') );
 
        function take_snapshot() {
            Webcam.snap().then( function(data_uri) {
                document.getElementById('my_result').innerHTML = '<img src="'+data_uri+'"/>';
            } );
        }
    </script> 
 
    <a href="javascript:void(take_snapshot())">Take Snapshot</a>

This will create a live camera view in the my_camera DIV, and when the Take Snapshot link is clicked it will take a still snapshot, convert it to a JPEG, and deliver a Data URI which is inserted into the my_result DIV as a standard <IMG SRC> tag.

Data URIs may be passed around like any URL, and can be submitted to your server as well (see below for example of this).

Configuration

If you want to override the default settings, just call Webcam.set() and pass in a hash with any of the following keys:

Param Name Default Value Notes
width (Auto) Width of the live camera viewer in pixels, defaults to the actual size of the DOM element.
height (Auto) Height of the live camera viewer in pixels, defaults to the actual size of the DOM element.
dest_width (Auto) Maximum width of the captured camera image in pixels, defaults to the live viewer size.
dest_height (Auto) Maximum height of the captured camera image in pixels, defaults to the live viewer size.
image_format jpeg Desired image format of captured image, may be "jpeg" or "png".
jpeg_quality 90 For JPEG images, this is the desired quality, from 0 (worst) to 100 (best).
enable_flash true Enable or disable Flash fallback, if there is no native webcam access.
force_flash false Setting this to true will always run in Adobe Flash fallback mode.
force_file false Force file upload mode
flip_horiz false Setting this to true will flip the image horizontally (mirror mode).
flip_horiz_back undefined When set to false, flip_horiz is enabled for front camera only.
fps 30 Set the desired fps (frames per second) capture rate.
webcam_path "./" Set an alternate location for the fallback SWF and CSS files.
flash_not_detected_text "ERROR: No Adobe Flash Player detected. Webcam.js relies on Flash for browsers that do not support getUserMedia (like yours)." text/html for flash player not detected.
no_interface_found_text "No supported webcam interface found." text/html for camera not detected.
enable_file_fallback true Enable "file upload" fallback for case, when both: HTML5 and Flash doesn't work. This may be helpful on iPhone Safari and MacOS Safari.
unfreeze_snap true Whether to unfreeze the camera after snap (defaults to true)
maximum_blur_index 0 0 to disable, less is better. Recommended value: 0.8. Read more and experiment: https://github.com/CezaryDanielNowak/inspector-bokeh
switch_camera_node null Contents of "Switch Camera" button. React Node required
verbose true Display all error messages. Consider disabling it on production.
force_fresh_photo false When true, it will disallow to Select Photo from Library on iOS < 11

Here is an example of overriding a single parameter. Remember to call this before you attach the viewer.

    Webcam.set('flip_horiz', true);

You can also set multiple parameters at once by passing in an object, like this:

    Webcam.set({
        width: 320,
        height: 240,
        dest_width: 640,
        dest_height: 480,
        image_format: 'jpeg',
        jpeg_quality: 90,
        force_flash: false,
        flip_horiz: true,
        fps: 45
    });
 
    // Attach camera here

Initialization

WebcamJS is initialized and activated by "attaching" a live camera viewer to a DOM element. The DOM element must already be created and empty. Pass in an ID or CSS selector to the Webcam.attach() function. Example:

    webcam.switchCamera( 'front' ).then(function() {
        Webcam.attach( document.querySelector('#my_camera') );
    });
 

This will activate the user's webcam, ask for the appropriate permission, and begin showing a live camera image in the specified DOM element.

Note that the browser itself handles asking the user for permission to use their camera. WebcamJS has no control over this, so there is no way to style the UI. Each browser does it a little differently, typically a bar at the top of the page, and Flash does it inside the view area.

Snapping a Picture

To snap a picture, just call the Webcam.snap() function, passing in a callback function. The image data will be passed to your function as a Data URI, which you can then display in your web page, or submit to a server. Example:

    Webcam.snap().then( function(data_uri) {
        document.getElementById('my_result').innerHTML = '<img src="'+data_uri+'"/>';
    } );

See a live demo of this here

Your function is also passed a HTML5 Canvas and a 2D Context object, so you can gain access to the raw pixels instead of a compressed image Data URI. These are passed as the 2nd and 3rd arguments to your callback function. Example:

    Webcam.snap().then( function(data_uri, canvas, context) {
        // copy image to my own canvas
        myContext.drawImage( canvas, 0, 0 );
    } );

If you would prefer that WebcamJS simply copy the image into your own canvas, it can do that instead of generating a Data URI (which can be an expensive operation). To do this, simply pass your canvas object to the Webcam.snap() method, as the 2nd argument, right after your callback function. Example:

    // assumes 'myCanvas' is a reference to your own canvas object, at the correct size
 
    Webcam.snap().then( function() {
        // the webcam image is now in your own canvas
    }, myCanvas );

Customizing Image Size

WebcamJS will automatically size the live camera viewer based on the DOM element it is attached to. However, you can override this by setting the width and/or height parameters:

    Webcam.set({
        width: 320,
        height: 240
    });
 
    // Attach camera here

The size of the captured JPEG / PNG image is set to match the live camera viewer by default. However, you can override this by setting the dest_width and/or dest_height. Note that you can set the destination image size different than the viewer size. So you can have a small live viewer, but capture a large image. Example:

    Webcam.set({
        width: 320,
        height: 240,
        dest_width: 640,
        dest_height: 480,
    });
 
    // Attach camera here

See a live demo of this feature here

Cropping The Image

WebcamJS can also crop the final image for you, to any dimensions you like. This is useful for when you want a square image (perhaps for a website profile pic), but you want to capture the image from the user's webcam at 4:3 ratio to be fully compatible (some cameras require 4:3 and cannot capture square images). To do this, include crop_width and crop_height params, specifying the area to crop out of the center of the final image:

    Webcam.set({
        width: 320,
        height: 240,
        crop_width: 240,
        crop_height: 240
    });
 
    // Attach camera here

This would crop a 240x240 square out of the center of the 320x240 webcam image. The crop is also reflected in the live preview area. In this case the live preview would also be cropped to 240x240, so the user can see exactly what portion of the image will be captured.

See a live demo of this feature here

Flipping The Image (Mirror Mode)

If you want, WebcamJS can "flip" (mirror) both the live preview and captured image horizontally. This will produce a reversed image, as if you were looking in a mirror. To enable this optional feature, include the flip_horiz param, and set it to true. Example:

    Webcam.set({
        width: 320,
        height: 240,
        flip_horiz: true
    });
 
    // Attach camera here

See a live demo of this feature here

Freezing / Previewing The Image

Want to provide your users with the ability to "freeze" (i.e. preview) the image before actually saving a snapshot? Just call Webcam.freeze() to freeze the current camera image. Then call Webcam.snap() to save the frozen image, or call Webcam.unfreeze() to cancel and resume the live camera feed.

The idea here is to provide a photo-booth-like experience, where the user can take a snapshot, then choose to keep or discard it, before actually calling Webcam.snap() to save the image.

See a live demo of this feature here

Setting an Alternate SWF Location

By default WebcamJS looks for the SWF file in the same directory as the JS file. If you are hosting the SWF in a different location, please set it using the Webcam.setSWFLocation() function. It should be on the same domain as your page. Example:

    Webcam.set("swfURL", "/path/to/the/webcam.swf");

Note that this is only used if the user's browser doesn't support HTML5 getUserMedia, and WebcamJS has to fallback to using an Adobe Flash movie to capture the camera.

Reset (Shutdown)

To shut down the live camera preview and reset the system, call Webcam.reset(). This removes any DOM elements we added, including a Flash movie if applicable, and resets everything in the library to the initial state. Example:

    Webcam.reset();

To use the library again after resetting, you must call Webcam.attach() and pass it your DOM element.

API Reference

Here is a list of all the API function calls available in the WebcamJS library.

Method Name Notes
Webcam.set() Set configuration parameters. Pass a key + value, or a hash with multiple keys/values.
Webcam.on() Register an event listener for a given event. Pass in the event name, and a callback function.
Webcam.off() Remove an event listener for a given event. Pass in the event name, and the callback function to remove. Omit the callback reference to remove all listeners.
Webcam.attach() Initialize library and attach live camera to specified DOM object.
Webcam.reset() Shut down library and reset everything. Must call attach() to use it again. Does not remove event listeners.
Webcam.freeze() Freeze the current live camera frame, allowing the user to preview before saving.
Webcam.unfreeze() Cancel the preview (discard image) and resume the live camera view.
Webcam.snap() Take a snapshot from the camera (or frozen preview image). Resolved promise receives data.
Webcam.detectFlash() return true if browser supports flash, false otherwise.

Custom Events

WebcamJS fires a number of events you can intercept using a simple JavaScript hook system. Events are fired when: the library is fully loaded, when the camera is live (after user allows access), when an error occurs, and during upload. To register an event listener, call the Webcam.on() function, passing an event name and callback function. Here is a table of the available event types:

Event Name Notes
load Fires when the library finishes loading.
live Fires when the user's camera goes live (i.e. showing a live preview). This will only happen after the user allows access to their camera.
error Fires when an error occurs (your callback function is passed an error string).
imageSelected Fires once user selects file in file upload fallback.

Example:

    Webcam.on( 'load', function() {
        // library is loaded
    } );
 
    Webcam.on( 'live', function() {
        // camera is live, showing preview image
        // (and user has allowed access)
    } );
 
    Webcam.on( 'error', function(err) {
        // an error occurred (see 'err')
    } );

By default the error event shows a JavaScript alert dialog, but if you register your own event handler this action is suppressed, and your function is called instead.

Please note that WebcamJS allows multiple listeners on the same event. So if you call Webcam.on() multiple times, your callback functions are all added to an array for the event, and all of them will be called when the event fires. So only call Webcam.on() once for each listener function. You can use Webcam.off() to remove listeners from an event.

Submitting Images to a Server

The Webcam.snap() function delivers your image by way of a client-side JavaScript Data URI. The binary image data is encoded with Base64 and stuffed into the URI. You can use this image in JavaScript and display it on your page. However, the library also provides a way to decode and submit this image data to a server API endpoint, via binary AJAX. Example:

    Webcam.snap().then( function(dataURI) {
        // snap complete, image data is in 'data_uri'
 
        const { data, extension } = dataURItoImage(dataURI);
 
        postMultipart('backend/photo/')
          .attach('photo', data, `photo.${extension}`)
          .end(console.info);
    } );

Custom User Media Constraints (Advanced)

The HTML5 getUserMedia API has a constraints system by which you can specify optional or mandatory requirements for the video stream. These include things such a minimum or maximum resolution and/or framerate. By default, WebcamJS will specify a mandatory minimum width and height, matching your dest_width and dest_height parameters. However, if you want to customize this, you can set a constraints parameter using Webcam.set(), and pass in an object containing all the custom constraints you want. Example:

    Webcam.set( 'constraints', {
        mandatory: {
            minWidth: 1280,
            minHeight: 720,
            minFrameRate: 30
        },
        optional: [
            { minFrameRate: 60 }
        ]
    } );

To remove the mandatory constraints and instead just specify the resolution you would prefer, you can set simple width and height properties like this:

    Webcam.set( 'constraints', {
        width: 1280,
        height: 720
    } );

Please call this this before calling Webcam.attach().

Note that some browsers may not support every possible constraint, so consult your browser's documentation and test in all your supported browsers before using this advanced feature. For example, as of this writing Chrome 44 doesn't support framerate constraints.

For more information see the Media Capture Spec and the WebRTC Constraints Spec.

Special cases and notes

  • iOS does not have getUserMedia until iOS 11. File fallback recommended.
  • iOS 11 (beta) produces lower quality in DETECTION_MODE_LABELS. We don't have much control over video stream resolution. See more: https://github.com/kimizuka/webcamera-preview-for-ios11
  • iOS 11 requires playsinline to be set in video tag. Otherwise video is black.
  • video in iOS 11 is rotated by 180 when using back camera. It does not happen in horizontal mode and for front camera.
  • Safari@desktop don't have getUserMedia until Safari 11. Flash fallback is recommended.
  • some browsers have getUserMedia, but does not have MediaRecorder.
  • device rotation while recording might change. In some cases it's better to reinitalise recorder.
  • iOS produces rotated photos. WebcamJS is resolving this problem out-of-the-box.
  • mediaDevices.enumerateDevices works different before and after granting camera access.
  • detecting best possible camera resolution: https://stackoverflow.com/a/27444179/2590921 does not work well with facingMode: 'user' / 'environment'.
  • Camera resolution is very low when another Chrome tab already uses camera. Camera might not be available when another application uses it.
  • Google Pixel and Samsung devices introduced problem with NotReadableError. It was fixed by: a) force webrtc detection mode b) camera is accessed just once a time. Reseting camera or enumerateDevices can't be called when previous call was not finished.

RESOURCES

https://jsfiddle.net/39puneug/4/ https://developer.mozilla.org/en-US/docs/Web/API/ImageCapture

License

The MIT License (MIT)

Copyright (c) 2012 - 2015 Joseph Huckaby

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Package Sidebar

Install

npm i mighty-webcamjs

Weekly Downloads

794

Version

3.1.1

License

MIT

Unpacked Size

352 kB

Total Files

63

Last publish

Collaborators

  • cezarydanielnowak
  • piotrjaworski