Muchos navegadores ahora pueden acceder a la entrada de audio y video del usuario. Sin embargo, según el navegador, puede ser una experiencia dinámica y intercalada completa, o bien puede delegarse a otra app en el dispositivo del usuario.
Comienza de forma simple y progresiva
Lo más sencillo es pedirle al usuario un archivo grabado previamente. Para ello, crea un elemento de entrada de archivo simple y agrega un filtro accept
que indique que solo podemos aceptar archivos de video y un atributo capture
que indique que queremos obtenerlo directamente de la cámara.
<input type="file" accept="video/*" capture />
Este método funciona en todas las plataformas. En computadoras de escritorio, se le pedirá al usuario que suba un archivo del sistema de archivos (sin tener en cuenta el atributo capture
). En Safari para iOS, se abrirá la app de la cámara, lo que te permitirá grabar un video y, luego, enviarlo a la página web. En Android, se le dará al usuario la opción de elegir en qué app grabar el video antes de enviarlo a la página web.
Muchos dispositivos móviles tienen más de una cámara. Si tienes una preferencia, puedes establecer el atributo capture
en user
si quieres que la cámara esté orientada hacia el usuario o en environment
si quieres que esté orientada hacia afuera.
<input type="file" accept="video/*" capture="user" />
<input type="file" accept="video/*" capture="environment" />
Ten en cuenta que esta es solo una sugerencia. Si el navegador no admite la opción o el tipo de cámara que solicitas no está disponible, es posible que el navegador elija otra cámara.
Una vez que el usuario termine de grabar y vuelva al sitio web, necesitarás obtener los datos del archivo de alguna manera. Para obtener acceso rápido, puedes
vincular un evento onchange
al elemento de entrada y, luego, leer
la propiedad files
del objeto del evento.
<input type="file" accept="video/*" capture="camera" id="recorder" />
<video id="player" controls></video>
<script>
var recorder = document.getElementById('recorder');
var player = document.getElementById('player');
recorder.addEventListener('change', function (e) {
var file = e.target.files[0];
// Do something with the video file.
player.src = URL.createObjectURL(file);
});
</script>
Una vez que tengas acceso al archivo, podrás hacer lo que quieras con él. Por ejemplo, puedes hacer lo siguiente:
- Adjúntalo directamente a un elemento
<video>
para que puedas reproducirlo. - Descargarlo en el dispositivo del usuario
- Sube el archivo a un servidor conectándolo a un
XMLHttpRequest
. - Dibuja los marcos en un lienzo y aplícale filtros
Si bien el uso del método de elemento de entrada para obtener acceso a los datos de video es omnipresente, es la opción menos atractiva. Queremos obtener acceso a la cámara y brindar una experiencia agradable directamente en la página.
Accede a la cámara de forma interactiva
Los navegadores modernos pueden tener una línea directa con la cámara, lo que nos permite crear experiencias que están completamente integradas en la página web y el usuario nunca abandonará el navegador.
Adquirir acceso a la cámara
Podemos acceder directamente a la cámara con una API en la especificación de WebRTC llamada getUserMedia()
. getUserMedia()
le solicitará al usuario acceso a sus micrófonos y cámaras conectados.
Si se realiza correctamente, la API mostrará un Stream
que contendrá los datos de la cámara o el micrófono, y luego podremos adjuntarlo a un elemento <video>
, a una transmisión de WebRTC o guardarlo con la API de MediaRecorder
.
Para obtener datos de la cámara, solo configuramos video: true
en el objeto de restricciones que se pasa a la API de getUserMedia()
.
<video id="player" controls></video>
<script>
var player = document.getElementById('player');
var handleSuccess = function (stream) {
player.srcObject = stream;
};
navigator.mediaDevices
.getUserMedia({audio: true, video: true})
.then(handleSuccess);
</script>
Si quieres elegir una cámara en particular, primero puedes enumerar las cámaras disponibles.
navigator.mediaDevices.enumerateDevices().then((devices) => {
devices = devices.filter((d) => d.kind === 'videoinput');
});
Luego, puedes pasar el deviceId que deseas usar cuando llames a getUserMedia
.
navigator.mediaDevices.getUserMedia({
audio: true,
video: {
deviceId: devices[0].deviceId,
},
});
Por sí solo, esto no es muy útil. Todo lo que podemos hacer es tomar los datos de video y reproducirlos.
Accede a los datos sin procesar de la cámara
Para acceder a los datos de video sin procesar de la cámara, puedes dibujar cada fotograma en un <canvas>
y manipular los píxeles directamente.
Para un lienzo 2D, puedes usar el método drawImage
del contexto para dibujar el marco actual de un elemento <video>
en el lienzo.
context.drawImage(myVideoElement, 0, 0);
Con un lienzo WebGL, puedes usar un elemento <video>
como fuente de una textura.
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
gl.RGBA,
gl.UNSIGNED_BYTE,
myVideoElement,
);
Ten en cuenta que, en cualquier caso, se usará el fotograma actual de un video que se esté reproduciendo. Para procesar varios fotogramas, debes volver a dibujar el video en el lienzo cada vez.
Puedes obtener más información sobre esto en nuestro artículo sobre cómo aplicar efectos en tiempo real a imágenes y videos.
Guarda los datos de la cámara
La forma más fácil de guardar los datos de la cámara es usar la API de MediaRecorder
.
La API de MediaRecorder
tomará la transmisión creada por getUserMedia
y, luego, guardará de forma progresiva los datos de la transmisión en tu destino preferido.
<a id="download">Download</a>
<button id="stop">Stop</button>
<script>
let shouldStop = false;
let stopped = false;
const downloadLink = document.getElementById('download');
const stopButton = document.getElementById('stop');
stopButton.addEventListener('click', function() {
shouldStop = true;
})
var handleSuccess = function(stream) {
const options = {mimeType: 'video/webm'};
const recordedChunks = [];
const mediaRecorder = new MediaRecorder(stream, options);
mediaRecorder.addEventListener('dataavailable', function(e) {
if (e.data.size > 0) {
recordedChunks.push(e.data);
}
if(shouldStop === true && stopped === false) {
mediaRecorder.stop();
stopped = true;
}
});
mediaRecorder.addEventListener('stop', function() {
downloadLink.href = URL.createObjectURL(new Blob(recordedChunks));
downloadLink.download = 'acetest.webm';
});
mediaRecorder.start();
};
navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then(handleSuccess);
</script>
En nuestro caso, guardamos los datos directamente en un array que luego podemos convertir en un Blob
, que se puede usar para guardar en nuestro servidor web o directamente en el almacenamiento del dispositivo del usuario.
Solicita permiso para usar la cámara con responsabilidad
Si el usuario no le otorgó acceso a la cámara a tu sitio anteriormente, en el momento en que llames a getUserMedia
, el navegador le pedirá al usuario que le otorgue permiso a tu sitio para usar la cámara.
A los usuarios no les gusta que se les solicite acceso a dispositivos potentes en su máquina y, a menudo, bloquean la solicitud o la ignoran si no comprenden el contexto en el que se creó la solicitud. Se recomienda solo solicitar acceso a la cámara cuando sea necesario por primera vez. Una vez que el usuario otorgue el acceso, no se le volverá a preguntar. Sin embargo, si rechaza el acceso, no podrás volver a obtener acceso para solicitarle permiso.
Usa la API de permisos para verificar si ya tienes acceso
La API de getUserMedia
no te informa si ya tienes acceso a la cámara. Esto te presenta un problema. Para proporcionar una IU agradable que le permita al usuario otorgarte acceso a la cámara, debes solicitarle acceso a la cámara.
Esto se puede resolver en algunos navegadores con la API de Permission. La API de navigator.permission
te permite consultar el estado de la capacidad de acceder a APIs específicas sin tener que volver a solicitarlo.
Para consultar si tienes acceso a la cámara del usuario, puedes pasar {name: 'camera'}
al método de consulta, y se mostrará una de las siguientes opciones:
granted
: El usuario te otorgó acceso a la cámara anteriormente.prompt
: El usuario no te otorgó acceso y se le pedirá cuando llames agetUserMedia
.denied
: El sistema o el usuario bloquearon de forma explícita el acceso a la cámara y no podrás acceder a ella.
Ahora puedes verificar rápidamente si necesitas alterar la interfaz de usuario para adaptarla a las acciones que el usuario debe realizar.
navigator.permissions.query({name: 'camera'}).then(function (result) {
if (result.state == 'granted') {
} else if (result.state == 'prompt') {
} else if (result.state == 'denied') {
}
result.onchange = function () {};
});