W3docs

WebRTC

WebRTC (Web Real-Time Communication) é um projeto open-source e conjunto de tecnologias web que permitem comunicação em tempo real diretamente entre navegadores e aplicações.

WebRTC: Comunicação em Tempo Real no Navegador

WebRTC (Web Real-Time Communication) é um padrão aberto e um conjunto de APIs do navegador que permitem que dois navegadores troquem áudio, vídeo e dados arbitrários diretamente entre si — peer-to-peer — sem rotear a mídia através de um servidor e sem qualquer plugin. Ele suporta videoconferência, chamadas de voz, compartilhamento de tela, estado de jogos ao vivo e transferência de arquivos com baixa latência.

Este capítulo explica o que o WebRTC oferece, as três APIs sobre as quais é construído, os conceitos de sinalização e travessia de NAT que confundem a maioria dos iniciantes, e um exemplo completo e funcional de canal de dados que você pode executar nesta página.

O que o WebRTC realmente faz

O navegador já sabe como se comunicar com um servidor (veja Fetch API e WebSockets). O WebRTC adiciona a peça que faltava: uma forma de dois clientes conversarem entre si. Uma vez que uma conexão peer seja aberta, mídia e dados trafegam pelo caminho mais curto possível — frequentemente diretamente entre as duas máquinas — razão pela qual a latência do WebRTC é muito menor do que retransmitir tudo através do seu backend.

Usos típicos:

  • Chamadas de áudio e vídeo — voz/vídeo em tempo real, como o Zoom ou o Google Meet.
  • Compartilhamento de tela — captura uma tela ou janela com getDisplayMedia() e a transmite para um peer.
  • Dados em tempo real — estado de jogo, chat, posições do cursor ou fragmentos de arquivos por meio de um RTCDataChannel.

Por que usar o WebRTC

  • Peer-to-peer, baixa latência. A mídia flui diretamente entre os peers, não através do seu servidor, portanto os tempos de ida e volta são curtos e sua conta de largura de banda permanece pequena.
  • Sem plugins. Integrado em todos os navegadores modernos — sem Flash, sem aplicativo nativo, sem download.
  • Criptografado por padrão. A mídia usa SRTP e os canais de dados usam DTLS; a criptografia é obrigatória e não pode ser desativada.
  • Multiplataforma. Funciona em navegadores desktop e móveis e em aplicativos nativos por meio do mesmo padrão.
  • Padrão aberto. Mantido pelo W3C e pelo IETF, portanto continua melhorando sem aprisionamento a um fornecedor.

As três APIs principais

O WebRTC é, na verdade, três APIs funcionando em conjunto:

  1. MediaStream API (getUserMedia) — captura áudio/vídeo do microfone, câmera ou tela como um MediaStream.
  2. RTCPeerConnection — o coração do WebRTC. Ela negocia, criptografa e mantém a conexão entre dois peers e transporta as trilhas de mídia.
  3. RTCDataChannel — um canal bidirecional para enviar dados arbitrários (strings ou binários) peer-to-peer, semelhante ao WebSockets, mas sem um servidor intermediário.

Sinalização: a parte que o WebRTC não faz

Dois navegadores não conseguem se encontrar do nada. Antes que uma conexão peer possa ser aberta, os peers devem trocar dois tipos de informação:

  • SDP (Session Description Protocol) — uma "oferta" e uma "resposta" descrevendo codecs, formatos de mídia e parâmetros de conexão.
  • Candidatos ICE — possíveis endereços de rede (pares de IP/porta) pelos quais cada peer pode ser alcançado.

O WebRTC não define como essa troca acontece — isso é sua responsabilidade, e é chamado de sinalização. Você constrói um canal de sinalização com o transporte de servidor que preferir; WebSockets é a escolha mais comum. O fluxo é sempre:

  1. O chamador cria uma oferta e a envia pelo servidor de sinalização.
  2. O receptor recebe a oferta, cria uma resposta e a envia de volta.
  3. Ambos os peers trocam candidatos ICE à medida que são descobertos.
  4. A conexão direta peer-to-peer é estabelecida; o servidor de sinalização não é mais necessário.

STUN e TURN: atravessando firewalls

A maioria dos dispositivos está atrás de NAT (Network Address Translation) e firewalls, portanto um peer raramente conhece seu próprio endereço público. Dois tipos de servidor resolvem isso:

  • Servidor STUN — informa a um peer seu IP/porta público para que os peers possam tentar uma conexão direta. Econômico e sem estado; o Google disponibiliza servidores públicos gratuitos.
  • Servidor TURN — retransmite a mídia quando uma conexão direta é impossível (firewalls corporativos restritivos). Consome largura de banda, portanto é um recurso de fallback, não o padrão.

Você lista esses servidores na configuração iceServers passada para RTCPeerConnection:

const configuration = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    // A TURN server is added for hard-to-reach networks:
    // { urls: 'turn:turn.example.com', username: 'user', credential: 'pass' }
  ],
};

const peerConnection = new RTCPeerConnection(configuration);

Exemplo: capturando a câmera com getUserMedia

O primeiro passo de qualquer videochamada é obter o stream local. getUserMedia retorna uma Promise, portanto você pode usar async/await:

<video id="localVideo" autoplay playsinline muted></video>
const localVideo = document.getElementById('localVideo');

async function startCamera() {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true,
    });
    localVideo.srcObject = stream; // show the live camera feed
    return stream;
  } catch (error) {
    console.error('Could not access camera/microphone:', error.message);
  }
}

startCamera();

getUserMedia só funciona em um contexto seguro (HTTPS ou localhost) e solicita permissão ao usuário — você nunca pode gravar alguém silenciosamente.

Exemplo: um canal de dados completo entre dois peers

A forma mais clara de ver o WebRTC funcionar é conectar dois objetos RTCPeerConnection entre si em um único script. Aqui, ambos os peers estão na mesma página, portanto podemos conectar sua sinalização diretamente em vez de usar um servidor — a troca de SDP/ICE é exatamente o que um servidor de sinalização real transportaria. Cole isso no console do navegador em qualquer página HTTPS para vê-lo funcionar:

// Two peers, normally on different machines.
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();

// --- Signaling: hand each peer's ICE candidates to the other.
// In production this travels over WebSockets; here we call directly.
caller.onicecandidate = (e) => e.candidate && callee.addIceCandidate(e.candidate);
callee.onicecandidate = (e) => e.candidate && caller.addIceCandidate(e.candidate);

// The callee listens for the channel the caller opens.
callee.ondatachannel = (event) => {
  const channel = event.channel;
  channel.onmessage = (e) => {
    console.log('Callee received:', e.data);
    channel.send('pong'); // reply over the same channel
  };
};

// The caller creates the data channel.
const channel = caller.createDataChannel('chat');
channel.onopen = () => channel.send('ping');
channel.onmessage = (e) => console.log('Caller received:', e.data);

// --- Offer / answer negotiation.
async function connect() {
  const offer = await caller.createOffer();
  await caller.setLocalDescription(offer);
  await callee.setRemoteDescription(offer);

  const answer = await callee.createAnswer();
  await callee.setLocalDescription(answer);
  await caller.setRemoteDescription(answer);
}

connect();
// Logs:
// Callee received: ping
// Caller received: pong

O padrão é o mesmo para vídeo: em vez de createDataChannel, você chama peerConnection.addTrack(track, stream) para cada trilha de getUserMedia, e lê a mídia recebida em um manipulador ontrack:

const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
stream.getTracks().forEach((track) => peerConnection.addTrack(track, stream));

// The remote peer's media arrives here:
peerConnection.ontrack = (event) => {
  document.getElementById('remoteVideo').srcObject = event.streams[0];
};

Problemas comuns

  • Requer HTTPS. getUserMedia e getDisplayMedia falham fora de um contexto seguro (HTTPS ou localhost).
  • Você ainda precisa de um servidor de sinalização. O WebRTC gerencia a mídia, mas você mesmo deve construir a troca de oferta/resposta/ICE — geralmente via WebSockets.
  • Sempre crie a oferta/resposta na ordem correta. setLocalDescription deve ser executado antes de setRemoteDescription para o lado correspondente, caso contrário a negociação falha.
  • Não se esqueça de um servidor TURN em produção. O STUN sozinho falha em redes restritivas; sem o TURN, cerca de 10–20% das conexões no mundo real não serão estabelecidas.
  • As permissões podem ser negadas. Envolva getUserMedia em try/catch e trate a rejeição de forma adequada.

Resumo

O WebRTC oferece ao navegador áudio, vídeo e dados verdadeiramente peer-to-peer. Use getUserMedia para capturar mídia, RTCPeerConnection para negociar e manter a conexão, e RTCDataChannel para dados arbitrários. O WebRTC não fornece sinalização — você mesmo troca ofertas/respostas SDP e candidatos ICE, tipicamente via WebSockets, e configura servidores STUN/TURN para atravessar o NAT. Com essas peças no lugar, você pode construir videochamadas, compartilhamento de tela e colaboração em tempo real inteiramente no navegador.

Practice

Prática
Quais das seguintes afirmações representam capacidades verdadeiras do WebRTC?
Quais das seguintes afirmações representam capacidades verdadeiras do WebRTC?
Was this page helpful?