Cómo comenzar a usar dispositivos de medios

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>