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

Support front/back-facing cameras #33

Open
schmich opened this issue Jul 19, 2016 · 17 comments
Open

Support front/back-facing cameras #33

schmich opened this issue Jul 19, 2016 · 17 comments

Comments

@schmich
Copy link
Owner

schmich commented Jul 19, 2016

@robertfausk
Copy link

Any updates on this?
Do you need a PR? If yes, do you have any hints where to start and/or how instascan interface should behave?

@adriengibrat
Copy link

What do you think about passing constraints to Camera.getCameras() ?

getCameras implementation could try to getUserMedia with provided constraints and filter the camera that fulfill those constraints.
see camera.js#L53

This could also be a way to fix #22, but then it would require to pass the resolution contraints to Camera contructor, to merge the resolution constraints with the default provided in start method.
see camera.js#L20

If it seems ok to anyone, I'm willing to submit a PR ;)

@clytras
Copy link

clytras commented Jul 28, 2017

My workaround, until this fixed by allowing some king of custom Camera settings, is to set the first camera which contains "back" inside its name value:

if (cameras.length > 0) {
    var selectedCam = cameras[0];
    $.each(cameras, (i, c) => {
        if (c.name.indexOf('back') != -1) {
            selectedCam = c;
            return false;
        }
    });

    scanner.start(selectedCam);
} else {
    console.error('No cameras found.');
}

It always selects the rear camera.

@souske
Copy link

souske commented Aug 9, 2017

my end its working but when i try to use the rear camera it flip horizontally.. how to put it back on the usual position? thanks

@cbnt
Copy link

cbnt commented Sep 13, 2017

I am having an unusual problem. It doesn't matter which camera I start, it always show the front camera. I can clearly see both cameras on the array and I force to start the back camera, still, the script always start the front camera.
Just downloaded the most recent version of iOS.
Settings:
iPhone 6s
iOS 11
Safari.

Also not loading camera on Chrome and Firefox for same device/OS.

Any ideas?

Thanks

@HelenH
Copy link

HelenH commented Sep 25, 2017

I am having the same issue. Were you able to select the rear camera on IOS

Thanks
Helen

@Smux
Copy link

Smux commented Oct 5, 2017

@cbnt
@HelenH
Did you solve this problem? For me I also see both cameras available but switching or preselecting to the back camera always ends in flipping back to the front camera :(

@schmich First of all thank you sooo much for this awesome project! :) Secondly, do you have any information on whether this is a common Iphone issue or how this can be fixed?

Note: Using iphone 7 with iOS 11

@HelenH
Copy link

HelenH commented Oct 5, 2017

Hi @Smux ,

Yes followed the steps in Issue #54

git clone git@github.com:schmich/instascan.git
cd instascan/
npm install gulp-cli -g
npm install
gulp release
cp dist/instascan.min.js /path/to/our/libraries/include/dir

Much thanks @schmich for this awesome project also.

@cbnt
Copy link

cbnt commented Oct 5, 2017

@HelenH
@Smux

I fixed the issue using this fork: https://github.com/PallasKatze/instascan
Still need to follow the steps in Issue #54 though

But it is working fine.
Just a little issue with Android but I believe it is one specific version.

@labregowski
Copy link

labregowski commented Dec 23, 2017

Hi @cbnt,
I want to try that too. But the minified js is that fork links to the same js as the original branch.
I cannot find any minified js in the package. HOw could I do that? Is there anyone who can link one working js file?
Thanks in advance.

I know this is a basic question and a bit off topic but I have been trying to produce a release js and haven't been able - installed npm on my test server but npm keeps giving errors when I try to publish.

@arnaubosch
Copy link

My workaround, until this fixed by allowing some king of custom Camera settings, is to set the first camera which contains "back" inside its name value:

if (cameras.length > 0) {
    var selectedCam = cameras[0];
    $.each(cameras, (i, c) => {
        if (c.name.indexOf('back') != -1) {
            selectedCam = c;
            return false;
        }
    });

    scanner.start(selectedCam);
} else {
    console.error('No cameras found.');
}

It always selects the rear camera.

My workaround, until this fixed by allowing some king of custom Camera settings, is to set the first camera which contains "back" inside its name value:

if (cameras.length > 0) {
    var selectedCam = cameras[0];
    $.each(cameras, (i, c) => {
        if (c.name.indexOf('back') != -1) {
            selectedCam = c;
            return false;
        }
    });

    scanner.start(selectedCam);
} else {
    console.error('No cameras found.');
}

It always selects the rear camera.

@clytras nice solution! But what happens if the mobile phone has more than one back camera?

I've tried this solution and with the first back camera of the array the vision is horrible with a lot of zoom. I am not able to scan anything.

But, if I use the second back camera returned it works perfectly and I can scan everything.

My question is if exists a a way to detect which is the main back camera? Imagine if the website is used by different users, which means they will have different devices and the number of back cameras will be different and the order returned.

Thanks a lot.

@ashu4code
Copy link

My workaround, until this fixed by allowing some king of custom Camera settings, is to set the first camera which contains "back" inside its name value:

if (cameras.length > 0) {
    var selectedCam = cameras[0];
    $.each(cameras, (i, c) => {
        if (c.name.indexOf('back') != -1) {
            selectedCam = c;
            return false;
        }
    });

    scanner.start(selectedCam);
} else {
    console.error('No cameras found.');
}

It always selects the rear camera.

German Iphone have different language of "Back"

@clytras
Copy link

clytras commented Nov 28, 2021

German Iphone have different language of "Back"

@ashu4code this is a workaround, not the solution to the problem, thus we have to adapt it to our needs.

If you face these kind of different language cases and your audience is mainly targeted on specific locales, then you can easily change the indexOf with a regular expression containing the words of the cameras you want to support.

So, instead of c.name.indexOf('back') we can have a RegExp test /back|zurück|arrière/iu.test(c.name). If you want to support older browsers that don't have Regular Expressions Unicode support, then just make a loop to search for the words you want to support.

@BryanRiveraLivia
Copy link

Hi guys, I have the solution and is possible set back camera for default.
`let opts = {
// Whether to scan continuously for QR codes. If false, use scanner.scan() to manually scan.
// If true, the scanner emits the "scan" event when a QR code is scanned. Default true.
continuous: true,

            // The HTML element to use for the camera's video preview. Must be a <video> element.
            // When the camera is active, this element will have the "active" CSS class, otherwise,
            // it will have the "inactive" class. By default, an invisible element will be created to
            // host the video.
            video: document.getElementById('preview'),
            
            // Whether to horizontally mirror the video preview. This is helpful when trying to
            // scan a QR code with a user-facing camera. Default true.
            mirror: false,
            
            // Whether to include the scanned image data as part of the scan result. See the "scan" event
            // for image format details. Default false.
            captureImage: false,
            
            // Only applies to continuous mode. Whether to actively scan when the tab is not active.
            // When false, this reduces CPU usage when the tab is not active. Default true.
            backgroundScan: false,
            
            // Only applies to continuous mode. The period, in milliseconds, before the same QR code
            // will be recognized in succession. Default 5000 (5 seconds).
            refractoryPeriod: 5000,
            
            // Only applies to continuous mode. The period, in rendered frames, between scans. A lower scan period
            // increases CPU usage but makes scan response faster. Default 1 (i.e. analyze every frame).
            scanPeriod: 5
        };
        let scanner = new Instascan.Scanner(opts);
        scanner.addListener('scan', function (content) {
            console.log(content);
            QRcodigo.set(content);
            scanner.stop();
        });
        Instascan.Camera.getCameras().then(function (cameras) {
            if (cameras.length > 0) {
                scanner.start(cameras[cameras.length-1]);
            } else {
                console.error('No cameras found.');
            }
        }).catch(function (e) {
            console.error(e);
        });`

@nrmnhdyt
Copy link

nrmnhdyt commented Jul 6, 2023

pls help me. how to use this code to my js?

@brunoinds
Copy link

For the new ones, I will explain step-by-step how to solve it:

  1. Clone the repository gh repo clone schmich/instascan
  2. Install the Gulp Compiler npm install gulp-cli -g. This is essential to regenerate the Instascan.min.js
  3. Enter the folder cd instascan and Install NPM dependecies npm install
  4. Go to file src/camera.js
  5. Replace the async start() method of the class Camera to:
async start() {
    let constraints = {
      audio: false,
      video: {
        facingMode: { exact: "environment" },
        mandatory: {
          sourceId: this.id,
          minWidth: 600,
          maxWidth: 800,
          minAspectRatio: 1.6
        },
        optional: []
      }
    };

    this._stream = await Camera._wrapErrors(async () => {
      return await navigator.mediaDevices.getUserMedia(constraints);
    });

    return this._stream;
  }
  1. Now let's create a new Instascan.min.js using the command: gulp release, it's will create a folder on the project called "dist" and inside of it, there is the brand-new Instascan.min.js that supports back-cameras.
  2. Now include the Instascan.min.js into your project, it will magically ✨ work!

P.S.: To generate the instascan.min.js again you need the gulp release. But this project use the old Gulp version, and this will not work in NodeJS new versions, so to solve that see this link https://stackoverflow.com/questions/55921442/how-to-fix-referenceerror-primordials-is-not-defined-in-node-js .

BONUS:

I have created a new Instascan.min.js with this capabillity. The gist is that: https://gist.github.com/brunoinds/4466253d4ec667280074c6aa3bd2dd19

And you can include it on your code using:
<script src="https://gist.githubusercontent.com/brunoinds/4466253d4ec667280074c6aa3bd2dd19/raw/871a09d0533fab04651de05a0d0e994f547ae60b/instascan.min.js"></script>

@valeroAlb
Copy link

@brunoinds I'm using your instascan.min.js but I have this error:
instascan.min.js:9 Uncaught (in promise) Error: Cannot access video stream (TypeError).

do you know why?

thanks

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