How to use webcam

Hello everyone, i don't know if this question goes here, but i hope to find some guidance in this forum.

I'm trying to stream the captured webcam image on the browser and i've got this code from some post and i've got it working on this jsfiddle:

https://jsfiddle.net/4jg36Lr2/

and when i try to do the same on node-red, ussing the template node it does not work

code on NR: https://pastebin.com/Z8136yNX

what am i doing wrong?

Hi Andres, your code works for my Node-Red, did you give permissions to your browser, to your Node-Red address permissions to use the camera?

I have tried things like that on node-red, and after many attempts I managed to get up to a video player on canvas, even make a recording and download it

It never ask for permission, and on console throws this:

prueba2:35 Uncaught (in promise) TypeError: Cannot set property 'innerHTML' of null
at init (prueba2:35)
at prueba2:46

referencing to this line: errorMsgElement.innerHTML = 'navigator.getUserMedia error:${e.toString()}';

and highlight this: = 'navigator.getUserMedia error:${e.toString()}';

What browser are you using?
In chrome it works perfectly. In firefox you have to look at compatibility issues. I think the code is specified for chrome.
I hope this website helps you, mozilla gave me a lot of problems when using the webcam
I hope these links help you a little

https://www.html5rocks.com/en/tutorials/video/basics/

https://www.youtube.com/watch?v=n9gFQ0QKYB8

I'm using chrome, and actually in firefox works for me. Does the non https has something to do with this?

The code is correctly done, the problem is probably some configuration of your browser. I had this problem with firefox, granted permission to use the camera and it works correctly. If your chrome doesn't have camera permits, be sure to give them to them

Hi Andres,

Here it works for me also when I use a Template node for my dashboard (in Chrome) ...

It asks me nicely whether it is allowed to use my microphone and webcam:

image

Are you sure you have used the correct Template node, i.e. the one for the dashboard:

[{"id":"1ee47625.5a7ffa","type":"ui_template","z":"60ad596.8120ba8","group":"2e442781.0c5608","name":"","order":5,"width":0,"height":0,"format":"<!-- Stream video via webcam -->\n<div class=\"video-wrap\">\n    <video id=\"video\" playsinline autoplay></video>\n</div>\n\n<!-- Trigger canvas web API -->\n<div class=\"controller\">\n    <button id=\"snap\">Capture</button>\n</div>\n\n<!-- Webcam video snapshot -->\n<canvas id=\"canvas\" width=\"640\" height=\"480\"></canvas>\n\n<script>\n    'use strict';\n    \n\tconst video = document.getElementById('video');\n    const canvas = document.getElementById('canvas');\n    const snap = document.getElementById(\"snap\");\n    const errorMsgElement = document.querySelector('span#errorMsg');\n\n    const constraints = {\n      audio: true,\n      video: {\n        width: 1280, height: 720\n      }\n    };\n\n    // Access webcam\n    async function init() {\n      try {\n        const stream = await navigator.mediaDevices.getUserMedia(constraints);\n        handleSuccess(stream);\n      } catch (e) {\n        errorMsgElement.innerHTML = 'navigator.getUserMedia error:${e.toString()}';\n      }\n    }\n\n    // Success\n    function handleSuccess(stream) {\n      window.stream = stream;\n      video.srcObject = stream;\n    }\n\n    // Load init\n    init();\n\n    // Draw image\n    var context = canvas.getContext('2d');\n    snap.addEventListener(\"click\", function() {\n            context.drawImage(video, 0, 0, 640, 480);\n    });\n</script>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":360,"y":340,"wires":[[]]},{"id":"2e442781.0c5608","type":"ui_group","z":"","name":"Hikvision","tab":"4779176.99cd2e8","disp":true,"width":"6","collapse":false},{"id":"4779176.99cd2e8","type":"ui_tab","z":"","name":"Camera","icon":"dashboard","disabled":false,"hidden":false}]

Question of of curiosity. I see great potential in capturing the dashboard's webcam and microphone signal and send both audio and video data to your Node-RED flow. But your example captures the webcam and microphone, but plays both again on the same machine (i.e. the pc where the dashboard is being displayed). Is there an existing use case for that, or is it just an experiment to get started?

sorry for the delay in the answer. about the permissions, chrome is not asking for them, but if i use the same code in another page, like jsfiddle, works fine. i'm thinking about the non https.

@BartButenaers the potential that i need is to read barcodes with any webcam, so if there is a way to do that, it would be great.

Andrés

Hi,

any tips on how to send the image data as an output when the "capture" button is pressed?

i also would like to capture an image of a barcode and feed it into a barcode decoder....

Hi @akd02,
If I were you, I would take a look at the node-red-node-ui-webcam node.
Bart

Thanks for the tip...

it would still be great to know how to send the picture data via usual template node, any tip on that would be highly appreciated!!!

I have adapted the ui-template node, so it now sends a base64 encoded image on the output (when you trigger the 'capture' button in the dashboard).

For the following example flow, you need also to install the node-red-contrib-image-output node to display the output image:

image

[{"id":"412a143b17eea6c4","type":"ui_template","z":"f3e346780eaa6c3c","group":"2e442781.0c5608","name":"","order":5,"width":0,"height":0,"format":"<!-- Stream video via webcam -->\n<div class=\"video-wrap\">\n    <video id=\"video\" playsinline autoplay></video>\n</div>\n\n<!-- Trigger canvas web API -->\n<div class=\"controller\">\n    <button id=\"snap\">Capture</button>\n</div>\n\n<!-- Webcam video snapshot -->\n<canvas id=\"canvas\" width=\"640\" height=\"480\"></canvas>\n\n<script>\n(function(scope) {\n    'use strict';\n    \n\tconst video = document.getElementById('video');\n    const canvas = document.getElementById('canvas');\n    const snap = document.getElementById(\"snap\");\n    const errorMsgElement = document.querySelector('span#errorMsg');\n\n    const constraints = {\n      audio: true,\n      video: {\n        width: 1280, height: 720\n      }\n    };\n\n    // Access webcam\n    async function init() {\n      try {\n        const stream = await navigator.mediaDevices.getUserMedia(constraints);\n        handleSuccess(stream);\n      } catch (e) {\n        errorMsgElement.innerHTML = 'navigator.getUserMedia error:${e.toString()}';\n      }\n    }\n\n    // Success\n    function handleSuccess(stream) {\n      window.stream = stream;\n      video.srcObject = stream;\n    }\n\n    // Load init\n    init();\n\n    // Draw image\n    var context = canvas.getContext('2d');\n    snap.addEventListener(\"click\", function() {\n        context.drawImage(video, 0, 0, 640, 480);\n        \n        var imageData = context.getImageData(0, 0, 640, 480);\n        var dataUrl = canvas.toDataURL('image/jpeg');\n        var base64EncodedImage = dataUrl.replace(/^data:image\\/(png|jpg);base64,/, '');\n        debugger;\n        scope.send({\n            payload: base64EncodedImage,\n            topic: \"snapshot\"\n        })\n    });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","className":"","x":1400,"y":280,"wires":[["0dc20ae6a177b69d"]]},{"id":"0dc20ae6a177b69d","type":"image","z":"f3e346780eaa6c3c","name":"","width":"240","data":"payload","dataType":"msg","thumbnail":false,"active":true,"pass":false,"outputs":0,"x":1610,"y":280,"wires":[]},{"id":"2e442781.0c5608","type":"ui_group","name":"Heatmap","tab":"4779176.99cd2e8","order":1,"disp":true,"width":"6","collapse":true},{"id":"4779176.99cd2e8","type":"ui_tab","name":"Home","icon":"dashboard","order":28,"disabled":false,"hidden":false}]

Although it is still very unclear to me what you want to achieve with this. The node-red-contrib-ui-webcam node is ready to use, while this template node is only a quick experiment that is far from usable. So I assume you have enough programming skills to get it running ...

@BartButenaers you are a star!!!!!!!!

1 Like

Found the solution for using the "back camera" from a mobile device..
'''
const constraints = {
audio: false,
video: { facingMode: { exact: "environment" } }
};
'''
thanks @BartButenaers :slight_smile:

1 Like

Thanks for sharing your solution!!!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.