O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Primeiros passos com dispositivos de mídia

Ao desenvolver para a web, o padrão WebRTC fornece APIs para acessar câmeras e microfones conectados ao computador ou smartphone. Estes dispositivos são comumente referidos como dispositivos de mídia e pode ser acessado com JavaScript através do navigator.mediaDevices objeto, que implementa o MediaDevices interface. A partir deste objeto, podemos enumerar todos os dispositivos conectados, ouvir as alterações do dispositivo (quando um dispositivo é conectado ou desconectado) e abrir um dispositivo para recuperar um Media Stream (veja abaixo).

A forma mais comum este é utilizado é através da função getUserMedia() , que retorna uma promessa de que irá resolver a um MediaStream para os dispositivos de mídia correspondentes. Esta função recebe um único MediaStreamConstraints objeto que especifica os requisitos que temos. Por exemplo, para simplesmente abrir o microfone e a câmera padrão, faríamos o seguinte.

Usando Promessas

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

A chamada para getUserMedia() irá desencadear um pedido de permissões. Se o usuário aceitar a permissão, a promessa é resolvido com um MediaStream contendo um vídeo e uma faixa de áudio. Se a permissão for negada, a PermissionDeniedError é lançada. No caso, não há dispositivos correspondentes conectado, uma NotFoundError será lançada.

A referência API completa para o MediaDevices de interface está disponível em docs web MDN .

Consultando dispositivos de mídia

Em um aplicativo mais complexo, provavelmente desejaremos verificar todas as câmeras e microfones conectados e fornecer o feedback apropriado ao usuário. Isso pode ser feito chamando a função enumerateDevices() . Isso irá retornar uma promessa que resolve uma série de MediaDevicesInfo que descrevem cada dispositivo de mídia conhecida. Podemos usar isso para apresentar uma IU ao usuário, permitindo que ele escolha a que preferir. Cada MediaDevicesInfo contém uma propriedade denominada kind com o valor audioinput , audiooutput ou videoinput , indicando que tipo de dispositivo de mídia que é.

Usando Promessas

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

Ouvindo mudanças de dispositivos

A maioria dos computadores suporta a conexão de vários dispositivos durante o tempo de execução. Pode ser uma webcam conectada por USB, um fone de ouvido Bluetooth ou um conjunto de alto-falantes externos. Para oferecer suporte adequado a isso, um aplicativo da web deve ouvir as alterações dos dispositivos de mídia. Isso pode ser feito adicionando um ouvinte para navigator.mediaDevices para o devicechange evento.

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

Restrições de mídia

As restrições objeto, que deve implementar a MediaStreamConstraints interface, que passamos como parâmetro para getUserMedia() nos permite abrir um dispositivo de mídia que corresponde a um determinado requisito. Este requisito pode ser definido de forma muito vaga (áudio e / ou vídeo) ou muito específico (resolução mínima da câmera ou uma ID exata do dispositivo). Recomenda-se que as aplicações que utilizam o getUserMedia() API verifique primeiro os dispositivos existentes e, em seguida, especifica uma restrição que corresponde ao dispositivo exata usando o deviceId restrição. Os dispositivos também serão, se possível, configurados de acordo com as restrições. Podemos habilitar o cancelamento de eco em microfones ou definir uma largura e altura específicas ou mínimas do vídeo da câmera.

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

A documentação completa para o MediaStreamConstraints interface pode ser encontrada nos documentos web MDN .

Reprodução local

Uma vez que um dispositivo de mídia foi aberto e temos um MediaStream disponíveis, podemos atribuí-la a um vídeo ou elemento de áudio para reproduzir o fluxo 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);
    }
}

O HTML necessário para um elemento de vídeo típico usado com getUserMedia() normalmente terão os atributos autoplay e playsinline . O autoplay atributo fará com que novos fluxos atribuídas ao elemento a tocar automaticamente. O playsinline atributo permite vídeo para jogar em linha, em vez de apenas em tela cheia, em determinados navegadores móveis. Também é recomendado o uso de controls="false" para transmissões ao vivo, a menos que o usuário deve ser capaz de fazer uma pausa-los.

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