nimiq / qr-scanner

Lightweight Javascript QR Code Scanner
https://nimiq.github.io/qr-scanner/demo
MIT License
2.44k stars 529 forks source link

Doesn't scan any QR code on chrome 107.0.5304.87 mac os 13.0 (22A380) (M1 processor) #209

Closed clawfire closed 1 year ago

clawfire commented 1 year ago

Neither my implementation nor your demo code scan anything. From built in camera or another webcam connected. I tried initialy with a EU DCC (covid pass) then switch to just "42" encoded with 30% correction 640x640 and even that doesn't work 🤷🏻‍♂️

No error, just no qr code detected.

Processor: Apple Silicon M1 Browser: chrome 107.0.5304.87 OS: mac os 13.0 (22A380)

clawfire commented 1 year ago

Neither the live scan nor the detect on a picture work btw.

kieranbarlow commented 1 year ago

I'm experiencing the same. Commenting to follow.

pb-pfernhout commented 1 year ago

As another datapoint, I am not seeing this issue on an Intel Macbook Pro with Catalina using Chrome Version 107.0.5304.87 (Official Build) (x86_64).

But, a coworker is seeing this issue on a similar Mac Arm64 setup as the original report: Chrome Version 107.0.5304.87 (Official Build) (arm64) on MacOS Ventura 13.0. My coworker did find that the app and the demo test page work OK in Safari.

Update: Another coworker says QR Code scanning works OK on an M1 Mac using macOS 12.3 (Monterey) and Chrome 107.0.5304.87. It also works OK for them on an Intel Mac running macOS 13 (Ventura).

pb-pfernhout commented 1 year ago

@clawfire One thing you could try is to see if the issue persists on a “dev” version of Chrome. You can find that application by searching on "Google Chrome for developers". The Chrome version on the “dev” channel is updated weekly with later versions. That dev version can be run alongside the regular version of Chrome as it installs a separate icon to run it. Then we could see whether an upcoming Chrome version would likely resolve the issue sometime soon.

I just tried that as an experiment. It took about a minute to download on a fast connection and then another minute to extract/install. For me on Intel hardware, Chrome Dev is currently running: Version 109.0.5396.3 (Official Build) dev (x86_64). Chrome Dev did read a QR code OK for me – although that is not telling me much since the regular Chrome version also works for me on Catalina (10.15.7).

pb-pfernhout commented 1 year ago

A coworker experiencing the issue tried Chome Dev 109.0.5396.3 (Official Build) dev (arm64) from the dev channel on their M1 mac, but it did not fix the issue. That version still will not scan QR codes.

SystemR commented 1 year ago

+1. Works fine in Safari and Firefox.

It looks like the import worker promise never gets resolved: https://github.com/nimiq/qr-scanner/blob/master/src/qr-scanner.ts#L633

alexvarone commented 1 year ago

Experiencing the same issue with Apple M1 Pro with Chrome Version 107.0.5304.87 (Official Build) (arm64).

Works fine on other browsers as @SystemR stated.

EDIT: All seems to be working fine on Chrome V 106

pb-pfernhout commented 1 year ago

@alexvarone Just to confirm, are the results you reported from testing under Ventura (Mac OS 13)? Specifically, are you saying QR Code detection works with Chrome V 106 under Ventura?

pb-pfernhout commented 1 year ago

As a workaround, we tried essentially setting:

QrScanner["_disableBarcodeDetector"] = true 

to disable using the native QR Code detector. A coworker was then able to scan a QR code successfully on an M1 Mac running Ventura using Chrome 107.0.5304.87.

pb-pfernhout commented 1 year ago

Related to why the workaround worked, on web pages using the qr-scanner library, you can evaluate code similar to what the qr-scanner library used to determine whether a native QR code detector is available:

 await BarcodeDetector.getSupportedFormats()

I was looking to see if “qr_code” is in the resulting list. For both Firefox and Safari on the Intel Catalina Mac I use, I see “ReferenceError: Can't find variable: BarcodeDetector” when I put that code in the console. So those two browsers would presumably be loading the extra worker thread code that uses jsQR instead of using the native detector. On Chrome I see: ['aztec', 'code_128', 'code_39', 'code_93', 'data_matrix', 'ean_13', 'ean_8', 'itf', 'pdf417', 'qr_code', 'upc_e']. That indicates the qr-scanner library is going to try to use the native detector for qr_code.

I am assuming that M1 Macs using Ventura with Chrome are also using the native detector (but it would be good for someone to confirm that who has an M1 lapotp with Ventura). Since detector seems to work when using the bundled QR detection code in the library (as above), this suggests the issue is with the native detector under Ventura/Chrome107 for M1 chips. I am not sure though whether that is a Chrome issue or a Ventura issues? If it works under Chrome 106 like @alexvarone reports, then maybe it is a Chrome issues?

pb-pfernhout commented 1 year ago

It looks like the import worker promise never gets resolved: https://github.com/nimiq/qr-scanner/blob/master/src/qr-scanner.ts#L633

@SystemR pointed to a section of code linked above that loads the worker thread code which uses the jsQR code. It looks like that referenced promise could indeed potentially silently fail since there is no catch clause there (or perhaps fail with an uncaught exception error which might be ignored by an application). But, since the workaround I mentioend above to not use the native detector works under Chrome works, and Safari and Firefox also work (without a native detector), it would seem that all three browsers must successfully load that worker thread code. So I would expect that promise must be succeeding to load the worker thread code. Happy to be informed otherwise in case I am confused somewhere on this (especially as I don't have a local setup to test this and have to rely on others for that).

SystemR commented 1 year ago

I can confirm that workaround works @pb-pfernhout.

I think it's a Chrome problem. Safari and Firefox both return false for 'BarcodeDetector' in window. Chrome on the other hand returns true. However, it seems BarcodeDetector is now static only and instantiating BarcodeDetector (new BarcodeDetector) returns an empty object.

You can try the following on dev tools:

> BarcodeDetector
Ć’ BarcodeDetector() { [native code] }
> new BarcodeDetector()
BarcodeDetector {}

Empty BarcodeDetector object is what caused the issue. I'll try this on my Intel + Mojave + Chrome later and report back.

alexvarone commented 1 year ago

@pb-pfernhout Per my comment earlier, confirming that it still works on: MacOS Monterey 12.6.1 Apple M2 Chrome V106~

alexvarone commented 1 year ago

As a workaround, we tried essentially setting:

QrScanner["_disableBarcodeDetector"] = true 

to disable using the native QR Code detector. A coworker was then able to scan a QR code successfully on an M1 Mac running Ventura using Chrome 107.0.5304.87.

@pb-pfernhout I'm having trouble disabling the native QR Code detector on Chrome. Would you be able to share a more detailed code snippet?

pb-pfernhout commented 1 year ago

@alexvarone You need to set QrScanner["_disableBarcodeDetector"] before you call new QrScanner(....

alexvarone commented 1 year ago
let startScan = function (qrData) {
  welcomeScreen = document.querySelector(".welcome-screen");
  welcomeScreen.remove();
  checkTier(qrData);
  checkPrize(tier);
  let qrScanner = document.getElementById("video-container");
  qrScanner.remove();
  displayWinMessage();

  document.body.addEventListener("keydown", (evt) => {
    playAgain();
  });
};

function setResult(label, result) {
  qrData = result.data;
  startScan(qrData);

  label.textContent = result.data;
  label.style.color = "teal";
  clearTimeout(label.highlightTimeout);
  label.highlightTimeout = setTimeout(
    () => (label.style.color = "inherit"),
    100
  );
}

const scanner = new QrScanner(
  video,
  (result) => setResult(camQrResult, result),
  {
    onDecodeError: (error) => {
      camQrResult.textContent = error;
      camQrResult.style.color = "inherit";
    },
    highlightScanRegion: true,
    highlightCodeOutline: true,
  }
);

scanner.start().then(() => {
  QrScanner.listCameras(true).then((cameras) =>
    cameras.forEach((camera) => {
      const option = document.createElement("option");
      option.value = camera.id;
      option.text = camera.label;
      camList.add(option);
    })
  );
});

@pb-pfernhout Any assistance on where I should declare? QrScanner["_disableBarcodeDetector"] = true

pb-pfernhout commented 1 year ago

@alexvarone That line has to go after whatever import you do to get the QrScanner object and also before any code that eventually creates a QRScanner. So, you could add that line before all the code you included. Or you could (at the latest) add that line just before the const scanner = QrScanner(... section of that code.

If it is not working for you, then there may be another unrelated issue, like your package manager perhaps not including qr-scanner-worker.min.js in the right place (as that file needs to load correctly to run the code that replaces the native barcode detector). You could check in the console if there is an error related to loading that file to see if that was the case.

You may also want to add a catch clause after scanner.start().then(...) to check for errors there.

alexvarone commented 1 year ago

@pb-pfernhout Thank you, that worked! Noted on 'catch clause'. Much appreciated.

danimoh commented 1 year ago

Thank you all for your help debugging this. From what it seems, this issue is caused by a bug in macOS Ventura's native BarcodeDetector implementation for M1/M2 chips which surfaced in Chromium based browsers. Also the older Chromium version 106 was already showing this behavior for me on Ventura on an M1, thus this issue likely shows for all Chromium versions with BarcodeDetector support and is why it's rather a macOS issue than a Chromium issue, @pb-pfernhout @SystemR. Also @SystemR, the BarcodeDetector instance is not an empty object, it's an instance of class BarcodeDetector and has the expected methods. Nothing seems to be wrong on the Chromium side of things.

I released a new package, 1.4.2, which now enforces the use of the Worker engine in Chromium based browsers on Ventura on M1/M2 chips to circumvent the issue. Please give it a try, if you have the chance.

pb-pfernhout commented 1 year ago

@danimoh Thanks for the new library version. With vacation and task scheduling it took until now to try it. The new library version works great, according to a coworker using an affected Mac M1 Ventura laptop (without using the previous workaround we had put in place locally).

sunknudsen commented 1 year ago

Hey @danimoh, did you ever manage to get BarcodeDetector to work on macOS Ventura running on M1 or M2 Macs?

dmi3y commented 1 year ago

v1.4.2 did the trick for Ventura but still an issue with iOS (16.2), it used to work with the previous versions. Also noticed that demo does not work with iOS either https://nimiq.github.io/qr-scanner/demo/

UPD: After a bit of investigation got it working on iOS as well, the culprit was custom application code trying to call vibrate api navigator.vibrate(300);, not qr-scanner. Thanks!