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:
- MediaStream API (
getUserMedia) — captura áudio/vídeo do microfone, câmera ou tela como umMediaStream. - 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.
- 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:
- O chamador cria uma oferta e a envia pelo servidor de sinalização.
- O receptor recebe a oferta, cria uma resposta e a envia de volta.
- Ambos os peers trocam candidatos ICE à medida que são descobertos.
- 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: pongO 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.
getUserMediaegetDisplayMediafalham fora de um contexto seguro (HTTPS oulocalhost). - 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.
setLocalDescriptiondeve ser executado antes desetRemoteDescriptionpara 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
getUserMediaem 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.