Instascan: IOS safari 11.4- Back camera opening issue

Created on 27 Sep 2018  ·  44Comments  ·  Source: schmich/instascan

Hi,
I am using Instascan and facing issue with ios safari.
No error is given by instascan but it is not opening back camera. Every time it is opening front camera.
Same code is working fine with Android(Chrome, Firefox).

var self;
isQRScannerInitialised = false;
function testQrCode(textBoxId,DivWidth){
    self = initialiseQRScanner(DivWidth);

    self.scanner.addListener('scan', function (content, image) {
         if(textBoxId == $("#hiddenTextBox").val()){
                audio.play();
                var code = content;
                $("#"+textBoxId).val(code);
                isQRScannerInitialised = false;

            }

    }, false);

}

function initialiseQRScanner(DivWidth){

    self = this;

    if(isQRScannerInitialised == false){

        var tempVideo = document.getElementsByTagName("video")[0];
        tempVideo.width=DivWidth;
        tempVideo.height=480;

        self.scanner = new Instascan.Scanner({ video: document.getElementsByTagName("video")[0],mirror:false, scanPeriod: 1});

        Instascan.Camera.getCameras().then(function (cameras) {
            self.cameras = cameras;
            if (self.cameras.length > 0) {
                 if(cameras[0].name.match(/back/) || cameras[0].name.match(/Back/)){
                    self.activeCameraId = cameras[0].id;
                    self.scanner.start(cameras[0]);
                } else if(cameras[1].name.match(/back/) || cameras[1].name.match(/Back/)){
                    self.activeCameraId = cameras[1].id;
                    self.scanner.start(cameras[1]);
                }
                isQRScannerInitialised = true;

            } else {

                alert('No cameras found.');
                isQRScannerInitialised = false;
                return;
            }
          }).catch(function (e) { 
                isQRScannerInitialised = false;
                alert("QR error name:-"+e.name + " & QR error message:-"+e.message); console.error(e); 
            });

    }
    return self;
}

Most helpful comment

This is a great product and it has been really useful, so thank you for making it wonderful. Here is the issue with this instascan from my research:

  • The class Camera when calling the getCameras returns a collection of Camera objects that are created from the MediaDeviceInfo objects collected through a call to navigator.mediaDevices.enumerateDevices(). These are NOT MediaStream objects which contain the actual stream from the camera used when starting the scanner. These MediaDeviceInfo objects contain _id_ and _name_ properties and nothing more. They are used to create an array of Camera objects.

When you call _scanner.start(camera)_, you are passing in a Camera object that will call the _camera.start()_ method on the camera.

  • The _camera.start()_ method THEN calls the _navigator.mediaDevices.getUserMedia(contraints)_, which returns an Arrary of MediaStream objects based on the given constraints listed in the method.
  • _scanner.start()_ calls _scanner._enableScan(camera)_ giving it the First MediaStream object returned from the call above in camera. It sets the
                  **This Part Is the Disconnect and what is messing it all up!**

The Constraint Issue:

The Camera object passed in uses its id in the constraints as _"mandatory"_ for the searching of the devices. If it is not found, no video will show. Also other "mandatory" constraints are set.

Different devices DO NOT SUPPORT the constraints used!
Run this link on the device you want to use and it will tell you what Constraints it supports:
https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints

Run this link on the device you want to use and enter a constraint. It will tell you if it is supported:
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSupportedConstraints/deviceId

Ipad/Iphone/IOS supported Constraints:

aspectRatio, facingMode, _deviceId*_ , height, width, aspectRatio and others.

_When I tested this, _deviceId will be ignored as a constraint._ Try this out in the above link for constraints and you will see it sets the deviceId = "". When I grabbed it in javascript and displayed it, the iphone always returned a blank deviceId.

So, To grab the back camera on the Iphone, you have to use the facingMode and NOT use deviceId.

Android supported Constraints:

deviceId, _facingMode*_, aspectRatio, height, width, and many others.

I tested this, on a samsung tablet and android phone. The facingMode defaulted to the "user" front camera. I experimented with this code and found that for some reason yet discovered, the facingMode for android is not working. Yet it works in the above link. I am going to continue to investigate that portion and possibly fix this code to work properly with facingMode and android.

* *ANSWER TO ANDROID ISSUE** *
The Gulp build of this project includes the webrtc-adapter version ^1.4.0 which messes up the facingMode on Android Chrome. Looking through the code it actually deleted the facing mode.

  • To fix in this project - in _index.js_, remove the line 2 require('webrtc-adapter'); Then follow the build procedures below. When I tested on a tablet and 4 different android phones on Chrome it all worked again to grab the back camera.

To grab the back camera on the Android with this instascan code, you can use the deviceId.
Make sure deviceId is a _video_ constraint like

video: {
  devideId: this.id
}

Camera Constraint Code:

Here is the Code from the project that sets the constraints and gets the MediaStream objects
The reason why this code doesn't work properly is that sourceId of the _video constraint_ is not supported for _Android_ or _Iphone_. This has to be changed to deviceId. Also all of the mandatory items need to go if they are not what your device handles.

async start() {
    let constraints;
    var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

    if (iOS) {
      constraints = {
        audio: false,
        video: {
          facingMode: 'environment',
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    } else {
      constraints = {
        audio: false,
        video: {
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    }

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

How to modify InstaScan and minify it:

to get this and change it, I have been using VSCode.
1) Install Node.js and vsCode.
2) at a terminal in the directory you want it to download run:
git clone https://github.com/JoseCDB/instascan.git

3) at the terminal cd to the instascan directory:
cd instascan

4) change the javascript and run gulp to release the code:
gulp release

5) This will give you a new minified instascan.min.js item in the _dist_ folder.

I am going to figure out this Android issue hopefully this weekend. I hope this gives you enough insight for any future projects with this awesome library.

All 44 comments

Do you have access to the apple device? Do you know if the demo is working?

It looks like this has been having issue with iOS safari but I've read that people were able to overcome this issue by adding meta tags. Just dig around this forum and you'll see. I'm working on something similar, so I'm interested. What's holding me back is that I do not have a device readily available.

I was trying the demo out on an iPhone, it did not work.

Yeah, been working on this, I can't get this to work. Trying to go back and re-read threads. I got the front-facing camera to work by adding the latest web RTC adapter and adding the _playsinline_ attribute to the video tag. It can read the cameras but does nothing when swapping to the back camera.

i had added playsinline attribute inside video tag and mentioned meta tag also.

i had added playsinline attribute inside video tag and mentioned meta tag also.

Someone had actually fixed this in one of the threads. I'm trying that out right now but have to wait for someone with an iPhone to come to work.

Hey, I got this to work but there's still the issue, despite choosing cameras, the default will always be the back rear camera. So if you're in the need to pick the front camera, you're screwed (but seriously, who's going to try and scan with the front facing camera).

Here's what I did!

I added the meta tag.
<meta name="apple-mobile-web-app-capable" content="yes">

Added this attribute:
<video id="scanner" class="video-back" playsinline></video>

Added this JS file:
<script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

And then packaged this to release: https://github.com/JoseCDB/instascan/tree/ios-rear-camera. Not sure if you know how to use Gulp with node.js but it's easy. I Iearned it in 15 minutes! I'm using this persons version of Instascan. He knew of the issue and was able to fix it. Hope this helps. Good luck.

I have used meta tag, video tag and adapter-latest.js.
And i am using instscan.min.js and don't know how can use the ".js - scanner.js - camara.js" separately.

I have used meta tag, video tag and adapter-latest.js.
And i am using instscan.min.js and don't know how can use the ".js - scanner.js - camara.js" separately.

You're supposed to have installed node.js. There's a command prompt that packages all of those files together, the final output would be that minified JS file of the instascanner.

This is a great product and it has been really useful, so thank you for making it wonderful. Here is the issue with this instascan from my research:

  • The class Camera when calling the getCameras returns a collection of Camera objects that are created from the MediaDeviceInfo objects collected through a call to navigator.mediaDevices.enumerateDevices(). These are NOT MediaStream objects which contain the actual stream from the camera used when starting the scanner. These MediaDeviceInfo objects contain _id_ and _name_ properties and nothing more. They are used to create an array of Camera objects.

When you call _scanner.start(camera)_, you are passing in a Camera object that will call the _camera.start()_ method on the camera.

  • The _camera.start()_ method THEN calls the _navigator.mediaDevices.getUserMedia(contraints)_, which returns an Arrary of MediaStream objects based on the given constraints listed in the method.
  • _scanner.start()_ calls _scanner._enableScan(camera)_ giving it the First MediaStream object returned from the call above in camera. It sets the
                  **This Part Is the Disconnect and what is messing it all up!**

The Constraint Issue:

The Camera object passed in uses its id in the constraints as _"mandatory"_ for the searching of the devices. If it is not found, no video will show. Also other "mandatory" constraints are set.

Different devices DO NOT SUPPORT the constraints used!
Run this link on the device you want to use and it will tell you what Constraints it supports:
https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints

Run this link on the device you want to use and enter a constraint. It will tell you if it is supported:
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSupportedConstraints/deviceId

Ipad/Iphone/IOS supported Constraints:

aspectRatio, facingMode, _deviceId*_ , height, width, aspectRatio and others.

_When I tested this, _deviceId will be ignored as a constraint._ Try this out in the above link for constraints and you will see it sets the deviceId = "". When I grabbed it in javascript and displayed it, the iphone always returned a blank deviceId.

So, To grab the back camera on the Iphone, you have to use the facingMode and NOT use deviceId.

Android supported Constraints:

deviceId, _facingMode*_, aspectRatio, height, width, and many others.

I tested this, on a samsung tablet and android phone. The facingMode defaulted to the "user" front camera. I experimented with this code and found that for some reason yet discovered, the facingMode for android is not working. Yet it works in the above link. I am going to continue to investigate that portion and possibly fix this code to work properly with facingMode and android.

* *ANSWER TO ANDROID ISSUE** *
The Gulp build of this project includes the webrtc-adapter version ^1.4.0 which messes up the facingMode on Android Chrome. Looking through the code it actually deleted the facing mode.

  • To fix in this project - in _index.js_, remove the line 2 require('webrtc-adapter'); Then follow the build procedures below. When I tested on a tablet and 4 different android phones on Chrome it all worked again to grab the back camera.

To grab the back camera on the Android with this instascan code, you can use the deviceId.
Make sure deviceId is a _video_ constraint like

video: {
  devideId: this.id
}

Camera Constraint Code:

Here is the Code from the project that sets the constraints and gets the MediaStream objects
The reason why this code doesn't work properly is that sourceId of the _video constraint_ is not supported for _Android_ or _Iphone_. This has to be changed to deviceId. Also all of the mandatory items need to go if they are not what your device handles.

async start() {
    let constraints;
    var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

    if (iOS) {
      constraints = {
        audio: false,
        video: {
          facingMode: 'environment',
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    } else {
      constraints = {
        audio: false,
        video: {
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    }

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

How to modify InstaScan and minify it:

to get this and change it, I have been using VSCode.
1) Install Node.js and vsCode.
2) at a terminal in the directory you want it to download run:
git clone https://github.com/JoseCDB/instascan.git

3) at the terminal cd to the instascan directory:
cd instascan

4) change the javascript and run gulp to release the code:
gulp release

5) This will give you a new minified instascan.min.js item in the _dist_ folder.

I am going to figure out this Android issue hopefully this weekend. I hope this gives you enough insight for any future projects with this awesome library.

Hi, this should be worked well.
First, add adapter.js from https://github.com/webrtc/adapter.

After that clone this:
git clone https://github.com/quocthai95/instascan.git
Run:
npm i
to install necessaries

Use gulp to release final code:
gulp release

I've checked on Iphone 6 plus (iOS 11.4) & Iphone 8 plus (iOS 11.3) and it worked well. You can swap cameras normally.

Hope you can solve your problem.

Hi, this should be worked well.
First, add adapter.js from https://github.com/webrtc/adapter.

After that clone this:
git clone https://github.com/quocthai95/instascan.git
Run:
npm i
to install necessaries

Use gulp to release final code:
gulp release

I've checked on Iphone 6 plus (iOS 11.4) & Iphone 8 plus (iOS 11.3) and it worked well. You can swap cameras normally.

Hope you can solve your problem.

When installing necessaries I get "12 vulnerabilities (1 low, 5 moderate, 6 high)".
Some "$ npm install --save-dev [package-name]" commands seems to resolve these vulnerabilities, but I cant build it due to the following exception:

$ gulp release assert.js:351 throw err; ^ AssertionError [ERR_ASSERTION]: Task function must be specified at Gulp.set [as _setTask] (C:\Users\John\Downloads\instascan-ios-rear-camera\instascan-ios-rear-camera\node_modules\undertaker\lib\set-task.js:10:3)

How do I get on from here, I'd really like to try this build. It works so well with my android phone?

/John

Hi @johnatitide ,
Did you install gulp latest version (4.0.0) ? If so, please try to restrict it to 3.9.1. FYI:
https://github.com/ampproject/docs/issues/793#issuecomment-354836162
Or can you provide which commands u did to build it.

Hi @quocthai95

Building works with the following commands:
git clone https://github.com/quocthai95/instascan.git
npm install [email protected]
npm i
gulp release

I can now switch camera in Safari on iPad and iPhone. Nice.

Any chance the constraint fixes will be merged back to schmich's repo?

Any chance the constraint fixes will be merged back to schmich's repo?

I've created new pull request. Wait for accepting ^^

@quocthai95 hi, ive followed your steps from https://github.com/schmich/instascan/issues/182#issuecomment-447198290.

i was wondering, im getting front camera as default on my android chrome. wondering how can i make back camera as default? do you have an example code?

@fariskas ,
Use regexp to test whether it matches /back/ then start it, so you can have back camera as default.

`Instascan.Camera.getCameras().then(function (cameras) {
if(cameras[0].name.match(/back/i)){
scanner.start(cameras[0]);
} else if(cameras[1].name.match(/back/i)){
scanner.start(cameras[1]);
}
}

This might be useful: I am using a for-loop to find "back" in cameras[i].name but I was unsuccessful and unable to select the back camera on iPad until I wrote cameras[i].name to console.log and found out that I had to look for "achterzijde" (which is "back" in Dutch).
So if you are unsuccessful trying to select the back camera in iOS, try translating "back" or write cameras[i].name to console.log to find out what is the back camera's name.

I can confirm the demo only works with the front facing camera. This is with Safari on iOS 12.2

Has anyone figured out how to use the back camera with Safari on iOS 12+?

Has anyone figured out how to use the back camera with Safari on iOS 12+?

I have been using a modified version of this library for about 7 months now on over 30+ types ios and android phones and tablets. Look at the comments I left above about a modified version to get any camera from the os you are working with. The comments keep talking about adding the webrtc after, which i found to be the whole issue of this library.

I removed webrtc from the project altogether and recompiled it. webrtc is not needed any more with this code when transpiled to es5 or above. The use of webrtc in the library and how it was coded did not allow the correct camera to be retrieved.

I have included the fixed and transpiled regular and minified js files that I have been using for a while now. I use it for school attendance with QrCodes across any phones students and teachers have, which have been about 30+ models at this point. It can grab any camera.

I hope this helps.

Back Camera code
```
scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
.then(handleSuccess)
.catch(handleError);
//Start scanning
scanner.addListener('scan', foundCode);

            Instascan.Camera.getCameras().then(function (cameras) {
                if (cameras.length > 0) {
                    scanner.start(cameras[0]);
                }
                else {
           ...        
                }
            }).catch (function (e) {
             ...  
            });

```
instascan.min.zip

https://github.com/schmich/instascan/issues/182#issuecomment-443388022

This is a great product and it has been really useful, so thank you for making it wonderful. Here is the issue with this instascan from my research:

  • The class Camera when calling the getCameras returns a collection of Camera objects that are created from the MediaDeviceInfo objects collected through a call to navigator.mediaDevices.enumerateDevices(). These are NOT MediaStream objects which contain the actual stream from the camera used when starting the scanner. These MediaDeviceInfo objects contain _id_ and _name_ properties and nothing more. They are used to create an array of Camera objects.

When you call _scanner.start(camera)_, you are passing in a Camera object that will call the _camera.start()_ method on the camera.

  • The _camera.start()_ method THEN calls the _navigator.mediaDevices.getUserMedia(contraints)_, which returns an Arrary of MediaStream objects based on the given constraints listed in the method.
  • _scanner.start()_ calls _scanner._enableScan(camera)_ giving it the First MediaStream object returned from the call above in camera. It sets the src element to this media stream object.
    **This Part Is the Disconnect and what is messing it all up!**

The Constraint Issue:

The Camera object passed in uses its id in the constraints as _"mandatory"_ for the searching of the devices. If it is not found, no video will show. Also other "mandatory" constraints are set.

Different devices DO NOT SUPPORT the constraints used!
Run this link on the device you want to use and it will tell you what Constraints it supports:
https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints

Run this link on the device you want to use and enter a constraint. It will tell you if it is supported:
https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSupportedConstraints/deviceId

Ipad/Iphone/IOS supported Constraints:

aspectRatio, facingMode, _deviceId*_ , height, width, aspectRatio and others.

_When I tested this, _deviceId will be ignored as a constraint._ Try this out in the above link for constraints and you will see it sets the deviceId = "". When I grabbed it in javascript and displayed it, the iphone always returned a blank deviceId.

So, To grab the back camera on the Iphone, you have to use the facingMode and NOT use deviceId.

Android supported Constraints:

deviceId, _facingMode*_, aspectRatio, height, width, and many others.

I tested this, on a samsung tablet and android phone. The facingMode defaulted to the "user" front camera. I experimented with this code and found that for some reason yet discovered, the facingMode for android is not working. Yet it works in the above link. I am going to continue to investigate that portion and possibly fix this code to work properly with facingMode and android.

* _*ANSWER TO ANDROID ISSUE*_ **
The Gulp build of this project includes the webrtc-adapter version ^1.4.0 which messes up the facingMode on Android Chrome. Looking through the code it actually deleted the facing mode.

  • To fix in this project - in _index.js_, remove the line 2 require('webrtc-adapter'); Then follow the build procedures below. When I tested on a tablet and 4 different android phones on Chrome it all worked again to grab the back camera.

To grab the back camera on the Android with this instascan code, you can use the deviceId.
Make sure deviceId is a _video_ constraint like

video: {
  devideId: this.id
}

Camera Constraint Code:

Here is the Code from the project that sets the constraints and gets the MediaStream objects
The reason why this code doesn't work properly is that sourceId of the _video constraint_ is not supported for _Android_ or _Iphone_. This has to be changed to deviceId. Also all of the mandatory items need to go if they are not what your device handles.

async start() {
    let constraints;
    var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

    if (iOS) {
      constraints = {
        audio: false,
        video: {
          facingMode: 'environment',
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    } else {
      constraints = {
        audio: false,
        video: {
          mandatory: {
            sourceId: this.id,
            minWidth: 600,
            maxWidth: 800,
            minAspectRatio: 1.6
          },
          optional: []
        }
      };
    }

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

How to modify InstaScan and minify it:

to get this and change it, I have been using VSCode.

  1. Install Node.js and vsCode.
  2. at a terminal in the directory you want it to download run:
    git clone https://github.com/JoseCDB/instascan.git
  3. at the terminal cd to the instascan directory:
    cd instascan
  4. change the javascript and run gulp to release the code:
    gulp release
  5. This will give you a new minified instascan.min.js item in the _dist_ folder.

I am going to figure out this Android issue hopefully this weekend. I hope this gives you enough insight for any future projects with this awesome library.

I followed above steps then edit file camera.js (at line 29) as below
facingMode: { exact: "environment" },
It work for me. Thank you @apchandler

I am glad you got something to work for you! Thanks @glorynguyen for posting this fix too!

Unfortunately these solutions do not work on iOS 13. It is simply blank (not even black).
When remote debugging Safari, also no errors are shown in the console.

Has anyone figured out how to use the back camera with Safari on iOS 12+?

I have been using a modified version of this library for about 7 months now on over 30+ types ios and android phones and tablets. Look at the comments I left above about a modified version to get any camera from the os you are working with. The comments keep talking about adding the webrtc after, which i found to be the whole issue of this library.

I removed webrtc from the project altogether and recompiled it. webrtc is not needed any more with this code when transpiled to es5 or above. The use of webrtc in the library and how it was coded did not allow the correct camera to be retrieved.

I have included the fixed and transpiled regular and minified js files that I have been using for a while now. I use it for school attendance with QrCodes across any phones students and teachers have, which have been about 30+ models at this point. It can grab any camera.

I hope this helps.

Back Camera code

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip

#182 (comment)

This solves my problem, thank you very much.

Whats the latest fix for this? I'we tried a few from the thread but i only seem to get the front camera.
Don't know how to use Gulp or actually compile .js .git projects, i mainly code in C#/Asp.net Mvc so this is a bit new to me.
apchandler's solution gives me errors. (Video not defined)
Currently loading an "fixed" instascan.min.js for Android devices and his version for IOS, But i can't seem to get it to work.

Whats the latest fix for this? I'we tried a few from the thread but i only seem to get the front camera.
Don't know how to use Gulp or actually compile .js .git projects, i mainly code in C#/Asp.net Mvc so this is a bit new to me.
apchandler's solution gives me errors. (Video not defined)
Currently loading an "fixed" instascan.min.js for Android devices and his version for IOS, But i can't seem to get it to work.

Do you have the html video element present?
```

When you run instascan you need to speficy a video element like:

var self = this;
self.scanner = new Instascan.Scanner({ video: document.getElementById('preview'), scanPeriod: 5 });
self.scanner.addListener('scan', function (content, image) {
self.scans.unshift({ date: +(Date.now()), content: content });
});
Instascan.Camera.getCameras().then(function (cameras) {
self.cameras = cameras;
if (cameras.length > 0) {
self.activeCameraId = cameras[0].id;
self.scanner.start(cameras[0]);
} else {
console.error('No cameras found.');
}
}).catch(function (e) {
console.error(e);
});
```

Yeah, i got it working with:

<video class="player" style="max-width:100%" id="preview" playsinline></video>

<script>
.....
  Instascan.Camera.getCameras().then(function (cameras) {
        if (cameras.length > 0) {
          scanner.start(cameras[0]);
        } else {
          console.error('No cameras found.');
        }
      }).catch(function (e) {
        console.error(e);
      });
</script>

Starting cameras[0] for Iphone/Ios Devices. And this for Android:

<script>
.....
  Instascan.Camera.getCameras().then(function (cameras) {
                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.');
                }
              });
</script>

Seems like the problem was that i only checked if Request.UserAgent.Contains("ios") and not "iphone", so i ran the Android script for the Iphone as well.

That's good to know. Thanks for the info.

@apchandler Hi, Do you know if exists a way for selecting the 'main' back camera?

I have a website where my users wilI scan QR CODES using instascan. I amb developing the website and doing some tests I access to the website using my mobiIe phone which has 4 back cameras (HUAWEI P30 PRO).

I have tried the $.each and with the first back camera selected I can't scan anything because the vision is so fuzzy and with a lot of zoom.

But, if I select the cameras[2] I am able to scan everything.

Exists a generic way to select the 'main' back camera?

I mean, my webapp is going to be used by so many users with differents mobile phones, different number of cameras and the order of the cameras will be also different.

Or do you recommend to do a select with all the cameras and then let the user to pick up the one that works perfectly for him?

Thanks

@apchandler Hi, Do you know if exists a way for selecting the 'main' back camera?

I have a website where my users wilI scan QR CODES using instascan. I amb developing the website and doing some tests I access to the website using my mobiIe phone which has 4 back cameras (HUAWEI P30 PRO).

I have tried the $.each and with the first back camera selected I can't scan anything because the vision is so fuzzy and with a lot of zoom.

But, if I select the cameras[2] I am able to scan everything.

Exists a generic way to select the 'main' back camera?

I mean, my webapp is going to be used by so many users with differents mobile phones, different number of cameras and the order of the cameras will be also different.

Or do you recommend to do a select with all the cameras and then let the user to pick up the one that works perfectly for him?

Thanks

I am sorry. I do not know any value that specifies as a ‘main’ camera when multiple are present. You can give the select camera function the criteria object specifying that it must be at least a certain resolution and other specs. That could at least give you a minimum ability camera. Otherwise your solution sounds good for how you want to approach it.

@apchandler Hi, Do you know if exists a way for selecting the 'main' back camera?
I have a website where my users wilI scan QR CODES using instascan. I amb developing the website and doing some tests I access to the website using my mobiIe phone which has 4 back cameras (HUAWEI P30 PRO).
I have tried the $.each and with the first back camera selected I can't scan anything because the vision is so fuzzy and with a lot of zoom.
But, if I select the cameras[2] I am able to scan everything.
Exists a generic way to select the 'main' back camera?
I mean, my webapp is going to be used by so many users with differents mobile phones, different number of cameras and the order of the cameras will be also different.
Or do you recommend to do a select with all the cameras and then let the user to pick up the one that works perfectly for him?
Thanks

I am sorry. I do not know any value that specifies as a ‘main’ camera when multiple are present. You can give the select camera function the criteria object specifying that it must be at least a certain resolution and other specs. That could at least give you a minimum ability camera. Otherwise your solution sounds good for how you want to approach it.

Thanks a lot for you answer! I will try with the resolution. Instascan can return the resolution of a camerA?

According to the methods provided by @glorynguyen and @apchandler.
Can now turn on the rear camera
Modify instascan.min
Before
case 0:return i={audio:!1,video:{mandatory:{sourceId:this.id,minWidth:600,maxWidth:800,minAspectRatio:1.6},optional:[]}}
After
case 0:return i=(/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream)?{audio:!1,video:{facingMode:{exact:"environment"},mandatory:{sourceId:this.id,minWidth:600,maxWidth:800,minAspectRatio:1.6},optional:[]}}:{audio:!1,video:{mandatory:{sourceId:this.id,minWidth:600,maxWidth:800,minAspectRatio:1.6},optional:[]}}

Has anyone figured out how to use the back camera with Safari on iOS 12+?

I have been using a modified version of this library for about 7 months now on over 30+ types ios and android phones and tablets. Look at the comments I left above about a modified version to get any camera from the os you are working with. The comments keep talking about adding the webrtc after, which i found to be the whole issue of this library.

I removed webrtc from the project altogether and recompiled it. webrtc is not needed any more with this code when transpiled to es5 or above. The use of webrtc in the library and how it was coded did not allow the correct camera to be retrieved.

I have included the fixed and transpiled regular and minified js files that I have been using for a while now. I use it for school attendance with QrCodes across any phones students and teachers have, which have been about 30+ models at this point. It can grab any camera.

I hope this helps.

Back Camera code

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip

#182 (comment)

You sir has just saved the job of a junior dev, you have got yourself a lifetime fan.

Thanks. I was right where you were when I saw this code. Had a deadline and needed the cameras from 30 different types. I am glad they wrote this.

Running 15 months now with 45 different models of phones and only one hiccup on a Samsung phone that was fixed when Samsung patched it. So it was a Samsung WebKit error.

Hi,
I am also facing back camera issue with IOS like as other person. My back camera is not opening on iPhone, default front camera is running. Please help me if anyone have resolved this issue with updated version(13.xx. xx) of safari.

Has anyone figured out how to use the back camera with Safari on iOS 12+?

I have been using a modified version of this library for about 7 months now on over 30+ types ios and android phones and tablets. Look at the comments I left above about a modified version to get any camera from the os you are working with. The comments keep talking about adding the webrtc after, which i found to be the whole issue of this library.

I removed webrtc from the project altogether and recompiled it. webrtc is not needed any more with this code when transpiled to es5 or above. The use of webrtc in the library and how it was coded did not allow the correct camera to be retrieved.

I have included the fixed and transpiled regular and minified js files that I have been using for a while now. I use it for school attendance with QrCodes across any phones students and teachers have, which have been about 30+ models at this point. It can grab any camera.

I hope this helps.

Back Camera code

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip

#182 (comment)

worked like a charm on both Android and iOS! I just downloaded the original instascan master branch, put your files into the "dist" folder, and that's it! thank you very much sir !

worked like a charm on both Android and iOS! I just downloaded the original instascan master branch, put your files into the "dist" folder, and that's it! thank you very much sir !

@antworks-hub did you use the whole code from the branch or the minified js?
where did you get the "dist" folder from?

worked like a charm on both Android and iOS! I just downloaded the original instascan master branch, put your files into the "dist" folder, and that's it! thank you very much sir !

@antworks-hub did you use the whole code from the branch or the minified js?
where did you get the "dist" folder from?

@Sandi2211 I guess I created a "dist" folder in the root of the original instascan master branch and put the content of the instasca,min.zip file into that folder.

Has anyone figured out how to use the back camera with Safari on iOS 12+?

I have been using a modified version of this library for about 7 months now on over 30+ types ios and android phones and tablets. Look at the comments I left above about a modified version to get any camera from the os you are working with. The comments keep talking about adding the webrtc after, which i found to be the whole issue of this library.
I removed webrtc from the project altogether and recompiled it. webrtc is not needed any more with this code when transpiled to es5 or above. The use of webrtc in the library and how it was coded did not allow the correct camera to be retrieved.
I have included the fixed and transpiled regular and minified js files that I have been using for a while now. I use it for school attendance with QrCodes across any phones students and teachers have, which have been about 30+ models at this point. It can grab any camera.
I hope this helps.
Back Camera code

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip
#182 (comment)

This solves my problem, thank you very much.

Thanks man, my is work well, just add your new js.

No problem. I am glad this is all still working here.

Has anyone figured out how to use the back camera with Safari on iOS 12+?

I have been using a modified version of this library for about 7 months now on over 30+ types ios and android phones and tablets. Look at the comments I left above about a modified version to get any camera from the os you are working with. The comments keep talking about adding the webrtc after, which i found to be the whole issue of this library.

I removed webrtc from the project altogether and recompiled it. webrtc is not needed any more with this code when transpiled to es5 or above. The use of webrtc in the library and how it was coded did not allow the correct camera to be retrieved.

I have included the fixed and transpiled regular and minified js files that I have been using for a while now. I use it for school attendance with QrCodes across any phones students and teachers have, which have been about 30+ models at this point. It can grab any camera.

I hope this helps.

Back Camera code

scanner = new Instascan.Scanner({ video: video, scanPeriod: 4, mirror:false })
                .then(handleSuccess)
                .catch(handleError);
             //Start scanning
             scanner.addListener('scan', foundCode);

             Instascan.Camera.getCameras().then(function (cameras) {
                 if (cameras.length > 0) {
                     scanner.start(cameras[0]);
                 }
                 else {
            ...        
                 }
             }).catch (function (e) {
              ...  
             });

instascan.min.zip

#182 (comment)

Tks, @apchandler11! You saved my work. god dms!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

desmond0412 picture desmond0412  ·  4Comments

jeroenbreen picture jeroenbreen  ·  7Comments

deadmanwalking74 picture deadmanwalking74  ·  7Comments

axed picture axed  ·  5Comments

werthdavid picture werthdavid  ·  5Comments