Escolher câmeras, microfones e alto-falantes no app da Web

Os navegadores mais recentes permitem selecionar dispositivos de entrada e saída, incluindo câmeras, microfones e alto-falantes.

Exemplo:

  • Em um smartphone, selecione a câmera frontal ou traseira.
  • Em um laptop, escolha os alto-falantes internos ou um conectado por Bluetooth.
  • Para um chat por vídeo, escolha uma câmera ou um microfone interno ou externo.

Toda essa funcionalidade é exposta pelo objeto MediaDevices, que é retornado por navigator.mediaDevices.

MediaDevices tem dois métodos, ambos implementados no Chrome 47 no computador e no Android: enumerateDevices() e getUserMedia().

Seleção de um dispositivo de saída de áudio.

enumerateDevices()

Retorna uma promessa que concede acesso a uma matriz de objetos MediaDeviceInfo para os dispositivos disponíveis.

O método é semelhante a MediaStreamTrack.getSources(), mas, diferentemente desse método (que só foi implementado no Chrome), é compatível com os padrões e inclui dispositivos de saída de áudio. Você pode testar isso com as demonstrações abaixo.

Veja um código ligeiramente simplificado em uma das demonstrações:

navigator.mediaDevices.enumerateDevices()
    .then(gotDevices)
    .catch(errorCallback);
...
function gotDevices(deviceInfos) {

    ...

    for (var i = 0; i !== deviceInfos.length; ++i) {
    var deviceInfo = deviceInfos[i];
    var option = document.createElement('option');
    option.value = deviceInfo.deviceId;
    if (deviceInfo.kind === 'audioinput') {
        option.text = deviceInfo.label ||
        'Microphone ' + (audioInputSelect.length + 1);
        audioInputSelect.appendChild(option);
    } else if (deviceInfo.kind === 'audiooutput') {
        option.text = deviceInfo.label || 'Speaker ' +
        (audioOutputSelect.length + 1);
        audioOutputSelect.appendChild(option);
    } else if (deviceInfo.kind === 'videoinput') {
        option.text = deviceInfo.label || 'Camera ' +
        (videoSelect.length + 1);
        videoSelect.appendChild(option);
    }

    ...

}

Depois de recuperar os IDs de dispositivos disponíveis com enumerateDevices(), você pode usar setSinkId() (definido na API Audio Output Devices) para mudar o destino de saída de áudio de um elemento de vídeo ou áudio:

element.setSinkId(sinkId)
    .then(function() {
    console.log('Audio output device attached: ' + sinkId);
    })
    .catch(function(error) {
    // ...
    });

Esse método define o dispositivo de saída para o áudio do elemento. Depois que setSinkId() for chamado, será possível receber o ID do dispositivo de áudio de saída atual para o elemento com a propriedade sinkId.

getUserMedia()

Isso substitui navigator.getUserMedia(), mas, em vez de usar um callback, retorna uma promessa que fornece acesso a um MediaStream. Os desenvolvedores são incentivados a usar MediaDevices.getUserMedia(), mas não há planos de remover navigator.getUserMedia(): ele continua fazendo parte da especificação.

Há uma demonstração no site de exemplos de WebRTC (em inglês).

Veja um fragmento de código da demonstração:

navigator.mediaDevices.getUserMedia(constraints)
    .then(function(stream) {
    var videoTracks = stream.getVideoTracks();
    console.log('Got stream with constraints:', constraints);
    console.log('Using video device: ' + videoTracks[0].label);
    stream.onended = function() {
        console.log('Stream ended');
    };
    window.stream = stream; // make variable available to console
    video.srcObject = stream;
    })
    .catch(function(error) {
    // ...
    }

Sem bandeira

O método enumerateDevices() não tem sinalização no Chrome, mas, para MediaDevices.getUserMedia(), você ainda precisa ativar os recursos experimentais da Plataforma Web em chrome://flags ou usar a seguinte sinalização de linha de comando:

--enable-blink-features=GetUserMedia

Da mesma forma para setSinkId(): ative os recursos experimentais da Plataforma Web experimental ou use uma flag:

--enable-blink-features=AudioOutputDevices

Abaixo há mais detalhes sobre o suporte ao navegador.

O futuro

O manipulador de eventos ondevicechange proposto faz o que diz: o evento devicechange é acionado quando o conjunto de dispositivos disponíveis muda e, em um gerenciador, você pode chamar enumerateDevices() para receber a nova lista de dispositivos. Isso ainda não foi implementado em nenhum navegador.

O rascunho da captura de tela é uma extensão da API Media Capture que propõe um método MediaDevices.getDisplayMedia() que permite que as regiões da tela de um usuário sejam usadas como a origem de um stream de mídia. Há também uma proposta de extensão MediaDevices para getSupportedConstraints(), que fornece informações sobre quais restrições podem ser usadas para uma chamada getUserMedia(): recursos de áudio e vídeo com suporte do navegador.

Demonstrações

Saiba mais