Cuando se desarrolla contenido para la Web, el estándar WebRTC proporciona APIs para acceder
cámaras y micrófonos conectados a la computadora o el smartphone. Estos dispositivos
comúnmente se denominan dispositivos multimedia, y se puede acceder a ellos con JavaScript
a través del objeto navigator.mediaDevices
, que implementa la función MediaDevices
.
interfaz de usuario. Desde este objeto, podemos enumerar todos los dispositivos conectados, detectar
cambia el dispositivo (cuando un dispositivo está conectado o desconectado) y abre un dispositivo
para recuperar un flujo de contenido multimedia (consulta a continuación).
La forma más común en que se usa esto es a través de la función getUserMedia()
, que
Muestra una promesa que se resolverá en un MediaStream
para el contenido multimedia coincidente.
dispositivos. Esta función toma un solo objeto MediaStreamConstraints
que
especifica los requisitos que tenemos. Por ejemplo, para abrir el archivo
micrófono y cámara predeterminados, haremos lo siguiente.
Usa promesas
const constraints = {
'video': true,
'audio': true
}
navigator.mediaDevices.getUserMedia(constraints)
.then(stream => {
console.log('Got MediaStream:', stream);
})
.catch(error => {
console.error('Error accessing media devices.', error);
});
Cómo usar async/await
const openMediaDevices = async (constraints) => {
return await navigator.mediaDevices.getUserMedia(constraints);
}
try {
const stream = openMediaDevices({'video':true,'audio':true});
console.log('Got MediaStream:', stream);
} catch(error) {
console.error('Error accessing media devices.', error);
}
La llamada a getUserMedia()
activará una solicitud de permisos. Si el usuario
acepta el permiso, la promesa se resuelve con un MediaStream
que contiene
un video y una pista de audio. Si se deniega el permiso, se genera una
Se arroja PermissionDeniedError
. En caso de que no haya dispositivos que coincidan
conectado, se arrojará una NotFoundError
.
La referencia completa de la API para la interfaz MediaDevices
está disponible en página web de MDN
documentación.
Cómo hacer consultas en dispositivos de medios
En una aplicación más compleja, lo más probable es que debamos verificar todos los
cámaras y micrófonos conectados, y proporcionará los comentarios adecuados al
usuario. Para ello, se debe llamar a la función enumerateDevices()
. Si confirmas esta acción,
mostrar una promesa que se resuelve en un array de MediaDevicesInfo
que describe
cada dispositivo de medios conocido. Podemos usarlo para presentarle una IU al usuario,
que elijan la que prefieran. Cada MediaDevicesInfo
contiene una propiedad llamada
kind
con el valor audioinput
, audiooutput
o videoinput
, que indica
de qué tipo de dispositivo de medios es.
Usa promesas
function getConnectedDevices(type, callback) {
navigator.mediaDevices.enumerateDevices()
.then(devices => {
const filtered = devices.filter(device => device.kind === type);
callback(filtered);
});
}
getConnectedDevices('videoinput', cameras => console.log('Cameras found', cameras));
Cómo usar async/await
async function getConnectedDevices(type) {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter(device => device.kind === type)
}
const videoCameras = getConnectedDevices('videoinput');
console.log('Cameras found:', videoCameras);
Escuchando cambios en los dispositivos
La mayoría de las computadoras admiten la conexión de varios dispositivos durante el tiempo de ejecución. Podría ser un
cámara web conectada mediante USB, auriculares Bluetooth o un conjunto de bocinas externas. En
para admitir esto adecuadamente, una aplicación web debe escuchar los cambios
de dispositivos de medios. Esto se puede hacer agregando un objeto de escucha a
navigator.mediaDevices
para el evento devicechange
// Updates the select element with the provided set of cameras
function updateCameraList(cameras) {
const listElement = document.querySelector('select#availableCameras');
listElement.innerHTML = '';
cameras.map(camera => {
const cameraOption = document.createElement('option');
cameraOption.label = camera.label;
cameraOption.value = camera.deviceId;
}).forEach(cameraOption => listElement.add(cameraOption));
}
// Fetch an array of devices of a certain type
async function getConnectedDevices(type) {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter(device => device.kind === type)
}
// Get the initial set of cameras connected
const videoCameras = getConnectedDevices('videoinput');
updateCameraList(videoCameras);
// Listen for changes to media devices and update the list accordingly
navigator.mediaDevices.addEventListener('devicechange', event => {
const newCameraList = getConnectedDevices('video');
updateCameraList(newCameraList);
});
Restricciones de contenido multimedia
El objeto de restricciones, que debe implementar MediaStreamConstraints
.
interfaz de usuario que pasamos como parámetro a getUserMedia()
nos permite abrir una
que cumpla con un requisito determinado. Este requisito puede ser muy
definido de manera flexible (audio o video) o muy específica (cantidad mínima de cámara
resolución o un ID de dispositivo exacto). Se recomienda que las aplicaciones que usan
la API de getUserMedia()
primero verifica los dispositivos existentes y, luego, especifica un
que coincida con el dispositivo exacto que usa la restricción deviceId
.
Si es posible, los dispositivos también se configurarán de acuerdo con las restricciones. Mié
Puedes habilitar la cancelación del eco en los micrófonos o establecer un ancho específico o mínimo
y la altura del video desde la cámara.
async function getConnectedDevices(type) {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter(device => device.kind === type)
}
// Open camera with at least minWidth and minHeight capabilities
async function openCamera(cameraId, minWidth, minHeight) {
const constraints = {
'audio': {'echoCancellation': true},
'video': {
'deviceId': cameraId,
'width': {'min': minWidth},
'height': {'min': minHeight}
}
}
return await navigator.mediaDevices.getUserMedia(constraints);
}
const cameras = getConnectedDevices('videoinput');
if (cameras && cameras.length > 0) {
// Open first available video camera with a resolution of 1280x720 pixels
const stream = openCamera(cameras[0].deviceId, 1280, 720);
}
Puedes encontrar la documentación completa de la interfaz MediaStreamConstraints
en la Web de MDN
documentación.
Reproducción local
Una vez que se abrió un dispositivo de medios y tenemos un MediaStream
disponible,
puedes asignarlo a un elemento de audio o video para reproducir la transmisión de manera local.
async function playVideoFromCamera() {
try {
const constraints = {'video': true, 'audio': true};
const stream = await navigator.mediaDevices.getUserMedia(constraints);
const videoElement = document.querySelector('video#localVideo');
videoElement.srcObject = stream;
} catch(error) {
console.error('Error opening video camera.', error);
}
}
El HTML necesario para un elemento de video típico que se usa con getUserMedia()
generalmente tienen los atributos autoplay
y playsinline
. El autoplay
hará que se reproduzcan automáticamente las nuevas transmisiones asignadas al elemento.
El atributo playsinline
permite que el video se reproduzca de forma intercalada en lugar de solo por completo.
pantalla, en algunos navegadores móviles. También se recomienda usar
controls="false"
para las transmisiones en vivo, a menos que el usuario pueda pausarlas
de ellos.
<html>
<head><title>Local video playback</title></head>
<body>
<video id="localVideo" autoplay playsinline controls="false"/>
</body>
</html>