Muchos navegadores ahora tienen la capacidad de acceder a la entrada de video y audio del usuario. Sin embargo, según el navegador, puede ser una experiencia dinámica y directa completa, o bien se puede delegar a otra app en el dispositivo del usuario.
Comienza de forma sencilla y progresiva
Lo más fácil 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, se le solicitará al usuario que suba un archivo desde el sistema de archivos (se ignorará el atributo capture). En Safari para iOS, se abrirá la app de cámara, lo que te permitirá grabar un video y, luego, enviarlo de vuelta a la página web. En Android, el usuario podrá elegir qué app usar para grabar el video antes de enviarlo de vuelta 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 la cámara que mira al usuario o en environment si quieres la cámara que mira hacia afuera.
<input type="file" accept="video/*" capture="user" />
<input type="file" accept="video/*" capture="environment" />
Ten en cuenta que esto es solo una sugerencia: si el navegador no admite la opción o el tipo de cámara que solicitas no está disponible, el navegador puede elegir otra cámara.
Una vez que el usuario haya terminado de grabar y vuelva al sitio web, deberás obtener los datos del archivo de alguna manera. Puedes obtener acceso rápido adjuntando un evento onchange al elemento de entrada y, luego, leyendo la propiedad files del objeto de 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:
- Adjuntarlo directamente a un elemento
<video>para que puedas reproducirlo - Descárgala en el dispositivo del usuario.
- Súbelo a un servidor adjuntándolo a un
XMLHttpRequest. - Dibuja los fotogramas en un lienzo y aplícales 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 proporcionar 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 a la cámara, lo que nos permite crear experiencias que se integran por completo con la página web y el usuario nunca abandonará el navegador.
Obtén 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 devolverá un Stream que contendrá los datos de la cámara o
el micrófono, y podremos adjuntarlo a un elemento <video>, a un flujo 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 quieras usar cuando llames a getUserMedia.
navigator.mediaDevices.getUserMedia({
audio: true,
video: {
deviceId: devices[0].deviceId,
},
});
Por sí solo, esto no es tan útil. Lo único que podemos hacer es tomar los datos del 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 en 2D, puedes usar el método drawImage del contexto para dibujar el fotograma actual de un elemento <video> en el lienzo.
context.drawImage(myVideoElement, 0, 0);
Con un lienzo de WebGL, puedes usar un elemento <video> como fuente para 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 en reproducción. 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 sencilla de guardar los datos de la cámara es usar la API de MediaRecorder.
La API de MediaRecorder tomará el flujo creado por getUserMedia y, luego,
guardará de forma progresiva los datos del flujo en el destino que prefieras.
<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 de forma responsable
Si el usuario no otorgó previamente acceso a la cámara a tu sitio, en el momento en que llames a getUserMedia, el navegador le solicitará al usuario que otorgue permiso a tu sitio para acceder a la cámara.
A los usuarios no les gusta que se les solicite acceso a dispositivos potentes en su máquina y, con frecuencia, bloquearán la solicitud o la ignorarán si no comprenden el contexto en el que se creó la solicitud. Se recomienda solicitar acceso a la cámara solo cuando sea necesario por primera vez. Una vez que el usuario haya otorgado el acceso, no se le volverá a preguntar. Sin embargo, si rechaza el acceso, no podrás volver a solicitarle permiso.
Usa la API de Permissions para verificar si ya tienes acceso
La API de getUserMedia no te proporciona información sobre si ya tienes acceso a la cámara. Esto te presenta un problema: para proporcionar una IU agradable que permita que el usuario te otorgue acceso a la cámara, debes solicitar 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, que devolverá uno de los siguientes valores:
granted: El usuario ya te otorgó acceso a la cámara.prompt: El usuario no te otorgó acceso y se le solicitará 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 modificar tu 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 () {};
});