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.
<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>
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).
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*/
});
};
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);
}
Hi,
This might help you. I don't have access to Safari browser for the moment, I can't help for test unfortunately.