O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

Introdução aos 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. Esses dispositivos são geralmente chamados de dispositivos de mídia e podem ser acessados ​​com JavaScript por meio do objeto navigator.mediaDevices , que implementa a interface MediaDevices . A partir desse objeto, podemos enumerar todos os dispositivos conectados, ouvir alterações no dispositivo (quando um dispositivo está conectado ou desconectado) e abrir um dispositivo para recuperar um fluxo de mídia (veja abaixo).

A maneira mais comum de usar isso é através da função getUserMedia() , que retorna uma promessa que será resolvida para um MediaStream para os dispositivos de mídia correspondentes. Essa função usa um único objeto MediaStreamConstraints 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 / waitit

 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() acionará uma solicitação de permissão. Se o usuário aceitar a permissão, a promessa será resolvida com um MediaStream contendo um vídeo e uma trilha de áudio. Se a permissão for negada, um PermissionDeniedError será lançado. Caso não haja dispositivos correspondentes conectados, um NotFoundError será lançado.

A referência completa da API para a interface MediaDevices está disponível nos documentos da web do MDN .

Consultando dispositivos de mídia

Em uma aplicação mais complexa, provavelmente quereremos 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 retornará uma promessa que é resolvida para uma matriz de MediaDevicesInfo que descreve cada dispositivo de mídia conhecido. Podemos usar isso para apresentar uma interface do usuário ao usuário, permitindo que ele escolha a que preferir. Cada MediaDevicesInfo contém uma propriedade chamada kind com o valor audioinput , audiooutput ou videoinput , indicando que tipo de dispositivo de mídia é.

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 / waitit

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

Escutando alterações 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 dar suporte adequado a isso, um aplicativo Web deve ouvir as alterações dos dispositivos de mídia. Isso pode ser feito adicionando um ouvinte a navigator.mediaDevices para o 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);
});
 

Restrições de mídia

O objeto de restrições, que deve implementar a interface MediaStreamConstraints , que passamos como parâmetro para getUserMedia() permite abrir um dispositivo de mídia que atenda a um determinado requisito. Esse requisito pode ser muito pouco definido (áudio e / ou vídeo) ou muito específico (resolução mínima da câmera ou um ID exato do dispositivo). É recomendável que os aplicativos que usam a API getUserMedia() primeiro verifiquem os dispositivos existentes e especifique uma restrição que corresponda ao dispositivo exato usando a restrição deviceId . Os dispositivos também serão configurados, se possível, de acordo com as restrições. Podemos ativar o cancelamento de eco em microfones ou definir uma largura e altura específica ou mínima do vídeo a partir 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 da interface MediaStreamConstraints pode ser encontrada nos documentos da web da MDN .

Reprodução local

Depois que um dispositivo de mídia é aberto e temos um MediaStream disponível, podemos atribuí-lo a um elemento de vídeo ou á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() geralmente terá os atributos autoplay e autoplay playsinline . O atributo de autoplay fará com que novos fluxos atribuídos ao elemento sejam reproduzidos automaticamente. O atributo playsinline permite que o vídeo seja reproduzido inline, em vez de apenas em tela cheia, em determinados navegadores móveis. Também é recomendável usar controls="false" para transmissões ao vivo, a menos que o usuário possa pausá-las.

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