question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ImageCapture API support

See original GitHub issue

I extended the code (Version 1.0) to support the (currently experimental) MediaStream Image Capture. It creates an ImageCapture from the active VideoStreamTrack and uses ImageCapture#grabFrame() to grab a frame from the stream. By using this API the PhoneSettings can be specified which means that e.g. flash light or focus can be configured. Note that this feature is currently only supported by Chrome for Android when the flag “chrome://flags/#enable-experimental-web-platform-features” is set to “true”.

Example configuration (note inputStream.photoSettings and flag inputStream.imageCapture to enable use of the API):

{
    numOfWorkers: 4,
    locate: true,
    inputStream: {
        name: "Live",
        type: "LiveStream",
        constraints: {
            width: {min: 640},
            height: {min: 480},
            facingMode: "environment",
            aspectRatio: {min: 1, max: 2}
        },
        photoSettings: {
            fillLightMode: "torch", /* or "flash" */
            focusMode: "continuous"
        },
        imageCapture: true
    },
    frequency: 10,
    decoder: {
        readers: [{
               format: "ean_reader",
               config: {}
           }]
    },
    locator: {
        patchSize: "medium",
        halfSample: true
    }
}

Modifications:

--- a/src/input/camera_access.js
+++ b/src/input/camera_access.js
@@ -127,6 +127,14 @@
         streamRef = null;
     },
     enumerateVideoDevices,
+    getActiveStreamTrack: function () {
+        if (streamRef) {
+            const tracks = streamRef.getVideoTracks();
+            if (tracks && tracks.length) {
+                return tracks[0];
+            }
+        }
+    },
     getActiveStreamLabel: function() {
         if (streamRef) {
             const tracks = streamRef.getVideoTracks();

--- a/src/input/frame_grabber.js
+++ b/src/input/frame_grabber.js
@@ -69,12 +69,13 @@
      * The image-data is converted to gray-scale and then half-sampled if configured.
      */
     _that.grab = function() {
+        return new Promise(function (resolve, reject) {
+            inputStream.getFrame()
+                    .then(function (frame) {
         var doHalfSample = _streamConfig.halfSample,
-            frame = inputStream.getFrame(),
             drawable = frame,
             drawAngle = 0,
             ctxData;
-        if (drawable) {
             adjustCanvasSize(_canvas, _canvasSize);
             if (_streamConfig.type === 'ImageStream') {
                 drawable = frame.img;
@@ -106,10 +107,12 @@
             } else {
                 computeGray(ctxData, _data, _streamConfig);
             }
-            return true;
-        } else {
-            return false;
-        }
+
+                        resolve();
+                    }).catch(function (err) {
+                        console.error('Error occured while getting frame: ' + err);
+                    });
+        })
     };
 
     _that.getSize = function() {

--- a/src/input/input_stream.js
+++ b/src/input/input_stream.js
@@ -134,7 +134,9 @@
     };
 
     that.getFrame = function() {
-        return video;
+        return new Promise(function (resolve) {
+                resolve(video);
+            });
     };
 
     return that;
@@ -142,8 +144,27 @@
 
 InputStream.createLiveStream = function(video) {
     video.setAttribute("autoplay", true);
-    var that = InputStream.createVideoStream(video);
+    var that = InputStream.createVideoStream(video),
+            _imageCapture = null;
 
+    that.setImageCapture = function (imageCapture) {
+        _imageCapture = imageCapture;
+    };
+
+    that.getFrame = function () {
+        if (_imageCapture !== null) {
+            console.log('Getting frame from ImageCapture...');
+
+            return _imageCapture.grabFrame();
+        } else {
+            console.warn('ImageCapture not set, using video as fallback!');
+
+            return new Promise(function (resolve, reject) {
+                    resolve(video);
+                });
+        }
+    };
+
     that.ended = function() {
         return false;
     };
@@ -305,13 +326,9 @@
     };
 
     that.getFrame = function() {
-        var frame;
-
-        if (!loaded){
-            return null;
-        }
-        if (!paused) {
-            frame = imgArray[frameIdx];
+        return new Promise(function (resolve, reject) {
+                if (loaded && !paused) {
+                    var frame = imgArray[frameIdx];
             if (frameIdx < (size - 1)) {
                 frameIdx++;
             } else {
@@ -320,8 +337,11 @@
                     publishEvent("ended", []);
                 }, 0);
             }
+                    resolve(frame);
+                } else {
+                    reject();
         }
-        return frame;
+            });
     };
 
     return that;

--- a/src/quagga.js
+++ b/src/quagga.js
@@ -60,6 +60,20 @@
         _inputStream = InputStream.createLiveStream(video);
         CameraAccess.request(video, _config.inputStream.constraints)
         .then(() => {
+            if (_config.inputStream.imageCapture === true) {
+                var activeStreamTrack = CameraAccess.getActiveStreamTrack();
+                if (activeStreamTrack) {
+                    var imageCapture = new ImageCapture(activeStreamTrack);
+                    if (imageCapture) {
+                        var photoSettings = _config.inputStream.photoSettings;
+
+                        // set the image capture options (e.g. flash light, autofocus, ...)
+                        imageCapture.setOptions(photoSettings)
+                                .then(function () {_inputStream.setImageCapture(imageCapture)})
+                                .catch(function (err) {console.error('setOptions(' + JSON.stringify(photoSettings) + ') failed: ', err)});                         
+                    }  
+                }
+            }
             _inputStream.trigger("canrecord");
         }).catch((err) => {
             return cb(err);
@@ -281,7 +295,7 @@
         } else {
             _framegrabber.attachData(_inputImageWrapper.data);
         }
-        if (_framegrabber.grab()) {
+        _framegrabber.grab().then(function () {
             if (availableWorker) {
                 availableWorker.busy = true;
                 availableWorker.worker.postMessage({
@@ -291,7 +305,7 @@
             } else {
                 locateAndDecode();
             }
-        }
+        });
     } else {
         locateAndDecode();
     }

Issue Analytics

  • State:open
  • Created 7 years ago
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
ericbladecommented, Jun 8, 2018

Torch/Focus/etc can be specified now, does that leave this with any valid changes still to be made?

1reaction
seanpoultercommented, Oct 11, 2017

Light/torch support has been released with v.12.0.

Read more comments on GitHub >

github_iconTop Results From Across the Web

ImageCapture API | Can I use... Support tables for HTML5 ...
The Image Capture API provides access to the Video Camera for taking photos while configuring picture-specific settings such as e.g. zoom or auto...
Read more >
ImageCapture - Web APIs | MDN
The ImageCapture interface of the MediaStream Image Capture API provides methods to enable the capture of images or photos from a camera or ......
Read more >
Alternative for the ImageCapture API for better browser support
First check if your browser supports the MediaStream Image Capture API by checking if the constructor exists in the window object.
Read more >
ImageCapture - Web APIs
Chrome Edge ImageCapture. Experimental Chrome Full support 59 Edge Full support... ImageCapture() constructor. ⚠️. Experimental Chrome Full support 59 Edge Full support... getPhotoCapabilities. ⚠️. Experimental Chrome...
Read more >
Interactive Guide To Image Capture API - RapidAPI
If your browser supports the API, a video stream will start. You can also stop the stream and take a picture using the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found