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:
[{"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 ...