Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to specify preferred camera #507

Open
rtamsatyam opened this issue Feb 20, 2023 · 12 comments
Open

Unable to specify preferred camera #507

rtamsatyam opened this issue Feb 20, 2023 · 12 comments

Comments

@rtamsatyam
Copy link

Angular 14, Zxing 3.6.2

As a user with more cameras sets the preferred camera, which is then stored in sessionStorage or localStorage.
However, when the user reloads the page, the zxing scanner seems to pick its own default camera.

Is there a way the preferred camera is taken as the default camera?

@0pahh
Copy link

0pahh commented Feb 20, 2023

Yes, you can do it, start by defining the input of the device like this, then define the function that will initialize the camera in the camerasFound output.

Normally you should not need to initialize selectedCamera

Just store the cameraDeviceId somewhere.

<zxing-scanner 
  [formats]="formats"
  [device]="selectedCamera"
  (scanSuccess)="scan($event)"
  (torchCompatible)="setTorchButton($event)"
  (camerasFound)="getCamerasAvailable($event)"
  (camerasNotFound)="showErrorMessage($event)" 
/>
selectedCamera!: MediaDeviceInfo; // Define the camera used by the scanner
availableCameras: MediaDeviceInfo[] = []; // Defines the cameras available for this device
getCamerasAvailable(availableCameras: MediaDeviceInfo[]): void {
  this.availableCameras = availableCameras;  //We define this.availableCameras according to availableCameras sent by the 
  ZXingScannerComponent
  
  const prefCamera = availableCameras.find(
            (c) => c.deviceId === 'ID_OF_PREFERRED_CAMERA'
  );
  if (prefCamera) this.selectedCamera = prefCamera;
}

@rtamsatyam
Copy link
Author

It seems to set the value here, but it somehow doesn't reflect in the camera being selected itself. For e.g. in my situation I have an integrated webcam and a microsoft webcam. The zxing scanner always shows integrated webcam as the default option. When I force it to select the Microsoft camera, then selected camera in the select list shows as Microsoft Webcam. But the camera actually being selected is still the integrated webcam.

@0pahh
Copy link

0pahh commented Feb 20, 2023

Just in case, try adding a timeout before switching cameras, maybe that can help.

@rtamsatyam
Copy link
Author

Sorry that also did not help.

@0pahh
Copy link

0pahh commented Feb 20, 2023

I may be the problem, try switching to this ?

<zxing-scanner 
  [formats]="formats"
  [(device)]="selectedCamera"
  (scanSuccess)="scan($event)"
  (torchCompatible)="setTorchButton($event)"
  (camerasFound)="getCamerasAvailable($event)"
  (camerasNotFound)="showErrorMessage($event)" 
/>

@rtamsatyam
Copy link
Author

rtamsatyam commented Feb 20, 2023

That was the original code actually with a two way bind on device. It doesn't work either!!

@NachoCarpintero2937
Copy link

Hi, it doesn't work for me either :(

@martindebrunne
Copy link

[device]="selectedCamera" instead of [(device)]="selectedCamera" works for me

@hsayed21
Copy link

doesn't work, is this bug or what?

@iijat
Copy link

iijat commented Jun 30, 2023

I see the same behavior. Setting the selectedCamera has no effect on the scanning camera.

@cre8
Copy link

cre8 commented Oct 4, 2023

Error is still there... also setting via scanner.device has no effect.
It only worked for me when I add a delay, but this could end in a bad UX:

  /**
   * Sets the camera
   * @param event
   */
  foundCameras(event: MediaDeviceInfo[]) {
    this.cameras = event;
    const selected = localStorage.getItem('camera');
    if (selected) {
      const found = this.cameras.find((c) => c.deviceId === selected);
      if (found) {
        setTimeout(() => {
          this.changeCamera(found);
        }, 2000);
      }
    }
  }

  changeCamera(camera: MediaDeviceInfo) {
    localStorage.setItem('camera', camera.deviceId);
    this.activeCamera = camera;
  }

@Ju-l1a
Copy link

Ju-l1a commented Oct 11, 2023

|Setting the camera programatically during startup only works if autostart is disabled, otherwise there's a race condition and the activeCamera is reset during zxing-scanner startup to whichever camera zxing-scanner chooses automatically.

In the template:

<zxing-scanner #scannerComponent
    ...
    [(device)]="activeCamera "
    [autostart]="false"
></zxing-scanner>

In the component:

    @ViewChild('scannerComponent')
    private scannerComponent: ZXingScannerComponent;

   ...

  /**
   * Sets the camera
   * @param event
   */
  foundCameras(event: MediaDeviceInfo[]) {
    this.cameras = event;
    const selected = localStorage.getItem('camera');
    if (selected) {
      const found = this.cameras.find((c) => c.deviceId === selected);
      if (found) {
      
            if (this.scannerComponent.device !== device) {
            this.scannerComponent.askForPermission()
                .then(() => changeCamera(found);
        }
      }
    }
  }

  changeCamera(camera: MediaDeviceInfo) {
    localStorage.setItem('camera', camera.deviceId);
    this.activeCamera = camera;
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants