ngx-scanner icon indicating copy to clipboard operation
ngx-scanner copied to clipboard

Camera showing black/white screen when multiple tabs are open

Open imtiaz993 opened this issue 7 months ago • 2 comments

When using the BrowserMultiFormatReader from @zxing/browser in a React/Next.js application with multiple browser tabs open, the camera stream fails to initialize correctly in tabs. Specifically:

The camera remains locked to the first tab that accesses it. Inactive tabs display a white screen instead of the camera feed. The camera does not release properly when switching tabs, preventing other tabs from accessing it until the page is manually interacted with (e.g., clicking a button) or refreshed, and even then, it often requires closing the original tab. This issue persists despite attempts to stop and restart the camera stream using reset() and managing tab visibility with visibilitychange events.

Expected behavior When switching between tabs, the camera should be released from the inactive tab and made available to the active tab. The

`import { useEffect, useRef, useState } from "react"; import { BrowserMultiFormatReader } from "@zxing/browser";

const ZXingScanner = ({ onScan, openCart }: any) => { const videoRef = useRef(null); const beepSound = new Audio("/beep.mp3"); const [cameraAccessError, setCameraAccessError] = useState(false);

useEffect(() => { const codeReader = new BrowserMultiFormatReader();

codeReader
  .decodeFromVideoDevice("", videoRef.current, (result) => {
    if (result && !openCart) {
      onScan(result.getText(), beepSound);
    }
  })
  .catch((error) => {
    setCameraAccessError(true);
  });

}, [onScan]);

const handleReload = () => { window.location.reload(); };

return ( <div className="h-44 w-3/4 mx-auto relative border-2 border-white"> {cameraAccessError && ( <div className="text-red-500 text-center"> Camera access denied.{" "} <span className="text-blue-500 cursor-pointer" onClick={handleReload}> Reload page{" "} or{" "} check permissions. )} <video ref={videoRef} style={{ width: "100%", height: "100%", objectFit: "cover" }} /> <div style={{ position: "absolute", top: "50%", left: "10px", width: "calc(100% - 20px)", height: "2px", backgroundColor: "red", }} > ); };

export default ZXingScanner; `

imtiaz993 avatar Mar 08 '25 18:03 imtiaz993