Skip to content

Instantly share code, notes, and snippets.

@dvergeylen
Last active April 3, 2024 16:27
Show Gist options
  • Save dvergeylen/a256deb3182b8a863238fcc0704aecb9 to your computer and use it in GitHub Desktop.
Save dvergeylen/a256deb3182b8a863238fcc0704aecb9 to your computer and use it in GitHub Desktop.
JSQrcode library tutorial

Introduction

This tutorial is a step by step guide on how to use the javascript QR Code scanner on a webcam video stream in browser. Some people reported experiencing problems including it in their own projets so I guess a tutorial might help others.

Step 1: Include library in <head> section

<html lang="en">
  <head>
    <script type="text/javascript" src="grid.js"></script>
    <script type="text/javascript" src="version.js"></script>
    <script type="text/javascript" src="detector.js"></script>
    <script type="text/javascript" src="formatinf.js"></script>
    <script type="text/javascript" src="errorlevel.js"></script>
    <script type="text/javascript" src="bitmat.js"></script>
    <script type="text/javascript" src="datablock.js"></script>
    <script type="text/javascript" src="bmparser.js"></script>
    <script type="text/javascript" src="datamask.js"></script>
    <script type="text/javascript" src="rsdecoder.js"></script>
    <script type="text/javascript" src="gf256poly.js"></script>
    <script type="text/javascript" src="gf256.js"></script>
    <script type="text/javascript" src="decoder.js"></script>
    <script type="text/javascript" src="qrcode.js"></script>
    <script type="text/javascript" src="findpat.js"></script>
    <script type="text/javascript" src="alignpat.js"></script>
    <script type="text/javascript" src="databr.js"></script>
  </head>

  <body>
    [...]
  </body>
</html>

Step 2: Create video and canvas markups

JSQrcode doesn't capture QRCodes from video stream directly, but from a canvas. Once there is sufficient data available from the video stream, one copies the data into the canvas and applies JSQRcode decoding method on it.

<div class="video-container">
  <video id="video-preview"></video>
  <canvas id="qr-canvas" class="hidden" ></canvas>
</div>

Notice the canvas must have id=qr-canvas (harcoded in library).

Step 3: Custom javascript to copy video into canvas

Create a new javascript file that you insert after the ones inserted at Step 1. On page load, start the video stream.

window.onload = async function() {
  try {
    /* Ask for "environnement" (rear) camera if available (mobile),
     * will fallback to only available otherwise (desktop).
     * User will be prompted if (s)he allows camera to be started */
    const stream = await navigator.mediaDevices.getUserMedia({
      video: {
        facingMode: "environment",
      },
      audio: false,
    });
    const video = document.getElementById("video-preview");
    video.srcObject = stream;
    video.setAttribute("playsinline", true); /* otherwise iOS safari starts fullscreen */
    video.play();
    setTimeout(tick, 100); /* We launch the tick function 100ms later (see next step) */
  } catch(err) {
    console.log(err); /* User probably refused to grant access*/
  });
};

Step 4: Copy Video image to canvas and start decoding

function tick() {
  const video = document.getElementById('video-preview');
  const qrCanvasElement = document.getElementById('qr-canvas');
  const qrCanvas = qrCanvasElement.getContext('2d');
  let width;
  let height;

  if (video.readyState === video.HAVE_ENOUGH_DATA) {
    qrCanvasElement.height = video.videoHeight;
    qrCanvasElement.width = video.videoWidth;
    qrCanvas.drawImage(video, 0, 0, qrCanvasElement.width, qrCanvasElement.height);

    try {
      const result = qrcode.decode();
      console.log(result)
      /* Video can now be stopped */
      video.pause();
      video.src = '';
      video.srcObject.getVideoTracks().forEach(track => track.stop());

      /* Display Canvas and hide video stream */
      qrCanvasElement.classList.remove('hidden');
      video.classList.add('hidden');
    } catch(e) {
      /* No Op */
    }
  }

  /* If no QR could be decoded from image copied in canvas */
  if (!video.classList.contains('hidden'))
    setTimeout(tick, 100);
}
@selrahcDC
Copy link

Thank you so much for this tutorials

@ukhaiyr
Copy link

ukhaiyr commented Feb 11, 2020

Thank you for this tutorial.

Take note, the result of the qrcode decoded will be shown in the console.

@Wirah
Copy link

Wirah commented May 27, 2020

I slip the alert message after the line navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" }, audio: false }).then(function(stream) {, because nothing happen in my all android browser.
And alert not showing.
I see message in desktop browser's console log:
MediaStreamError
constraint: ""
message: "The object can not be found here."
name: "NotFoundError"
stack: ""
: MediaStreamErrorPrototype { name: Getter, message: Getter, constraint: Getter, … }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment