1

I'm trying out webAR demos using webrtc and threejs, while accessing the camera through my android mobile chrome:54 the front camera opens up by default.

I checked and tried to fix the issue by referring to all the questions regarding this on stack overflow, even tried to change the array values but no luck. Can anyone please tell me how to access the rear camera by tweaking this code?

    var THREEx = THREEx || {}


  navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
  window.URL = window.URL || window.webkitURL;

  /**
   * Grab camera
   */
  THREEx.WebcamGrabbing = function() {


    // create video element
    var domElement = document.createElement('video')
    domElement.setAttribute('autoplay', true)

    // window.domElement = video
    domElement.style.zIndex = -1;
    domElement.style.position = 'absolute'


    domElement.style.top = '0px'
    domElement.style.left = '0px'
    domElement.style.width = '100%'
    domElement.style.height = '100%'


    function onResize() {
      // is the size of the video available ?
      if (domElement.videoHeight === 0) return

      var videoAspect = domElement.videoWidth / domElement.videoHeight
      var windowAspect = window.innerWidth / window.innerHeight

    }

    window.addEventListener('resize', function(event) {
      onResize()
    })

    setInterval(function() {
      onResize()
    }, 500)

    // get the media sources
    navigator.mediaDevices.enumerateDevices().then(function(sourceInfos) {
      // define getUserMedia() constraints
      var constraints = {
          video: true,
          audio: false,
        }
        // to mirror the video element when it isnt 'environment'
        // domElement.style.transform   = 'scaleX(-1)'

      // it it finds the videoSource 'environment', modify constraints.video
      for (var i = 0; i != sourceInfos.length; ++i) {
        var sourceInfo = sourceInfos[i];
        if (sourceInfo.kind == "video" && sourceInfo.facing == "environment") {
          constraints.video = {
              optional: [{
                sourceId: sourceInfo.id
              }]
            }
            // not to mirror the video element when it is 'environment'
            // domElement.style.transform   = ''
        }
      }

      // try to get user media
      navigator.getUserMedia(constraints, function(stream) {
        domElement.src = URL.createObjectURL(stream);
      }, function(error) {
        console.error("Cant getUserMedia()! due to ", error);
      });
    });

    this.domElement = domElement
  }

I tried adding this into the constraints. Yet again the same result.

var constraints = {
                        video: {facingMode: { exact: "environment" }},
                        audio: false
                }
andy ram
  • 213
  • 3
  • 21

5 Answers5

3

Latest spac support "facingMode" in constraints. but, Chrome does not yet support a "facingMode". "sourceId" deprecated, latest spec "deviceId" insted of "sourceId". I wrote demo.

Tanaka Kenji
  • 397
  • 2
  • 9
1

Have you included adapter.js to polyfill? So you should be able to choose the default camera like this:

 facingMode: { exact: "environment" }
Polaris
  • 712
  • 7
  • 21
  • Thanks for the reply, can you please elaborate ? I just added the adapter.js file and the facingMode: { exact: "environment" } to my existing code [updated question] . i guess im wrong somewhere, the results seems to be same as before. – andy ram Nov 24 '16 at 09:37
  • with some research i found few suggesting the use adapter.js , can you please tell me how i can make use of it in this scenario ? – andy ram Nov 24 '16 at 12:10
  • Thats surprising, i could swear I had a proper working solution with the same constellation, but I've tested it today and now I'm also looking for a working solution. - Did you found a way, @andy ram? Enumerating the devices is working and you can use a variable with the back-device as value within the video constraints... – Polaris Nov 29 '16 at 17:56
0

In combination with adapterJS I have following Code:

Step1: Enumerating the devices

 navigator.mediaDevices.enumerateDevices()
   .then(gotDevices)
.catch(errorCallback);

var videodeviceId ;
var videolabel;
function gotDevices(deviceInfos) {
   var camcount = 1;   //used for labeling if the device label is not enumerated
   for (var i = 0; i !== deviceInfos.length; ++i) {
       if (deviceInfos[i].kind === 'videoinput') {
         videolabel=deviceInfos[i].label.split(' ')[1];
         //alert(deviceInfos[i].label + '//' +deviceInfos[i].deviceId);
         if (deviceInfos[i].label.match(/back/g) ||
             deviceInfos[i].label.match(/environment/g)) {
           videodeviceId= deviceInfos[i].deviceId;
         }
         else {
           videodeviceId= deviceInfos[i].deviceId;
         }
         camcount++;
       }
   }
}

It iterate through the found devices and saves the found devices which has "back" or "environment" in it.

Step2: The Constraints to set the resolution in Chrome (Excerp):

var options = {
     localMediaConstraints: {
         audio: false,
            video: {
           optional: [ // Try width step by step until maximum
               {sourceId: videodeviceId},
               {minWidth: 320},
               {minWidth: 640},
               {minWidth: 800},
               {minWidth: 1024},
               {minWidth: 1280},
               {minWidth: 1600},
               {minWidth: 1920},
               {minWidth: 2560}
           ],
       }
     },

This works so far, the back-camera is used and set in the sourceid (deprecated, I know) but if I stop the stream and change the participants resolution, it shows the front cam again. Thats weird, Firefox is quite easy to use...

Does anyone have a solution?

Polaris
  • 712
  • 7
  • 21
0

I tried few approaches but couldn't get an exact answer, that is accessing my rare camera by default. I tried an alternative where i coded a css popup modal to open up when the page opens so that i could choose either the front or back camera at the very begining.

However this is not a logical answer to my question but within less time it could solve my problem.

andy ram
  • 213
  • 3
  • 21
0

The correct one is not

for (var i = 0; i != sourceInfos.length; ++i) {
   constraints = {//};
}
navigator.getUserMedia(constraints, function(stream) {//});

but

for (var i = 0; i != sourceInfos.length; ++i) {
   constraints = {//};
   navigator.getUserMedia(constraints, function(stream) {//});
}

, I suppose.

And does not open both the front and back open at the same time

Would you please re-confirm it?

Community
  • 1
  • 1
Tanaka Kenji
  • 397
  • 2
  • 9