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 padrões e inclui dispositivos de saída de áudio. Você pode testar 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. Recomendamos que os desenvolvedores usem 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

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() que fornece informações sobre quais restrições podem ser usadas para uma chamada getUserMedia(): recursos de áudio e vídeo aceitos pelo navegador.

Demonstrações

Saiba mais