Escolhendo câmeras em JavaScript com a API mediaDevices
Tempo de leitura: 6 minutos
A maioria dos smartphones vêm com uma câmera frontal e traseira, e quando você está construindo uma aplicação de vídeo para mobile, você pode querer escolher ou alternar entre elas.
Se você estiver construindo uma aplicação de chat, provavelmente vai querer a câmera frontal, mas se estiver construindo um aplicativo de câmeras, talvez esteja mais interessado na câmera traseira. Neste post, vamos ver como escolher ou alternar entre as câmeras usando a API mediaDevices
e restrições de mídia.
Do que você vai precisar
Para prosseguir neste post, você vai precisar de:
- Um iOS ou Android com duas câmeras para fazer testes. Se você tiver duas webcams no notebook, também serve.
- ngrok para que você possa facilmente acessar o projeto do seu aparelho móvel (e porque eu acho o ngrok incrível).
- O código deste repositório do GitHub para começar
Para pegar o código, clone o projeto e dê um checkout no projeto:
O projeto inicial vai te dar alguns arquivos HTML e CSS para que você possa concentrar no JavaScript. Você pode abrir o arquivo index.html
diretamente, mas eu te recomendo disponibilizar estes arquivos em um webserver. Eu gosto de usar o módulo serve do npm. Eu também incluí o módulo serve
no repositório. Para usá-lo, instale a dependência com o npm e inicie o servidor.
Uma vez que tiver o servidor rodando, abra um túnel usando o ngrok. O serve
disponibiliza os arquivos na porta 5000, para vincular o túnel desta porta com o ngrok, rode a linha de comando a seguir em uma nova janela:
Agora você tem uma versão pública disponível do site que você pode abrir em seu aparelho móvel para testá-lo mais tarde. Certifique-se de que você está abrindo a URL HTTPS já que as APIs que estamos usando só rodam em um ambiente seguro.
O app deve se parecer com a imagem a seguir:
Pegando o Stream de mídia
Nosso primeiro desafio é pegar o stream de vídeo de qualquer câmera na tela. Uma vez que isso estiver completo, vamos investigar as opções para selecionar uma câmera específica. Abra o app.js
e comece selecionando os elementos de vídeo e de botão do DOM:
Vamos pedir acesso à câmera usando a API da mediaDevices
, quando o usuário clicar no botão. Para isso, chame o navigator.mediaDevices.getUserMedia()
passando um objeto de restrições de mídia. Vamos começar com uma simples configuração de restrições, neste caso filtrando apenas por vídeos, então vamos configurar vídeo em true
e áudio em false
.
getUserMedia
retorna uma promise que, quando resolvida, nos dá acesso ao streaming de mídia da câmera.
Defina o srcObj
do vídeo com stream e teremos o seguinte código:
Salve o arquivo, recarregue a página e clique no botão. Agora deve aparecer uma caixa de confirmação solicitando acesso à sua câmera. Uma vez que as permissões forem dadas, seu vídeo vai aparecer na tela.
Experimente em seu computador e telefone. Quando eu tentei com meu iPhone, a câmera selecionada foi a câmera frontal.
Se estiver usando um iPhone, certifique-se de checar no Safari, já que aparentemente não está funcionando em outros navegadores.
Quais câmeras estão disponíveis?
A API da mediaDevices
nos dá uma maneira de listar todos os dispositivos disponíveis para entrada de áudio e vídeo. Vamos usar o enumerateDevices
para construir um conjunto de opções em uma caixa de listagem para que possamos escolher a câmera que queremos ver
. Abra o app.js novamente e comece selecionando o elemento do DOM da caixa de seleção:
enumerateDevices
retorna uma promise, então vamos escrever uma função que possamos usar para receber os resultados da promise. A função vai receber uma lista de aparelhos de mídia como argumento.
A primeira coisa a se fazer é esvaziar o <select>
de qualquer opção existente e anexar uma <option>
vazia. E depois percorrer a lista de dispositivos, filtrando qualquer um que não seja do tipo “videoinput”. Depois criamos uma <option>
usando o ID do dispositivo como o valor e o label do dispositivo para o texto. Também vamos lidar com o caso onde um aparelho não tiver um label definido, criando um texto “Camera n” para este caso.
No final do app.js
, faça a chamada para enumerateDevices
.
Atualize a página e dê uma olhada na caixa de seleção próximo ao botão. Se estiver no Android, ou usando o Chrome ou Firefox, você vai ver o nome das câmeras que estiverem disponíveis.
No iPhone, você vai ver o nome genérico “Camera 1” e “Camera 2” da nossa função. No iOS, você não vai receber labels das câmeras até que tenha dado permissão ao site para usar pelo menos uma das câmeras. Isso torna nossa interface menos útil ao selecionar as câmeras, e mesmo que você receba o ID dos aparelhos, você não conseguirá saber qual câmera é qual.
Ainda não fizemos o código para trocar a câmera ao mudar a caixa de seleção. Antes disso, vamos dar uma olhada em outra maneira para podermos escolher qual câmera queremos usar.
Modo de Face
Uma alternativa que podemos usar para selecionar a câmera é a restrição facingMode
. Esta é uma maneira menos exata de selecionar uma câmera do que pegando seu ID do enumerateDevices
, mas funciona muito bem para dispositivos móveis. Existem quatro opções que você pode usar para a restrição: user
, environemnt
, left
e right
. As restrições são explicadas na documentação MDN, e para este post, vamos usar user
e environment
já que eles mapeiam bem as câmeras dianteiras e traseiras em smartphones.
Para usar a restrição facingMode
, precisamos mudar as constraints
que usamos em nossa chamada para o getUserMedia
. Ao invés de apenas dizer true
para vídeo
, precisamos de um objeto para essas restrições. Atualize o código do botão para selecionar a câmera dianteira:
Teste no seu celular agora. Você vai ver a câmera frontal selecionada. Faça a atualização do facingMode
para environment
e tente novamente. Agora a câmera de trás deve estar selecionada.
Vamos juntar o código com os resultados do enumerateDevices
acima para construir um alternador de câmeras, uma vez que tivermos permissões para ler os dados de câmera.
Alternando Câmeras
Temos o código para selecionar uma câmera de usuário ou ambiente na primeira seleção, mas se quisermos alternar entre câmeras, precisamos de um pouco mais.
Primeiro, deveríamos manter uma referência do stream atual para que possamos pará-lo quando trocamos para outro dispositivo. Adicione mais uma variável e uma função para parar a stream no topo do app.js
.
A função stopMediaTracks
recebe uma stream como parâmetro e percorre todas as trilhas disponíveis na stream, parando cada uma delas.
Vamos mudar de câmera quando apertamos no mesmo botão, então precisamos atualizar o event listener, mas se tivermos um currentStream
definido, devemos pará-lo primeiro. Depois, vamos checar o <select>
para ver se estamos escolhendo um dispositivo em particular e construir as restrições de vídeo baseadas na seleção.
Atualize o handler de clique do botão e vamos ter o seguinte:
Quando quisermos selecionar um aparelho por seu deviceId
, usamos a restrição exact
. Evitamos isso para o facingMode
, já que isso poderia falhar em um aparelho que não reconheça user
ou environment
, nos deixando sem nenhuma mídia.
Ainda dentro do handler de click do botão, quando tivermos permissão de usar o vídeo, vamos mudar mais algumas coisas. Configure o currentStream
para o novo stream passado pela função, para que possamos pará-lo depois, e chame o enumerateDevices
novamente.
Como o enumerateDevices
retorna uma promise, vamos acioná-lo como um retorno do nosso then
da getUserMedia e ligá-lo a um novo then
com o resultado que será repassado para nossa função gotDevices
.
Substitua a chamada existente por getUserMedia
com o seguinte:
Quando adicionar todo o código, seu app.js
deve parecer com este código completo. Atualize a página para poder brincar, selecionando e mudando as câmeras. Isso funciona no dispositivo móvel e na web também.
Próximos passos
Acabamos de ver como selecionar uma câmera de usuário com a facingMode
ou deviceId
. Lembre-se, facingMode
é mais confiável antes de você ter permissões, mas selecionar um deviceId
é mais preciso. Você pode pegar todo o código deste post no repositório do GitHub ou experimentar a aplicação ao vivo aqui.
Se estiver usando a Twilio Video para construir uma aplicação de vídeo, você pode usar essas restrições ao chamar os comandos connect
ou createLocalVideoTrack
.
Selecionar ou alternar câmeras é uma funcionalidade útil para chat em vídeo, permitindo que usuários selecionem a câmera exata que eles querem usar na sua interface, e pode ser muito útil ao compartilhar sua tela durante uma chamada de vídeo também.
Existem outras funcionalidades de vídeo que você gostaria de ver que seriam úteis em chats de vídeo ou tem alguma pergunta sobre essa funcionalidade? Me conte no Twitter @luisleao.
Publicações relacionadas
Recursos relacionados
Twilio Docs
De APIs a SDKs e aplicativos de amostra
Documentação de referência de API, SDKs, bibliotecas auxiliares, guias de início rápido e tutoriais para sua linguagem e plataforma.
Centro de Recursos
Os mais recentes e-books, relatórios do setor e webinars
Aprenda com especialistas em engajamento do cliente para melhorar sua própria comunicação.
Ahoy
Centro da comunidade de desenvolvedores da Twilio
Melhores práticas, exemplos de código e inspiração para criar comunicações e experiências de engajamento digital.