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

Os navegadores modernos 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 alto-falante conectado por Bluetooth.
  • Para um chat por vídeo, escolha o microfone ou a câmera interna ou externa.

Todas essas funcionalidades são expostas pelo objeto MediaDevices, que é retornado por navigator.mediaDevices.

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

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

enumerateDevices()

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

O método é semelhante ao MediaStreamTrack.getSources(), mas, ao contrário desse método (que só foi implementado no Chrome), ele é compatível com os padrões e inclui dispositivos de saída de áudio. Teste isso com as demonstrações abaixo.

Confira um código um pouco simplificado de 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 extrair os IDs dos dispositivos disponíveis com enumerateDevices(), use 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 de áudio do elemento. Depois que setSinkId() for chamado, você poderá conferir o ID do dispositivo de áudio de saída atual do elemento com a propriedade sinkId.

getUserMedia()

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

Há uma demonstração no site de amostras do WebRTC.

Confira 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) {
    // ...
    }

Agitação de bandeira

O método enumerateDevices() não tem flag no Chrome, mas para MediaDevices.getUserMedia(), ainda é necessário ativar os recursos experimentais da plataforma da Web em chrome://flags ou usar a flag de linha de comando a seguir:

--enable-blink-features=GetUserMedia

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

--enable-blink-features=AudioOutputDevices

Confira mais detalhes sobre a compatibilidade com navegadores abaixo.

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 manipulador, você pode chamar enumerateDevices() para receber a nova lista de dispositivos. Isso ainda não foi implementado em nenhum navegador.

O rascunho de 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() (link em inglês), que fornece informações sobre quais restrições podem ser usadas para uma chamada getUserMedia(): recursos de áudio e vídeo compatíveis com o navegador.

Demonstrações

Saiba mais