How to Scan QR Codes in Web Browsers With Web Workers and jsQR

Join 5,000 subscribers and get a periodic digest of news, articles, and more.
By submitting your email, you agree to the Terms of Use and Privacy Policy.
James Walker is a CloudSavvy IT contributor. He is the founder of Heron Web, a UK-based digital agency providing bespoke software development services to SMEs. He has experience managing complete end-to-end web development workflows with DevOps, CI/CD, Docker, and Kubernetes. Read more…
QR codes have become much more popular in recent years. They’re widely used to deliver information and facilitate check-ins. While most commonly found as part of native mobile apps, you can also incorporate QR scans into your websites.
Here’s how to use the popular jsQR library in combination with Web Workers to offer a high-performance QR scanning experience on the web. We’ll assume you’re already familiar with JavaScript basics and you’ve got a functioning site which you’re ready to add your code to.
Begin by downloading the jsQR library in pre-compiled distributable format. Make sure it’s publicly accessible on your web server; in this article, we’re assuming the URL is /jsQR.js. jsQR is also available as an npm package if you’ve got a build routine configured.
This package provides real-time detection of QR codes visible in a video stream. It retrieves the data within the code and supplies it to your application.
The next step is to acquire a MediaStream from the browser. Use the mediaDevices API to get a new stream from the user’s camera:
We’re selecting the first camera which is found. You could add extra logic to enable selection of a specific camera indicated by the user. In a real app, you should also improve the error handling when the mediaDevices API is unavailable. This could be because the user is in an old web browser or they’ve permanently blocked the camera access permission.
Use the getCamera() function to acquire the video stream. Attach the stream to a <video> element so it can be played and displayed to the user:
The next step is to create a canvas element. The video data will be streamed from the camera onto the canvas where the image pixels will be extracted and fed to jsQR. The canvas needs to be sized to match the dimensions of the video stream.
The canvas context will be used in the next step to draw each frame of the video stream onto the canvas.
Add jsQR to your code next. Running jsQR in a web worker lets the browser delegate it to a background process, improving performance. jsQR needs to scan every video frame so running it in your main JavaScript thread can incur severe slowdowns on low-end devices.
The main thread and your web worker can communicate using messages. Your main thread will message the jsQR worker each time a new video frame is available. The worker will inspect that frame for QR codes in its background thread, then send a message to the main thread when the frame has been processed.
Load your worker in your main JavaScript code and add a message listener:
Next add qr-worker.js to your project. This needs to be publicly accessible at the URL given to the Worker constructor. Browsers will download the web worker at the time it’s needed.
The importScripts() function downloads the jsQR library. This call is equivalent to a <script> tag in your HTML but makes the script’s contents available to your web worker.
A message listener is added to receive events from your JavaScript’s main thread. Each event needs to include the data, width, and height of a video frame streamed from the camera. These values are fed to jsQR which will attempt to detect a QR code within the frame. The result is posted back to the main thread.
The final step is to create an update loop that feeds video frames to the jsQR worker periodically.
The tick() function requests the browser allocate time to calling updateJsQr() before the next repaint. This function gets the current video frame, draws it to the canvas, and then pulls out the resulting image data ready to pass to jsQR. The postMessage() method on the worker instance actually sends the data.
The worker will then act on the data as shown in the code above. The detection result is communicated back to the main thread which processes it as shown in Step 4. When a QR code is detected, your application should use the retrieved data to move forward in its flow. When there’s no detected code, tick() is called again to pass the next frame to the QR worker, ready for assessment.
This mechanism ensures you don’t end up overloading the browser by running multiple frame detections concurrently. Each call to jsQR() is potentially expensive so you want to wait until the result is known before scheduling another. The loop is only sustained until a successful result is obtained, with jsQR handling one frame at a time. Your site’s UI and its real-time camera preview will remain responsive throughout as the worker runs independently in the background.
Each successful call to jsQR() returns a result object with the following properties:
No data is available when jsQR fails to detect a code in the provided image.
Combining jsQR with Web Workers lets you implement high performance QR code scans in your web application. QR codes are an easy and convenient data sharing mechanism which most mobile users are now familiar with.
Although you could use jsQR as part of your main loop, you’d need to implement aggressive throttling to keep your UI responsive. This would result in a longer delay before a successful detection. Web Workers are supported in all modern browsers and provide a substantial performance boost to this solution, enabling split-second scans under optimal lighting conditions.
The above article may contain affiliate links, which help support CloudSavvy IT.
Facebook
Twitter
LinkedIn
RSS Feed
Cloud wisdom in your inbox
By submitting your email, you agree to the Terms of Use and Privacy Policy.

source

Digital Strategist Chris Hood

Leave a Reply

Your email address will not be published. Required fields are marked *

© 2021 SHAQ HAX - Proudly powered by theme Octo