javascript - GetUserMedia-modo de cara
(6)
Al implementar nuestra aplicación web en Android a través de Cordova, probé varias soluciones para acceder a la cámara trasera. La solución que funcionó para mí fue:
constraints = {
audio: false,
video: {
width: 400,
height: 300,
deviceId: deviceId ? {exact: deviceId} : undefined
}
};
Recuperando el ID de dispositivo a través de:
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
// devices is an array of accessible audio and video inputs. deviceId is the property I used to switch cameras
})
.catch(function(err) {
console.log(err.name + ": " + error.message);
});
Elegí no usar un complemento de Cordova para que si decidimos alejarnos de Cordova, no habría una migración tan fuerte.
Actualmente estoy usando una tableta Android y GetUserMedia para tomar fotos en mi programa.
Aparentemente, la cámara predeterminada utilizada por GetUserMedia es la cámara frontal. ¿Cómo uso la cámara trasera como predeterminada?
Aquí está mi código para GetUserMedia:
navigator.getUserMedia({
"audio": false,
"video": {
mandatory: {
minWidth: this.params.dest_width,
minHeight: this.params.dest_height,
//facingMode: "environment",
},
}
},
function(stream) {
// got access, attach stream to video
video.src = window.URL.createObjectURL( stream ) || stream;
Webcam.stream = stream;
Webcam.loaded = true;
Webcam.live = true;
Webcam.dispatch(''load'');
Webcam.dispatch(''live'');
Webcam.flip();
},
function(err) {
return self.dispatch(''error'', "Could not access webcam.");
});
Inserté faceMode en la parte "obligatoria" pero no funcionó.
Por favor ayuda.
En la versión más reciente de Chrome (después de v52), las soluciones adaper.js parecen no funcionar. Así que resuelvo el problema enumerando primero los dispositivos. Aquí está mi solución. No estoy seguro de si hay una mejor manera de voltear la cámara y mostrar el video en la pantalla. Pero primero tengo que detener la pista y obtener una nueva transmisión.
let Video = function() {
let cameras = [];
let currCameraIndex = 0;
let constraints = {
audio: true,
video: {
deviceId: { exact: "" }
}
};
let videoCanvas = $(''video#gum'');
this.initialize = function() {
return enumerateDevices()
.then(startVideo);
};
this.flipCamera = function() {
currCameraIndex += 1;
if (currCameraIndex >= cameras.length) {
currCameraIndex = 0;
}
if (window.stream) {
window.stream.getVideoTracks()[0].stop();
}
return startVideo();
};
function enumerateDevices() {
return navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
devices.forEach(function(device) {
console.log(device);
if (device.kind === "videoinput") {
cameras.push(device.deviceId);
}
});
console.log(cameras);
});
}
function startVideo() {
constraints.video.deviceId.exact = cameras[currCameraIndex];
return navigator.mediaDevices.getUserMedia(constraints)
.then(handleSuccess).catch(handleError);
}
function handleSuccess(stream) {
videoCanvas[0].srcObject = stream;
window.stream = stream;
}
function handleError(error) {
alert(error);
}
};
Un fragmento bastante elegante que puedes usar es:
var front = false;
document.getElementById(''flip-button'').onclick = function() { front =` !front; };
var constraints = { video: { facingMode: (front? "user" : "environment") } };
Esto debería funcionar para usted con suerte.
Usando el código de Peter ( https://.com/a/41618462/7723861 ) se me ocurrió esta solución para obtener la cámara trasera:
function handleSuccess(stream) {
window.stream = stream; // make stream available to browser console
video.srcObject = stream;
}
function handleError(error) {
console.log(''navigator.getUserMedia error: '', error);
}
var DEVICES = [];
var final = null;
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
var arrayLength = devices.length;
for (var i = 0; i < arrayLength; i++)
{
var tempDevice = devices[i];
//FOR EACH DEVICE, PUSH TO DEVICES LIST THOSE OF KIND VIDEOINPUT (cameras)
//AND IF THE CAMERA HAS THE RIGHT FACEMODE ASSING IT TO "final"
if (tempDevice.kind == "videoinput")
{
DEVICES.push(tempDevice);
if(tempDevice.facingMode == "environment" ||tempDevice.label.indexOf("facing back")>=0 )
{final = tempDevice;}
}
}
var totalCameras = DEVICES.length;
//If couldnt find a suitable camera, pick the last one... you can change to what works for you
if(final == null)
{
//console.log("no suitable camera, getting the last one");
final = DEVICES[totalCameras-1];
};
//Set the constraints and call getUserMedia
var constraints = {
audio: false,
video: {
deviceId: {exact: final.deviceId}
}
};
navigator.mediaDevices.getUserMedia(constraints).
then(handleSuccess).catch(handleError);
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
});
Actualización:
facingMode
ahora está disponible en Chrome para Android a través del polyfill
adapter.js
.
facingMode
aún no
está
implementado en Chrome para Android
, pero funciona de forma nativa en Firefox para Android.
Sin embargo, debe usar restricciones standard : (use https fiddle para Chrome):
var gum = mode =>
navigator.mediaDevices.getUserMedia({video: {facingMode: {exact: mode}}})
.then(stream => (video.srcObject = stream))
.catch(e => log(e));
var stop = () => video.srcObject && video.srcObject.getTracks().forEach(t => t.stop());
var log = msg => div.innerHTML += msg + "<br>";
<button onclick="stop();gum(''user'')">Front</button>
<button onclick="stop();gum(''environment'')">Back</button>
<div id="div"></div><br>
<video id="video" height="320" autoplay></video>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
La sintaxis
{ exact: }
significa que se requiere la restricción, y las cosas fallan si el usuario no tiene la cámara correcta.
Si lo deja fuera, entonces la restricción es opcional, lo que en Firefox para Android significa que solo cambia el valor predeterminado en el selector de cámara en la solicitud de permiso.
Esto funcionaría para la cámara trasera:
navigator.mediaDevices.getUserMedia({
video: {facingMode: "environment",
height:{<heightValueHere>},
width : {<widthValueHere>}
}
})
.then(function(stream){
window.stream = stream;
video.srcObject = stream;
})