Search code examples
javascriptreactjscamerabarcode-scannerquaggajs

Using a browser stream on phones with more than one Camera


I currently have a React App that is using QuaggaJS to create a barcode scanner component. The scanner works fine with phone cameras that only possess one camera. When dealing with newer phones that possess multiple cameras the scanner does not work because there is no way of focusing the camera so it continuously changes between all cameras.

import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import Quagga from "@ericblade/quagga2";
import adapter from "webrtc-adapter";
import "./BarcodeScanner.css";

const BarcodeScanner = (props) => {
  const navigate = useNavigate();

  useEffect(() => {
    startQuagga();
  }, []);

  if (
    !navigator.mediaDevices &&
    !(typeof navigator.mediaDevices.getUserMedia === "function")
  ) {
    console.log("getUserMedia function is not available in this browser.");
    props.onError("getUserMedia function is not available in this browser");
    return;
  }

  function startQuagga() {
    try{
      Quagga.init(
        {
          inputStream: {
            name: "Live",
            type: "LiveStream",
            target: document.querySelector("#interactive"),
            constraints: {
              width: 640,
              height: 480,
              facingMode: "environment",
              
            },
            
          },
          locate: true,
          decoder: {
            readers: ["upc_reader", "code_128_reader"],
            
          },
        },
        function (err) {
          if (err != null) {
            console.log(err);
            props.onError(err);
            stopScanner();
            return;
          }
          console.log("Initialization finished. Ready to start");
          Quagga.start();
        }
      );
    }catch {
      props.onError("Failed to open camera");
    }
    
  }

  Quagga.onDetected((data) =>  {
    let countDecodedCodes = 0;
    let err = 0;
    for (let id in data.codeResult.decodedCodes) {
      let error = data.codeResult.decodedCodes[id];
      if (error.error != undefined) {
        countDecodedCodes++;
        err += parseFloat(error.error);
      }
    }
    if (err / countDecodedCodes < 0.9) {
      props.onDetected(data.codeResult.code);
      Quagga.stop();
    } 
  });

  const stopScanner = () => {
    console.log("stopping Quagga")
    Quagga.stop();
  };


  useEffect(() => {
    if (props.showBottomSheet === "false") {
      stopScanner();
    } 
  }, [props.showBottomSheet]);

  return <div className="barcode-scanner viewport" id="interactive"></div>;
};

export default BarcodeScanner;```

Solution

  • I found that by changing the resolution to 1281 (Changing the height in the constraints) Quagga will automatically choose the high resolution camera. Adding this with a box overlay to guide the user seems to have fixed the issue.