1

I came across several questions on this subject. I'm trying to select the rear camera on an Android device running Chrome.

So, after some reading :

var selector = document.getElementById('video-source-selector');
navigator.mediaDevices.enumerateDevices()
  .then(function(devices) {
    var videoDevices = devices.map(function (item) {
      if(item.kind === 'videoinput'){
        return item;
      }
    }).filter(function( element ) {
       return element !== undefined;
    });
    var max = videoDevices.length;
    videoDevices.forEach(function(device, i) {
      var html = '';
      var div = document.createElement('div');
      if(i === max-1){ // last element reached
        html += '<option value="'+device.deviceId+'" selected>'+ device.label +'</option>';
      }
      else {
        html += '<option value="'+device.deviceId+'">'+ device.label +'</option>';
      }
      div.innerHTML = html;
      selector.appendChild(div.childNodes[0]);

      console.log(device.kind + ": " + device.label +
        " id = " + device.deviceId);
    });
  })
  .catch(function(err) {
    console.log(err.name + ": " + err.message);
  });
  selector.addEventListener("change", function(){
    console.log(selector.value); // Works as supposed : returns the ID of the selected device
  });

Then, as I'm using Three.js in this app, I'm binding this ID to Jerome Etienne three extension WebcamGrabbing (https://github.com/jeromeetienne/threex.webar):

var videoGrabbing = new THREEx.WebcamGrabbing(selector.value);

Then I had to modify THREEx.WebcamGrabbing class this way (I removed the irrelevant parts):

THREEx.WebcamGrabbing = function(sourceDeviceId){

    ...

    console.log('webcamgrabbing : ', sourceDeviceId); // returns the expected ID

    var constraints = {
            video: {
              optional: [{
                sourceId: sourceDeviceId
              }]
            }
    }


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


    ...
}

But still, Chrome on Android is still giving me the stream of the face camera, whatever device I select...

What do I miss?

EDIT : Based on this topic (GetUserMedia - facingmode), I came up with some logs to see what's happening here :

   var constraints = {
            audio: false,
            video: { facingMode: { exact: "environment" } }
    }

    console.log('Try to get stream with constraints:', constraints);

    navigator.getUserMedia( constraints, function(stream){
            var videoTracks = stream.getVideoTracks();

            console.log('Got stream with constraints:', constraints);  // Ok
            console.log('Using video device: ' + videoTracks[0].label);  // > Using video device: camera 0, facing back

            for(var i = 0; i < videoTracks.length; i++){
              console.log('Found video device with contraints : ', videoTracks[i].label); // Found video device with contraints :  camera 0, facing back
            }

            domElement.src = URL.createObjectURL(stream);
    }, function(error) {
            console.error("Cant getUserMedia()! due to ", error);
    });
Community
  • 1
  • 1
enguerranws
  • 8,087
  • 8
  • 49
  • 97
  • 1
    Possible duplicate of [GetUserMedia - facingmode](http://stackoverflow.com/questions/32086122/getusermedia-facingmode) – jib Jul 04 '16 at 18:06
  • @jib Also tried the way provided in this topic, but it keeps selecting the front cam. – enguerranws Jul 05 '16 at 08:59
  • Did you try the [fiddle](https://jsfiddle.net/j2oe36eL/) in the other answer? Worked in Chrome on my S4. - Also, your own logs suggest you got the back camera: `Using video device: camera 0, facing back`. – jib Jul 05 '16 at 12:27
  • It works well on my device too. That's why I don't see any reason that my code is still selecting the front cam, as I practically copy/pasted the fiddle? – enguerranws Jul 05 '16 at 12:38
  • The important bit in the other answer is that `facingMode` support in Chrome for Android is provided by the [adapter.js](https://github.com/webrtc/adapter) polyfill. Did you copy that? – jib Jul 05 '16 at 13:01
  • @jib Yes, I'm calling (for test purpose) `` – enguerranws Jul 05 '16 at 13:04
  • Then I don't know. All code shown looks correct. – jib Jul 05 '16 at 17:34

1 Answers1

0

An alternative way to select the back camera on chrome is to use the enumerateDevices method.

First get all the video input id's:

   navigator.mediaDevices.enumerateDevices().then(function(devices) {
     devices.forEach(function(device) {

  if(device.kind=="videoinput"){
     //If device is a video input add to array.
  }
});

Then the first element of the array will contain the id of the front camera, the second element will contain the id of the back camera.

Finally put the id of the camera that you want to use

 navigator.getUserMedia({audio: false, video:  { sourceId: VideoId } }, successCallback, errorCallback);
Akil
  • 719
  • 13
  • 23
  • I used that method in my first attempt (first code in the question): I got the right ID (back camera), but I got the stream of the front cam... – enguerranws Jul 15 '16 at 13:51
  • You have to make sure that only one camera stream is active, if the front camera stream is active, then you need to stop it before starting the rear camera. – Akil Jul 16 '16 at 05:02
  • Just a thought, you have made the video source id as optional, maybe you could try video: { sourceId: VideoId } It works for me on chrome on android. – Akil Jul 16 '16 at 05:10
  • Those two things could help me a lot. I will try it tomorrow and tell you. – enguerranws Jul 17 '16 at 14:47
  • I tried {sourceId: VideoId }, where `VideoId` is the good ID (`label` = "camera facing back"). Still the same, I just get the video stream from front cam... – enguerranws Jul 21 '16 at 13:26