最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - HTML userMedia facingMode: "environment"doesn't work on android phone - Stack Overflow

programmeradmin3浏览0评论

It keeps using the front facing camera instead of the back camera This is my code: I added the facingMode: {exact:"environment"}, but it doesn't work

const constraints = {
    video: true,
    facingMode: { exact: 'environment' }
};

if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {
    console.log("Let's get this party started")
}
navigator.mediaDevices.getUserMedia(constraints).
then((stream) => {video.srcObject = stream});
function displayImage()
{
    const selectedFile = document.getElementById('fileinput')
    //var image =document.getElementById('output')
    //image.src = URL.createObjectURL(selectedFile.files[0]);
    //selectedFile.files[0]
    const img = new Image()
    img.src = URL.createObjectURL(selectedFile.files[0])
    canvas.width = video.videoWidth
    canvas.height = video.videoHeight
    video.style.display="none"
    canvas.style.display ="inline"
    console.log(img)
    console.log("image uploaded")

    img.onload = function() {
        canvas.getContext('2d').drawImage(img, 0, 0,video.videoWidth,video.videoHeight);
        console.log('the image is drawn');
    }

}

It keeps using the front facing camera instead of the back camera This is my code: I added the facingMode: {exact:"environment"}, but it doesn't work

const constraints = {
    video: true,
    facingMode: { exact: 'environment' }
};

if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {
    console.log("Let's get this party started")
}
navigator.mediaDevices.getUserMedia(constraints).
then((stream) => {video.srcObject = stream});
function displayImage()
{
    const selectedFile = document.getElementById('fileinput')
    //var image =document.getElementById('output')
    //image.src = URL.createObjectURL(selectedFile.files[0]);
    //selectedFile.files[0]
    const img = new Image()
    img.src = URL.createObjectURL(selectedFile.files[0])
    canvas.width = video.videoWidth
    canvas.height = video.videoHeight
    video.style.display="none"
    canvas.style.display ="inline"
    console.log(img)
    console.log("image uploaded")

    img.onload = function() {
        canvas.getContext('2d').drawImage(img, 0, 0,video.videoWidth,video.videoHeight);
        console.log('the image is drawn');
    }

}
Share Improve this question edited Oct 27, 2020 at 12:14 Sayd Fuad 3242 silver badges14 bronze badges asked Oct 27, 2020 at 11:07 Wannes Van der PerrenWannes Van der Perren 611 gold badge1 silver badge7 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 5

Your constraints are not set correctly.

facingMode is a member of the video constraint, so it should be

const constraints = {
  video: {
    facingMode: {
      exact: "environment"
    }
  }
};

Live Fiddle to be ran from a device with a back camera.

The facingMode constraint is inpletely implemented, especially in mobile devices.

I have found that the label member of the device object contains the string back for an environment-facing camera and front for a user-facing camera in a wide range of mobile devices, android and iOS. (Sometimes those strings are partially in upper case.) So you could do something like this. It's a bit of a hairball pared to facingMode, but it works.

/* get user's permission to muck around with video devices */
const tempStream = await navigator.mediaDevices.getUserMedia({video:true})
const devices = navigator.mediaDevices.enumerateDevices()
let frontDeviceId
let backDeviceId
if (devices.length > 0) {
  /* defaults so all this will work on a desktop */
  frontDeviceId = devices[0].deviceId;
  backDeviceId = devices[0].deviceId;
}
/* look for front and back devices */
devices.forEach (device => {
  if( device.kind === 'videoinput' ) {
    if( device.label && device.label.length > 0 ) {
      if( device.label.toLowerCase().indexOf( 'back' ) >= 0 ) 
        backDeviceId = device.deviceId
      else if( device.label.toLowerCase().indexOf( 'front' ) >= 0 )
        frontDeviceId = device.deviceId
    }
  }
}
/* close the temp stream */
const tracks = tempStream.getTracks()
if( tracks ) 
  for( let t = 0; t < tracks.length; t++ ) tracks[t].stop()
/* open the device you want */
const constraints = {
  video: true,
  deviceId: {exact: backDeviceId }
}
const stream = navigator.mediaDevices.getUserMedia(constraints)

 

The best way for me is to use "ideal" so it will work both on a pc both on a phone:

const constraints = {
  video: {
    facingMode: {
      ideal: "environment"
    }
  }
};
btn.onclick = e => {
    navigator.mediaDevices.getUserMedia(constraints)
        .then((stream) => {video.srcObject = stream})
        .catch( console.error );
};

https://jsfiddle/Zibri/pk7en85u/

I don't know why this works for me, but supporting both desktop and phone conditions works if I also define width and height properties on the constraints:

      const constraints = {
        video: {
          width: { ideal: 4096 },
          height: { ideal: 2160 },
          facingMode: "environment",
        },
      }

Why this works? I have no idea, but on Chrome on iOS it does as well as Chrome on desktop.

What worked for me on Safari Iphone 6s (I think) was to pass the constraints directly to getUserMedia:

const mediaStream = await navigator.mediaDevices.getUserMedia(
    {
        video: { facingMode: { ideal: "environment" } },
        audio: false
    }
);
发布评论

评论列表(0)

  1. 暂无评论