Detecting barcodes from the webcam

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
Search for a command to run...

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
I like that you included browser support. Too many times that gets skipped in posts about newer features (:
unfortunately it does, I try to include it in all relevant posts. As you say it's an important aspect in our jobs as developers.
Most of you know me for my consistency, a golden arrow in my blog series. I've written 1000 articles in 1008 days! Almost an article a day, and my honeymoon was the only holiday I ever took. I'm super proud of this achievement; it has been a fantasti...

It's not the first time I'll be talking about community. I think it's an essential aspect of any successful tool. This shows in my previous explorations of Astro, Medusa, and now Vendure as well. All these products thrive in a super open, welcoming, ...

The cool part about Vendure is how easy it is to set up and how abstract each layer is. Basically, we get the following elements: External database Server Worker Admin UI Frontend While this is amazing, it also brings a bit of complexity when it co...

The previous article looked at customizing Vendure on a data and process level. In this article, we'll look at customizing emails, as they are often a big part of a webshop system. We'll be looking at two different layers of customization for customi...

Even though Vendure is a pretty significant project out of the box, in some cases, we might want to go in and modify some elements to work to our specific use case. In this article, I'll take a high-level look at some elements we can customize within...

Yesterday we had a look at the barcode detector API using an image as our source. Today I'd like to explore how this works when we use a webcam as the input source.
This will work a little bit differently from what we've done with the image since we need to loop the function that detects the barcodes.
The end result will be this application that can scan unique barcodes and outputs them as a list.

First of all, let's start without HTML structure which has nothing fancy going on, we just want a placeholder for our list items.
<ul id="barcode-list"></ul>
Next up, we want to change the unload function to call an async function.
window.onload = () => {
detect();
};
async function detect() {
// Function code
}
We want it like this since we want to wait for the video to be accepting and working.
Let's start by defining some variables inside our detect function.
const barcodeDetector = new BarcodeDetector();
const list = document.getElementById('barcode-list');
let itemsFound = [];
const mediaStream = await navigator.mediaDevices.getUserMedia({
video: {facingMode: 'environment'}
});
We create out barcodeDetector as we did with the image. Then we define what element our list is, and we make a variable array that can hold our codes that have been found. Then we create a new media device targeting the webcam.
The next step is to output this webcam onto the screen, so the user has some visual feedback.
const video = document.createElement('video');
video.srcObject = mediaStream;
video.autoplay = true;
list.before(video);
Here we create a new element of the type of video and set the source to be the media stream we just created. We then add it before our list.
This should now give us the webcam output on our screen.

Then we need to have a function that can check for out barcodes. However, this function needs to keep running.
So inside the detect function, we can have another function like this:
async function detect() {
function render() {
// Do the detection
}
(function renderLoop() {
requestAnimationFrame(renderLoop);
render();
})();
}
This will make sure the render function is called at a certain rate, and call it initially.
The render function itself is much like what we've done before:
function render() {
barcodeDetector
.detect(video)
.then(barcodes => {
barcodes.forEach(barcode => {
if (!itemsFound.includes(barcode.rawValue)) {
itemsFound.push(barcode.rawValue);
const li = document.createElement('li');
li.innerHTML = barcode.rawValue;
list.appendChild(li);
}
});
})
.catch(console.error);
}
For each barcode we find, we add a new list item.
You can try this code out on the following Codepen.
As mentioned the API is still in progress being rolled out, as of Chrome 83 and Edge 82 we can use it. However, Firefox does not yet support it.

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter