En Google, luchamos por la equidad racial de la comunidad negra. Más información
Esta página se ha traducido con Cloud Translation API.
Switch to English

Comenzando con los dispositivos multimedia

Al desarrollar para la web, el estándar WebRTC proporciona API para acceder a cámaras y micrófonos conectados a la computadora o teléfono inteligente. Estos dispositivos se conocen comúnmente como dispositivos de medios y se puede acceder con JavaScript a través del objeto navigator.mediaDevices , que implementa la interfaz MediaDevices . Desde este objeto podemos enumerar todos los dispositivos conectados, escuchar los cambios del dispositivo (cuando un dispositivo está conectado o desconectado) y abrir un dispositivo para recuperar un flujo de medios (ver más abajo).

La forma más común de usar esto es a través de la función getUserMedia() , que devuelve una promesa que se resolverá en MediaStream para los dispositivos de medios correspondientes. Esta función toma un solo objeto MediaStreamConstraints que especifica los requisitos que tenemos. Por ejemplo, para abrir simplemente el micrófono y la cámara predeterminados, haríamos lo siguiente.

Usando 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);
    });
 

Usando 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 contiene un video y una pista de audio. Si se deniega el permiso, se lanza un PermissionDeniedError . En caso de que no haya dispositivos coincidentes conectados, se NotFoundError un NotFoundError .

La referencia completa de la API para la interfaz MediaDevices está disponible en los documentos web de MDN .

Consultar dispositivos de medios

En una aplicación más compleja, lo más probable es que queramos verificar todas las cámaras y micrófonos conectados y brindarle los comentarios apropiados al usuario. Esto se puede hacer llamando a la función enumerateDevices() . Esto devolverá una promesa que se resuelve en una matriz de MediaDevicesInfo que describe cada dispositivo de medios conocido. Podemos usar esto para presentar una IU al usuario que les permita elegir la que prefieran. Cada MediaDevicesInfo contiene una propiedad denominada kind con el valor audioinput , audiooutput o videoinput , que indica qué tipo de dispositivo multimedia es.

Usando 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));
 

Usando 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);
 

Escuchar los cambios de dispositivos

La mayoría de las computadoras admiten enchufar varios dispositivos durante el tiempo de ejecución. Podría ser una cámara web conectada por USB, auriculares Bluetooth o un conjunto de altavoces externos. Para admitir esto correctamente, una aplicación web debe escuchar los cambios de los dispositivos multimedia. Esto se puede hacer agregando un oyente a navigator.mediaDevices para el evento de cambio de 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);
});
 

Limitaciones de los medios

El objeto de restricciones, que debe implementar la interfaz MediaStreamConstraints , que pasamos como parámetro a getUserMedia() nos permite abrir un dispositivo de medios que getUserMedia() un determinado requisito. Este requisito puede estar muy poco definido (audio y / o video) o muy específico (resolución mínima de la cámara o una identificación exacta del dispositivo). Se recomienda que las aplicaciones que usan la API getUserMedia() primero verifiquen los dispositivos existentes y luego especifiquen una restricción que coincida con el dispositivo exacto usando la restricción deviceId . Los dispositivos también, si es posible, se configurarán de acuerdo con las restricciones. Podemos habilitar la cancelación de eco en los micrófonos o establecer un ancho y una altura específica o mínima 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);
}
 

La documentación completa de la interfaz MediaStreamConstraints se puede encontrar en los documentos web de MDN .

Reproducción local

Una vez que se ha abierto un dispositivo de medios y tenemos un MediaStream disponible, podemos asignarlo a un elemento de video o audio para reproducir la transmisión localmente.

 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 utilizado con getUserMedia() generalmente tendrá los atributos autoplay y autoplay playsinline . El atributo de autoplay hará que las nuevas transmisiones asignadas al elemento se reproduzcan automáticamente. El atributo playsinline permite que el video se reproduzca en línea, en lugar de solo en pantalla completa, en ciertos navegadores móviles. También se recomienda usar los controls="false" para las transmisiones en vivo, a menos que el usuario pueda pausarlos.

 <html>
<head><title>Local video playback</video></head>
<body>
    <video id="localVideo" autoplay playsinline controls="false"/>
</body>
</html>