O que é sinalização?
A sinalização é o processo de coordenação da comunicação. Para que um app WebRTC faça uma chamada, os clientes precisam trocar as seguintes informações:
- Mensagens de controle de sessão usadas para abrir ou fechar a comunicação.
- Mensagens de erro
- Metadados de mídia, como codecs, configurações de codec, largura de banda e tipos de mídia
- Dados principais usados para estabelecer conexões seguras
- Dados de rede, como o endereço IP e a porta de um host, conforme vistos pelo mundo externo
Esse processo de sinalização precisa de uma maneira para os clientes trocarem mensagens. Esse mecanismo não é implementado pelas APIs WebRTC. Você precisa criar um. Mais adiante neste artigo, você vai aprender a criar um serviço de sinalização. Mas primeiro, você precisa de um pouco de contexto.
Por que a sinalização não é definida pelo WebRTC?
Para evitar redundância e maximizar a compatibilidade com tecnologias estabelecidas, os métodos e protocolos de sinalização não são especificados pelos padrões do WebRTC. Essa abordagem é descrita pelo Protocolo de estabelecimento de sessão JavaScript (JSEP):
A arquitetura do JSEP também evita que um navegador precise salvar o estado, ou seja, funcionar como uma máquina de estado de sinalização. Isso seria problemático se, por exemplo, os dados de indicadores fossem perdidos a cada recarregamento de página. Em vez disso, o estado de sinalização pode ser salvo em um servidor.

O JSEP exige a troca entre peers de oferta e resposta, os metadados de mídia mencionados acima. As ofertas e respostas são comunicadas no formato do Protocolo de descrição de sessões (SDP), que é assim:
v=0
o=- 7614219274584779017 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:W2TGCZw2NZHuwlnf
a=ice-pwd:xdQEccP40E+P0L5qTyzDgfmW
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=mid:audio
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:9c1AHz27dZ9xPI91YNfSlI67/EMkjHHIHORiClQe
a=rtpmap:111 opus/48000/2
…
Quer saber o que tudo isso significa? Confira os exemplos do Internet Engineering Task Force (IETF) (em inglês).
O WebRTC foi projetado para que a oferta ou a resposta possa ser ajustada antes de ser definida como a descrição local ou remota editando os valores no texto do SDP. Por exemplo, a função preferAudioCodec()
em appr.tc pode ser usada para definir o codec e a taxa de bits padrão. A SDP é um pouco difícil de manipular com JavaScript, e há uma discussão sobre se as versões futuras do WebRTC devem usar JSON. No entanto, há algumas vantagens em continuar usando a SDP.
API RTCPeerConnection
e sinalização: oferta, resposta e candidato
RTCPeerConnection
é a API usada por apps WebRTC para criar uma conexão entre usuários e comunicar áudio e vídeo.
Para iniciar esse processo, o RTCPeerConnection
tem duas tarefas:
- Verifique as condições de mídia locais, como resolução e recursos de codec. São os metadados usados para o mecanismo de oferta e resposta.
- Receba possíveis endereços de rede para o host do app, conhecidos como candidatos.
Depois que esses dados locais forem determinados, eles precisarão ser trocados por um mecanismo de sinalização com o peer remoto.
Imagine que Alice está tentando ligar para Eve. Veja o mecanismo completo de oferta/resposta em todos os detalhes:
- Alice cria um objeto
RTCPeerConnection
. - Alice cria uma oferta (uma descrição de sessão SDP) com o método
RTCPeerConnection
createOffer()
. - Alice liga para
setLocalDescription()
com a oferta dela. - Alice transforma a oferta em string e usa um mecanismo de sinalização para enviá-la a Eve.
- Eve liga para
setRemoteDescription()
com a oferta de Alice para que oRTCPeerConnection
dela saiba sobre a configuração de Alice. - Eve chama
createAnswer()
, e o callback de sucesso para isso recebe uma descrição de sessão local, que é a resposta de Eve. - Eve define a resposta como a descrição local chamando
setLocalDescription()
. - Em seguida, Eve usa o mecanismo de sinalização para enviar a resposta em formato de string para Alice.
- Alice define a resposta de Eve como a descrição da sessão remota usando
setRemoteDescription()
.
Alice e Eve também precisam trocar informações de rede. A expressão "encontrar candidatos" se refere ao processo de encontrar interfaces de rede e portas usando a estrutura ICE.
- Alice cria um objeto
RTCPeerConnection
com um manipuladoronicecandidate
. - O manipulador é chamado quando os candidatos de rede ficam disponíveis.
- No manipulador, Alice envia dados de candidatos em formato de string para Eve pelo canal de sinalização.
- Quando Eve recebe uma mensagem candidata de Alice, ela chama
addIceCandidate()
para adicionar o candidato à descrição do peer remoto.
O JSEP oferece suporte ao ICE Candidate Trickling, que permite que o autor da chamada forneça candidatos de forma incremental ao destinatário após a oferta inicial. Assim, o destinatário pode começar a atender a chamada e configurar uma conexão sem esperar que todos os candidatos cheguem.
Codificar o WebRTC para sinalização
O snippet de código a seguir é um exemplo de código do W3C que resume o processo de sinalização completo. O código pressupõe a existência de algum mecanismo de sinalização, SignalingChannel
. A sinalização será discutida em mais detalhes mais adiante.
// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);
// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});
// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
try {
await pc.setLocalDescription(await pc.createOffer());
// send the offer to the other peer
signaling.send({desc: pc.localDescription});
} catch (err) {
console.error(err);
}
};
// After remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
// Don't set srcObject again if it is already set.
if (remoteView.srcObject) return;
remoteView.srcObject = event.streams[0];
};
// Call start() to initiate.
async function start() {
try {
// Get local stream, show it in self-view, and add it to be sent.
const stream =
await navigator.mediaDevices.getUserMedia(constraints);
stream.getTracks().forEach((track) =>
pc.addTrack(track, stream));
selfView.srcObject = stream;
} catch (err) {
console.error(err);
}
}
signaling.onmessage = async ({desc, candidate}) => {
try {
if (desc) {
// If you get an offer, you need to reply with an answer.
if (desc.type === 'offer') {
await pc.setRemoteDescription(desc);
const stream =
await navigator.mediaDevices.getUserMedia(constraints);
stream.getTracks().forEach((track) =>
pc.addTrack(track, stream));
await pc.setLocalDescription(await pc.createAnswer());
signaling.send({desc: pc.localDescription});
} else if (desc.type === 'answer') {
await pc.setRemoteDescription(desc);
} else {
console.log('Unsupported SDP type.');
}
} else if (candidate) {
await pc.addIceCandidate(candidate);
}
} catch (err) {
console.error(err);
}
};
Para ver os processos de oferta/resposta e troca de candidatos em ação, consulte simpl.info RTCPeerConnection e confira o registro do console para um exemplo de chat de vídeo de página única. Se quiser mais informações, baixe um despejo completo de sinalização e estatísticas do WebRTC na página about://webrtc-internals no Google Chrome ou opera://webrtc-internals no Opera.
Descoberta de semelhantes
Essa é uma forma elegante de perguntar: "Como faço para encontrar alguém para conversar?"
Para ligações, você tem números de telefone e diretórios. Para videochamadas e mensagens on-line, você precisa de sistemas de gerenciamento de identidade e presença, além de uma maneira para os usuários iniciarem sessões. Os apps WebRTC precisam de uma maneira para que os clientes sinalizem uns aos outros que querem iniciar ou participar de uma chamada.
Os mecanismos de descoberta de pares não são definidos pelo WebRTC, e você não precisa acessar as opções aqui. O processo pode ser tão simples quanto enviar um URL por e-mail ou mensagem. Para apps de chat por vídeo, como Talky, tawk.to e Browser Meeting, você convida pessoas para uma chamada compartilhando um link personalizado. O desenvolvedor Chris Ball criou um experimento intrigante serverless-webrtc (link em inglês) que permite que os participantes de chamadas WebRTC troquem metadados por qualquer serviço de mensagens que quiserem, como mensagens instantâneas, e-mail ou pombo-correio.
Como criar um serviço de sinalização?
Vale lembrar que os protocolos e mecanismos de sinalização não são definidos pelos padrões do WebRTC. Seja qual for sua escolha, você vai precisar de um servidor intermediário para trocar mensagens de sinalização e dados de apps entre clientes. Infelizmente, um app da Web não pode simplesmente gritar na Internet: "Me conecte ao meu amigo!"
Felizmente, as mensagens de sinalização são pequenas e trocadas principalmente no início de uma chamada. Em testes com appr.tc para uma sessão de chat por vídeo, um total de cerca de 30 a 45 mensagens foram processadas pelo serviço de sinalização com um tamanho total de todas as mensagens de cerca de 10 KB.
Além de serem relativamente pouco exigentes em termos de largura de banda, os serviços de sinalização WebRTC não consomem muito processamento ou memória porque só precisam retransmitir mensagens e reter uma pequena quantidade de dados de estado da sessão, como quais clientes estão conectados.
Enviar mensagens push do servidor para o cliente
Um serviço de mensagens para sinalização precisa ser bidirecional: do cliente para o servidor e do servidor para o cliente. A comunicação bidirecional vai contra o modelo de solicitação/resposta cliente/servidor HTTP, mas vários hacks, como o long polling, foram desenvolvidos ao longo de muitos anos para enviar dados de um serviço em execução em um servidor da Web para um app da Web em execução em um navegador.
Mais recentemente, a EventSource
API foi amplamente implementada. Isso permite eventos enviados pelo servidor, ou seja, dados enviados de um servidor da Web para um cliente de navegador por HTTP. O EventSource
foi projetado para mensagens unidirecionais, mas pode ser usado em combinação com XHR para criar um serviço de troca de mensagens de sinalização. Um serviço de sinalização passa uma mensagem de um chamador, entregue por uma solicitação XHR, enviando-a por EventSource
para o destinatário da chamada.
O WebSocket é uma solução mais natural, projetada para comunicação full-duplex entre cliente e servidor, ou seja, mensagens que podem fluir em ambas as direções ao mesmo tempo. Uma vantagem de um serviço de sinalização criado com WebSocket puro ou eventos enviados pelo servidor (EventSource
) é que o back-end dessas APIs pode ser implementado em uma variedade de frameworks da Web comuns à maioria dos pacotes de hospedagem na Web para linguagens como PHP, Python e Ruby.
Todos os navegadores modernos, exceto o Opera Mini, são compatíveis com WebSocket e, mais importante, todos os navegadores que oferecem suporte ao WebRTC também são compatíveis com WebSocket, tanto em computadores quanto em dispositivos móveis. O TLS precisa ser usado em todas as conexões para garantir que as mensagens não sejam interceptadas sem criptografia e também para reduzir problemas com a travessia de proxy. Para mais informações sobre WebSocket e travessia de proxy, consulte o capítulo do WebRTC em High Performance Browser Networking de Ilya Grigorik.
Também é possível processar a sinalização fazendo com que os clientes WebRTC pesquisem um servidor de mensagens repetidamente usando o Ajax, mas isso gera muitas solicitações de rede redundantes, o que é especialmente problemático para dispositivos móveis. Mesmo depois que uma sessão é estabelecida, os participantes precisam pesquisar mensagens de sinalização em caso de mudanças ou encerramento da sessão por outros participantes. O exemplo de app WebRTC Book usa essa opção com algumas otimizações para a frequência de polling.
Sinalização de escala
Embora um serviço de sinalização consuma relativamente pouca largura de banda e CPU por cliente, os servidores de sinalização de um app popular podem precisar processar muitas mensagens de diferentes locais com altos níveis de simultaneidade. Os apps WebRTC que recebem muito tráfego precisam de servidores de sinalização capazes de lidar com uma carga considerável. Você não entra em detalhes aqui, mas há várias opções para mensagens de alto volume e alto desempenho, incluindo:
O eXtensible Messaging and Presence Protocol (XMPP), originalmente conhecido como Jabber, é um protocolo desenvolvido para mensagens instantâneas que pode ser usado para sinalização. As implementações do servidor incluem ejabberd e Openfire. Clientes JavaScript, como Strophe.js, usam BOSH para emular o streaming bidirecional, mas, por vários motivos, o BOSH pode não ser tão eficiente quanto o WebSocket e, pelos mesmos motivos, pode não ser dimensionado corretamente. (A propósito, Jingle é uma extensão XMPP para ativar voz e vídeo. O projeto WebRTC usa componentes de rede e transporte da biblioteca libjingle, uma implementação em C++ do Jingle.
Bibliotecas de código aberto, como ZeroMQ (usada pela TokBox no serviço Rumour) e OpenMQ. O NullMQ aplica conceitos do ZeroMQ a plataformas da Web usando o protocolo STOMP no WebSocket.
Plataformas comerciais de mensagens na nuvem que usam WebSocket (embora possam voltar para o long polling), como Pusher, Kaazing e PubNub (o PubNub também tem uma API para WebRTC).
Plataformas comerciais de WebRTC, como o vLine
O Guia de tecnologias da Web em tempo real (link em inglês) do desenvolvedor Phil Leggetter oferece uma lista abrangente de serviços e bibliotecas de mensagens.
Criar um serviço de sinalização com Socket.io no Node
Confira abaixo o código de um app da Web simples que usa um serviço de sinalização criado com Socket.io em Node. O design do Socket.io facilita a criação de um serviço para troca de mensagens, e ele é especialmente adequado para sinalização WebRTC devido ao conceito integrado de salas. Este exemplo não foi criado para ser dimensionado como um serviço de sinalização de nível de produção, mas é simples de entender para um número relativamente pequeno de usuários.
O Socket.io usa WebSocket com substitutos: sondagem longa AJAX, streaming multipart AJAX, Forever Iframe e sondagem JSONP. Ele foi portado para vários back-ends, mas talvez seja mais conhecido pela versão do Node usada neste exemplo.
Não há WebRTC neste exemplo. Ele foi projetado apenas para mostrar como criar sinalização em um web app. Consulte o registro do console para ver o que acontece quando os clientes entram em uma sala e trocam mensagens. Este codelab do WebRTC oferece instruções detalhadas sobre como integrar isso a um app completo de chat de vídeo do WebRTC.
Este é o cliente index.html
:
<!DOCTYPE html>
<html>
<head>
<title>WebRTC client</title>
</head>
<body>
<script src='/socket.io/socket.io.js'></script>
<script src='js/main.js'></script>
</body>
</html>
Este é o arquivo JavaScript main.js
referenciado no cliente:
const isInitiator;
room = prompt('Enter room name:');
const socket = io.connect();
if (room !== '') {
console.log('Joining room ' + room);
socket.emit('create or join', room);
}
socket.on('full', (room) => {
console.log('Room ' + room + ' is full');
});
socket.on('empty', (room) => {
isInitiator = true;
console.log('Room ' + room + ' is empty');
});
socket.on('join', (room) => {
console.log('Making request to join room ' + room);
console.log('You are the initiator!');
});
socket.on('log', (array) => {
console.log.apply(console, array);
});
Confira o app de servidor completo:
const static = require('node-static');
const http = require('http');
const file = new(static.Server)();
const app = http.createServer(function (req, res) {
file.serve(req, res);
}).listen(2013);
const io = require('socket.io').listen(app);
io.sockets.on('connection', (socket) => {
// Convenience function to log server messages to the client
function log(){
const array = ['>>> Message from server: '];
for (const i = 0; i < arguments.length; i++) {
array.push(arguments[i]);
}
socket.emit('log', array);
}
socket.on('message', (message) => {
log('Got message:', message);
// For a real app, would be room only (not broadcast)
socket.broadcast.emit('message', message);
});
socket.on('create or join', (room) => {
const numClients = io.sockets.clients(room).length;
log('Room ' + room + ' has ' + numClients + ' client(s)');
log('Request to create or join room ' + room);
if (numClients === 0){
socket.join(room);
socket.emit('created', room);
} else if (numClients === 1) {
io.sockets.in(room).emit('join', room);
socket.join(room);
socket.emit('joined', room);
} else { // max two clients
socket.emit('full', room);
}
socket.emit('emit(): client ' + socket.id +
' joined room ' + room);
socket.broadcast.emit('broadcast(): client ' + socket.id +
' joined room ' + room);
});
});
Não é necessário aprender sobre node-static para isso. Ele só é usado neste exemplo.)
Para executar esse app no localhost, você precisa ter o Node, o Socket.IO e o node-static instalados. O Node pode ser baixado em Node.js (a instalação é simples e rápida). Para instalar o Socket.IO e o node-static, execute o Node Package Manager em um terminal no diretório do app:
npm install socket.io
npm install node-static
Para iniciar o servidor, execute o seguinte comando em um terminal no diretório do app:
node server.js
No navegador, abra localhost:2013
. Abra uma nova guia ou janela em qualquer navegador e acesse localhost:2013
novamente. Para conferir o que está acontecendo, verifique o console. No Chrome e no Opera, é possível acessar o console pelas Ferramentas para desenvolvedores do Google Chrome com Ctrl+Shift+J
(ou Command+Option+J
no Mac).
Qualquer que seja a abordagem escolhida para a sinalização, o back-end e o app cliente precisam fornecer serviços semelhantes a este exemplo.
Pegadinhas de sinalização
- O
RTCPeerConnection
não vai começar a coletar candidatos até quesetLocalDescription()
seja chamado. Isso é obrigatório no rascunho do JSEP IETF. - Aproveite o Trickle ICE. Chame
addIceCandidate()
assim que os candidatos chegarem.
Servidores de sinalização prontos
Se você não quiser criar seu próprio servidor, há vários servidores de sinalização WebRTC disponíveis, que usam Socket.IO como no exemplo anterior e são integrados às bibliotecas JavaScript do cliente WebRTC:
- O webRTC.io é uma das primeiras bibliotecas de abstração para WebRTC.
- O Signalmaster é um servidor de sinalização criado para uso com a biblioteca de cliente JavaScript SimpleWebRTC.
Se você não quiser escrever nenhum código, plataformas WebRTC comerciais completas estão disponíveis em empresas como vLine, OpenTok e Asterisk.
Para constar, a Ericsson criou um servidor de sinalização usando PHP no Apache nos primeiros dias do WebRTC. Isso agora está um pouco obsoleto, mas vale a pena conferir o código se você estiver considerando algo semelhante.
Segurança de indicadores
"Segurança é a arte de não deixar nada acontecer."
Salman Rushdie
A criptografia é obrigatória para todos os componentes do WebRTC.
No entanto, os mecanismos de sinalização não são definidos pelos padrões do WebRTC. Portanto, cabe a você garantir a segurança da sinalização. Se um invasor conseguir sequestrar a sinalização, ele poderá interromper sessões, redirecionar conexões e gravar, alterar ou inserir conteúdo.
O fator mais importante para proteger a sinalização é usar protocolos seguros, como HTTPS e WSS (por exemplo, TLS), que garantem que as mensagens não possam ser interceptadas sem criptografia. Além disso, tenha cuidado para não transmitir mensagens de sinalização de forma que elas possam ser acessadas por outros chamadores usando o mesmo servidor de sinalização.
Após a sinalização: use o ICE para lidar com NATs e firewalls
Para sinalização de metadados, os apps WebRTC usam um servidor intermediário. No entanto, para streaming real de mídia e dados depois que uma sessão é estabelecida, o RTCPeerConnection
tenta conectar os clientes diretamente ou ponto a ponto.
Em um mundo mais simples, cada endpoint WebRTC teria um endereço exclusivo que poderia ser trocado com outros participantes para se comunicar diretamente.

Na realidade, a maioria dos dispositivos fica atrás de uma ou mais camadas de NAT, alguns têm software antivírus que bloqueia determinadas portas e protocolos, e muitos estão atrás de proxies e firewalls corporativos. Um firewall e um NAT podem ser implementados pelo mesmo dispositivo, como um roteador Wi-Fi doméstico.

Os apps WebRTC podem usar a estrutura ICE para superar as complexidades das redes do mundo real. Para isso, seu app precisa transmitir URLs do servidor ICE para RTCPeerConnection
, conforme descrito neste artigo.
O ICE tenta encontrar o melhor caminho para conectar os participantes. Ele tenta todas as possibilidades em paralelo e escolhe a opção mais eficiente que funciona. Primeiro, o ICE tenta fazer uma conexão usando o endereço do host obtido do sistema operacional e da placa de rede de um dispositivo. Se isso falhar (o que vai acontecer para dispositivos atrás de NATs), o ICE vai conseguir um endereço externo usando um servidor STUN e, se isso falhar, o tráfego será encaminhado por um servidor de retransmissão TURN.
Em outras palavras, um servidor STUN é usado para receber um endereço de rede externa, e os servidores TURN são usados para retransmitir o tráfego se a conexão direta (ponto a ponto) falhar.
Todos os servidores TURN são compatíveis com STUN. Um servidor TURN é um servidor STUN com funcionalidade de retransmissão integrada adicional. O ICE também lida com as complexidades das configurações de NAT. Na realidade, o NAT hole-punching pode exigir mais do que apenas um endereço IP público:porta.
Os URLs dos servidores STUN e/ou TURN são especificados (opcionalmente) por um app WebRTC no objeto de configuração iceServers
, que é o primeiro argumento do construtor RTCPeerConnection
. Para appr.tc, esse valor tem esta aparência:
{
'iceServers': [
{
'urls': 'stun:stun.l.google.com:19302'
},
{
'urls': 'turn:192.158.29.39:3478?transport=udp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
},
{
'urls': 'turn:192.158.29.39:3478?transport=tcp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
}
]
}
Depois que o RTCPeerConnection
tiver essas informações, a mágica do ICE vai acontecer automaticamente. O RTCPeerConnection
usa a estrutura ICE para determinar o melhor caminho entre os peers, trabalhando com servidores STUN e TURN conforme necessário.
STUN
Os NATs fornecem um dispositivo com um endereço IP para uso em uma rede local privada, mas esse endereço não pode ser usado externamente. Sem um endereço público, não há como os participantes do WebRTC se comunicarem. Para contornar esse problema, o WebRTC usa o STUN.
Os servidores STUN ficam na Internet pública e têm uma tarefa simples: verificar o endereço IP:porta de uma solicitação recebida (de um app em execução por trás de um NAT) e enviar esse endereço de volta como uma resposta. Em outras palavras, o app usa um servidor STUN para descobrir o IP:porta dele de uma perspectiva pública. Esse processo permite que um peer do WebRTC receba um endereço acessível publicamente para si mesmo e o transmita a outro peer por um mecanismo de sinalização para configurar um link direto. Na prática, diferentes NATs funcionam de maneiras diferentes, e pode haver várias camadas de NAT, mas o princípio é o mesmo.
Os servidores STUN não precisam fazer muito ou lembrar de muita coisa. Por isso, servidores STUN de especificações relativamente baixas podem processar um grande número de solicitações.
A maioria das chamadas do WebRTC faz uma conexão usando STUN (86%, de acordo com Webrtcstats.com), mas esse número pode ser menor para chamadas entre peers por trás de firewalls e configurações NAT complexas.

TURN
O RTCPeerConnection
tenta configurar a comunicação direta entre os participantes por UDP. Se isso não funcionar, RTCPeerConnection
vai recorrer ao TCP. Se isso falhar, os servidores TURN poderão ser usados como substitutos, retransmitindo dados entre endpoints.
Vale lembrar que o TURN é usado para retransmitir streaming de áudio, vídeo e dados entre usuários, não dados de sinalização.
Os servidores TURN têm endereços públicos, então podem ser contatados por peers mesmo que eles estejam atrás de firewalls ou proxies. Os servidores TURN têm uma tarefa conceitualmente simples: retransmitir um fluxo. No entanto, ao contrário dos servidores STUN, eles consomem muito da largura de banda. Em outras palavras, os servidores TURN precisam ser mais robustos.

Este diagrama mostra o TURN em ação. O STUN puro não teve sucesso, então cada peer recorre ao uso de um servidor TURN.
Como implantar servidores STUN e TURN
Para testes, o Google executa um servidor STUN público, stun.l.google.com:19302, usado pelo appr.tc. Para um serviço STUN/TURN de produção, use o rfc5766-turn-server. O código-fonte dos servidores STUN e TURN está disponível no GitHub, onde você também encontra links para várias fontes de informações sobre a instalação do servidor. Uma imagem de VM para Amazon Web Services também está disponível.
Uma alternativa é o servidor TURN restund, disponível como código-fonte e também para a AWS. Confira as instruções para configurar o restund no Compute Engine.
- Abra o firewall conforme necessário para tcp=443, udp/tcp=3478.
- Crie quatro instâncias, uma para cada IP público, imagem padrão do Ubuntu 12.06.
- Configure o firewall local (permita QUALQUER de QUALQUER).
- Instale ferramentas:
shell sudo apt-get install make sudo apt-get install gcc
- Instale o libre em creytiv.com/re.html.
- Busque o restund em creytiv.com/restund.html e descompacte./
wget
hancke.name/restund-auth.patch e aplique compatch -p1 < restund-auth.patch
.- Execute
make
,sudo make install
para libre e restund. - Adapte
restund.conf
às suas necessidades (substitua os endereços IP e verifique se ele contém a mesma senha secreta compartilhada) e copie para/etc
. - Copie
restund/etc/restund
para/etc/init.d/
. - Configurar o restund:
- Defina
LD_LIBRARY_PATH
. - Copie
restund.conf
para/etc/restund.conf
. - Defina
restund.conf
para usar os 10 corretos. ele vai receber um novo endereço IP.
- Defina
- Executar restund
- Teste usando o cliente stund de uma máquina remota:
./client IP:port
Além de um para um: WebRTC multiparty
Confira também o padrão proposto pelo IETF de Justin Uberti para uma API REST para acesso aos serviços TURN (em inglês).
É fácil imaginar casos de uso para streaming de mídia que vão além de uma simples chamada individual. Por exemplo, uma videoconferência entre um grupo de colegas ou um evento público com um palestrante e centenas ou milhões de espectadores.
Um app WebRTC pode usar várias RTCPeerConnections para que cada endpoint se conecte a todos os outros em uma configuração de malha. Essa é a abordagem adotada por apps como o talky.io e funciona muito bem para um pequeno grupo de pessoas. Além disso, o consumo de processamento e largura de banda se torna excessivo, especialmente para clientes móveis.

Outra opção é um app WebRTC escolher um endpoint para distribuir streams a todos os outros em uma configuração em estrela. Também é possível executar um endpoint WebRTC em um servidor e criar seu próprio mecanismo de redistribuição. Um app cliente de exemplo é fornecido pelo webrtc.org.
Desde o Chrome 31 e o Opera 18, um MediaStream
de um RTCPeerConnection
pode ser usado como entrada para outro. Isso pode permitir arquiteturas mais flexíveis, porque um web app pode processar o roteamento de chamadas escolhendo a qual outro usuário pareado se conectar. Para ver isso em ação, consulte Exemplos do WebRTC: retransmissão de conexão de mesmo nível e Exemplos do WebRTC: várias conexões de mesmo nível.
Unidade de controle multiponto
Uma opção melhor para um grande número de endpoints é usar uma unidade de controle multiponto (MCU, na sigla em inglês). É um servidor que funciona como uma ponte para distribuir mídia entre um grande número de participantes. As MCUs podem lidar com diferentes resoluções, codecs e frame rates em uma videoconferência, além de fazer transcodificação, encaminhamento seletivo de stream e mixagem ou gravação de áudio e vídeo. Para chamadas em grupo, há vários problemas a serem considerados, principalmente como mostrar várias entradas de vídeo e misturar áudio de várias fontes. Plataformas de nuvem, como vLine, também tentam otimizar o roteamento de tráfego.
É possível comprar um pacote completo de hardware de MCU ou criar o seu próprio.

Há várias opções de software de MCU de código aberto disponíveis. Por exemplo, a Licode (antes conhecida como Lynckia) produz uma MCU de código aberto para WebRTC. O OpenTok tem o Mantis.
Além dos navegadores: VoIP, telefones e mensagens
A natureza padronizada do WebRTC permite estabelecer comunicação entre um app WebRTC executado em um navegador e um dispositivo ou plataforma executado em outra plataforma de comunicação, como um telefone ou um sistema de videoconferência.
O SIP é um protocolo de sinalização usado por sistemas de VoIP e videoconferência. Para ativar a comunicação entre um app da Web WebRTC e um cliente SIP, como um sistema de videoconferência, o WebRTC precisa de um servidor proxy para intermediar a sinalização. A sinalização precisa passar pelo gateway, mas, depois que a comunicação é estabelecida, o tráfego SRTP (vídeo e áudio) pode fluir diretamente de ponto a ponto.
A rede pública de telefonia comutada (PSTN) é a rede comutada por circuito de todos os telefones analógicos "simples e antigos". Para chamadas entre apps da Web WebRTC e telefones, o tráfego precisa passar por um gateway de RPTC. Da mesma forma, os web apps WebRTC precisam de um servidor XMPP intermediário para se comunicar com endpoints Jingle, como clientes de mensagens instantâneas. O Jingle foi desenvolvido pelo Google como uma extensão do XMPP para ativar voz e vídeo em serviços de mensagens. As implementações atuais do WebRTC são baseadas na biblioteca libjingle em C++, uma implementação do Jingle inicialmente desenvolvida para o Talk.
Vários apps, bibliotecas e plataformas usam a capacidade do WebRTC de se comunicar com o mundo externo:
- sipML5: um cliente SIP JavaScript de código aberto.
- jsSIP: biblioteca SIP JavaScript.
- Phono: API de telefone JavaScript de código aberto criada como um plug-in.
- Zingaya: um widget de telefone incorporável.
- Twilio: voz e mensagens
- Uberconference: videoconferência
Os desenvolvedores do sipML5 também criaram o gateway webrtc2sip. A Tethr e a Tropo demonstraram uma estrutura para comunicações em caso de desastre "em uma pasta" usando uma célula OpenBTS para permitir a comunicação entre smartphones comuns e computadores pelo WebRTC. É uma comunicação telefônica sem operadora!
Saiba mais
O codelab do WebRTC (link em inglês) oferece instruções detalhadas sobre como criar um app de chat de vídeo e texto usando um serviço de sinalização Socket.io executado no Node.
Apresentação do WebRTC no Google I/O de 2013 com o líder técnico do WebRTC, Justin Uberti
Apresentação de Chris Wilson no SFHTML5: Introdução aos apps WebRTC (em inglês)
O livro de 350 páginas WebRTC: APIs and RTCWEB Protocols of the HTML5 Real-Time Web (em inglês) fornece muitos detalhes sobre caminhos de dados e sinalização e inclui vários diagramas detalhados de topologia de rede.
WebRTC e sinalização: o que dois anos nos ensinaram: postagem do blog TokBox sobre por que deixar a sinalização fora da especificação foi uma boa ideia.
Um guia prático para criar apps WebRTC, de Ben Strong, oferece muitas informações sobre topologias e infraestrutura do WebRTC.
O capítulo do WebRTC em Redes de navegadores de alta performance de Ilya Grigorik aborda a arquitetura, os casos de uso e o desempenho do WebRTC.