Começar a usar o WebRTC

O WebRTC é uma nova frente na longa guerra por uma Web aberta e livre de obstáculos.

Brendan Eich, inventor do JavaScript

Imagine um mundo onde seu telefone, TV e computador pudessem se comunicar em uma plataforma comum. Imagine que foi fácil adicionar o chat por vídeo e o compartilhamento de dados ponto a ponto ao seu app da Web. Essa é a visão do WebRTC.

Quer fazer um teste? O WebRTC está disponível para computadores e dispositivos móveis no Google Chrome, Safari, Firefox e Opera. Um bom lugar para começar é o aplicativo simples de bate-papo por vídeo disponível em appr.tc:

  1. Abra appr.tc no seu navegador.
  2. Clique em Participar para entrar em uma sala de chat e permitir que o app use sua webcam.
  3. Abra o URL exibido no final da página em uma nova guia ou, melhor ainda, em um computador diferente.

Início rápido

Não tem tempo para ler este artigo ou quer apenas o código?

Se preferir, acesse diretamente o codelab de WebRTC, um guia explicativo que explica como criar um app completo de chat por vídeo, incluindo um servidor de sinalização simples.

Um breve histórico do WebRTC

Um dos últimos grandes desafios da Web é possibilitar a comunicação humana por voz e vídeo: a comunicação em tempo real, ou RTC, para abreviar. O RTC deve ser tão natural em um aplicativo da web quanto inserir texto em uma entrada de texto. Sem ela, sua capacidade de inovar e desenvolver novas maneiras de interação é limitada.

Historicamente, a RTC é corporativa e complexa, exigindo que tecnologias caras de áudio e vídeo sejam licenciadas ou desenvolvidas internamente. Integrar a tecnologia RTC aos conteúdos, dados e serviços existentes tem sido difícil e demorado, especialmente na web.

O bate-papo por vídeo do Gmail ficou popular em 2008 e, em 2011, o Google lançou o Hangouts, que usa o Google Talk (assim como o Gmail). O Google comprou a GIPS, uma empresa que desenvolveu muitos componentes necessários para o RTC, como codecs e técnicas de cancelamento de eco. O Google abriu o código das tecnologias desenvolvidas pelo GIPS e se envolveu com órgãos de normalização relevantes na Internet Engineering Task Force (IETF) e no World Wide Web Consortium (W3C) para garantir o consenso do setor. Em maio de 2011, a Ericsson criou a primeira implementação do WebRTC.

O WebRTC implementou padrões abertos para comunicação de vídeo, áudio e dados em tempo real e sem plug-ins. A necessidade era real:

  • Muitos serviços da Web usavam o RTC, mas precisavam de downloads, apps nativos ou plug-ins. Eles incluíam o Skype, o Facebook e o Hangouts.
  • Fazer o download, instalar e atualizar plug-ins é algo complexo, propenso a erros e irritante.
  • Plug-ins são difíceis de implantar, depurar, solucionar problemas, testar e manter. Além disso, eles podem exigir licenciamento e integração com tecnologias complexas e caras. Muitas vezes, é difícil persuadir as pessoas a instalar plug-ins em primeiro lugar!

Os princípios orientadores do projeto WebRTC são que suas APIs devem ser de código aberto, sem custo financeiro, padronizadas, integradas em navegadores da Web e mais eficientes do que as tecnologias existentes.

Onde estamos agora?

O WebRTC é usado em vários apps, como o Google Meet. O WebRTC também foi integrado ao WebKitGTK+ e aos apps nativos do Qt.

O WebRTC implementa estas três APIs: - MediaStream (também conhecido como getUserMedia) – RTCPeerConnectionRTCDataChannel

As APIs são definidas nestas duas especificações:

As três APIs são compatíveis com dispositivos móveis e computadores pelo Chrome, Safari, Firefox, Edge e Opera.

getUserMedia: para demonstrações e códigos, consulte as amostras de WebRTC (em inglês) ou teste os exemplos incríveis (em inglês) de Chris Wilson que usam getUserMedia como entrada para áudio da Web.

RTCPeerConnection: para uma demonstração simples e um app de chat por vídeo totalmente funcional, consulte Amostras de WebRTC conexão de peering e appr.tc, respectivamente. Este app usa o adapter.js, um paliativo de JavaScript mantido pelo Google com a ajuda da comunidade WebRTC (links em inglês), para entender as diferenças do navegador e as mudanças nas especificações.

RTCDataChannel: para conferir como isso funciona, consulte as amostras de WebRTC para conferir uma das demonstrações dos canais de dados.

O codelab WebRTC mostra como usar as três APIs para criar um app simples de chat por vídeo e compartilhamento de arquivos.

Seu primeiro WebRTC

Os apps WebRTC precisam fazer várias coisas:

  • Tenha streaming de áudio, vídeo ou outros dados.
  • Receba informações sobre a rede, como portas e endereços IP, e as troque com outros clientes WebRTC (conhecidos como peers) para permitir a conexão, mesmo por meio de NATs e firewalls.
  • Coordene a comunicação de sinalização para relatar erros e iniciar ou encerrar sessões.
  • Troque informações sobre a mídia e a capacidade do cliente, como resolução e codecs.
  • Comunicar streaming de áudio, vídeo ou dados.

Para adquirir e comunicar dados de streaming, o WebRTC implementa as seguintes APIs:

  • O MediaStream tem acesso a fluxos de dados, como da câmera e do microfone do usuário.
  • O RTCPeerConnection permite fazer chamadas de áudio ou vídeo com recursos de criptografia e gerenciamento de largura de banda.
  • O RTCDataChannel permite a comunicação ponto a ponto de dados genéricos.

(Há uma discussão detalhada sobre a rede e os aspectos de sinalização do WebRTC mais tarde.)

API MediaStream (também conhecida como API getUserMedia)

A API MediaStream representa fluxos de mídia sincronizados. Por exemplo, um stream capturado pela entrada de câmera e microfone tem faixas de vídeo e áudio sincronizadas. Não confunda MediaStreamTrack com o elemento <track>, que é totalmente diferente.

Provavelmente, a maneira mais fácil de entender a API MediaStream é conferindo-a:

  1. No navegador, acesse Exemplos de WebRTC getUserMedia.
  2. Abra o console.
  3. Inspecione a variável stream, que está no escopo global.

Cada MediaStream tem uma entrada, que pode ser uma MediaStream gerada por getUserMedia(), e uma saída, que pode ser transmitida para um elemento de vídeo ou um RTCPeerConnection.

O método getUserMedia() usa um parâmetro de objeto MediaStreamConstraints e retorna um Promise que é resolvido em um objeto MediaStream.

Cada MediaStream tem um label, como 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'. Uma matriz de MediaStreamTracks é retornada pelos métodos getAudioTracks() e getVideoTracks().

No exemplo da getUserMedia, stream.getAudioTracks() retorna uma matriz vazia (porque não há áudio) e, supondo que uma webcam que funcione está conectada, stream.getVideoTracks() retorna uma matriz de um MediaStreamTrack que representa o stream da webcam. Cada MediaStreamTrack tem um tipo ('video' ou 'audio'), um label (algo como 'FaceTime HD Camera (Built-in)') e representa um ou mais canais de áudio ou vídeo. Neste caso, há apenas uma faixa de vídeo e nenhum áudio, mas é fácil imaginar casos de uso em que há mais, como um app de chat que recebe streams da câmera frontal, câmera traseira, microfone e um app que compartilha a tela.

Uma MediaStream pode ser anexada a um elemento de vídeo definindo o atributo srcObject. Anteriormente, isso era feito ao definir o atributo src como um URL de objeto criado com URL.createObjectURL(), mas esse método foi descontinuado.

O getUserMedia também pode ser usado como um nó de entrada para a API Web Audio:

// Cope with browser differences.
let audioContext;
if (typeof AudioContext === 'function') {
  audioContext = new AudioContext();
} else if (typeof webkitAudioContext === 'function') {
  audioContext = new webkitAudioContext(); // eslint-disable-line new-cap
} else {
  console.log('Sorry! Web Audio not supported.');
}

// Create a filter node.
var filterNode = audioContext.createBiquadFilter();
// See https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#BiquadFilterNode-section
filterNode.type = 'highpass';
// Cutoff frequency. For highpass, audio is attenuated below this frequency.
filterNode.frequency.value = 10000;

// Create a gain node to change audio volume.
var gainNode = audioContext.createGain();
// Default is 1 (no change). Less than 1 means audio is attenuated
// and vice versa.
gainNode.gain.value = 0.5;

navigator.mediaDevices.getUserMedia({audio: true}, (stream) => {
  // Create an AudioNode from the stream.
  const mediaStreamSource =
    audioContext.createMediaStreamSource(stream);
  mediaStreamSource.connect(filterNode);
  filterNode.connect(gainNode);
  // Connect the gain node to the destination. For example, play the sound.
  gainNode.connect(audioContext.destination);
});

Apps e extensões baseados no Chromium também podem incorporar getUserMedia. A adição de permissões audioCapture e/ou videoCapture ao manifesto permite que a permissão seja solicitada e concedida apenas uma vez após a instalação. Depois disso, o usuário não recebe uma solicitação de permissão para acessar a câmera ou o microfone.

A permissão só precisa ser concedida uma vez para getUserMedia(). Na primeira vez, o botão "Permitir" aparece na barra de informações do navegador. O acesso HTTP ao getUserMedia() foi suspenso pelo Chrome no final de 2015 por ser classificado como um recurso avançado.

A intenção é ativar um MediaStream para qualquer fonte de dados de streaming, não apenas para uma câmera ou microfone. Isso permite o streaming de dados armazenados ou fontes de dados arbitrárias, como sensores ou outras entradas.

getUserMedia() realmente ganha vida em combinação com outras APIs e bibliotecas JavaScript:

  • O Webcam Toy é um app para cabine de fotos que usa WebGL para adicionar efeitos estranhos e incríveis às fotos, que podem ser compartilhados ou salvos localmente.
  • O FaceKat é um jogo de rastreamento de rostos criado com headtrackr.js.
  • A câmera ASCII usa a API Canvas para gerar imagens ASCII.
.
Imagem ASCII gerada por idevelop.ro/ascii-camera
arte ASCII de gUM!

Restrições

Restrições podem ser usadas a fim de definir valores de resolução de vídeo para getUserMedia(). Isso também permite suporte a outras restrições, como proporção; Modo voltado (câmera frontal ou traseira) frame rate, altura e largura. e um método applyConstraints().

Para ver um exemplo, consulte Amostras de WebRTC getUserMedia: selecionar resolução.

A definição de um valor de restrição não permitido vai gerar uma DOMException ou uma OverconstrainedError se, por exemplo, uma resolução solicitada não estiver disponível. Para ver isso em ação, consulte Exemplos de WebRTC getUserMedia: selecionar resolução para uma demonstração.

Captura de tela e guia

Os apps do Chrome também permitem compartilhar um vídeo ao vivo de uma única guia do navegador ou de toda a área de trabalho usando as APIs chrome.tabCapture e chrome.desktopCapture. Para uma demonstração e mais informações, consulte Compartilhamento de tela com WebRTC. O artigo é de alguns anos atrás, mas ainda é interessante.)

Também é possível usar a captura de tela como uma fonte MediaStream no Chrome usando a restrição chromeMediaSource experimental. Observe que a captura de tela exige HTTPS e só deve ser usada para desenvolvimento, porque está ativada por meio de uma sinalização de linha de comando, conforme explicado nesta postagem.

Sinalização: informações de controle de sessão, rede e mídia

O WebRTC usa RTCPeerConnection para comunicar dados de streaming entre navegadores (também conhecidos como pares), mas também precisa de um mecanismo para coordenar a comunicação e enviar mensagens de controle, um processo conhecido como sinalização. Os métodos e protocolos de sinalização não são especificados pelo WebRTC. A sinalização não faz parte da API RTCPeerConnection.

Em vez disso, os desenvolvedores de aplicativos WebRTC podem escolher o protocolo de mensagens que preferirem, como SIP ou XMPP, e qualquer canal de comunicação duplex (duas vias). O exemplo appr.tc usa XHR e a API de canais como mecanismo de sinalização. O codelab usa o Socket.io em execução em um servidor do nó.

A sinalização é usada para trocar três tipos de informações:

  • Mensagens de controle de sessão: para inicializar ou encerrar a comunicação e relatar erros.
  • Configuração da rede: para o mundo exterior, qual é o endereço IP e a porta do seu computador?
  • Recursos de mídia: quais codecs e resoluções podem ser gerenciados pelo navegador e pelo navegador com o qual ele deseja se comunicar?

A troca de informações por sinalização precisa ser concluída com sucesso antes que o streaming ponto a ponto possa começar.

Por exemplo, imagine que Alice quer se comunicar com Bob. Este é um exemplo de código da especificação WebRTC do W3C, que mostra o processo de sinalização em ação. O código pressupõe a existência de algum mecanismo de sinalização criado no método createSignalingChannel(). Observe também que no Chrome e no Opera, RTCPeerConnection está atualmente prefixado.

// 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);
  }
};

// Once 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);
  }
};

Primeiro, Alice e Bob trocam informações de rede. A expressão Encontrar candidatos se refere ao processo de encontrar interfaces e portas de rede usando o framework ICE.

  1. Alice cria um objeto RTCPeerConnection com um gerenciador onicecandidate, que é executado quando os candidatos à rede ficam disponíveis.
  2. Alice envia dados de candidatos serializados para Bob por qualquer canal de sinalização usado, como WebSocket ou outro mecanismo.
  3. Quando Bob recebe uma mensagem de candidato de Alice, ele chama addIceCandidate para adicionar o candidato à descrição do colega remoto.

Os clientes WebRTC (também conhecidos como peers, ou "Alice e Bob", neste exemplo) também precisam verificar e trocar informações locais e remotas de mídia de áudio e vídeo, como recursos de resolução e codec. A sinalização para trocar informações de configuração de mídia é realizada com a troca de uma oferta e uma resposta usando o Session Description Protocol (SDP):

  1. Alice executa o método RTCPeerConnection createOffer(). O resultado recebe uma RTCSessionDescription, a descrição da sessão local de Alice.
  2. No callback, Alice define a descrição local usando setLocalDescription() e envia a descrição da sessão a Beto pelo canal de sinalização. RTCPeerConnection não vai começar a coletar candidatos até que setLocalDescription() seja chamado. Isso está codificado no rascunho do IETF do JSEP.
  3. Bob define a descrição que Alice enviou a ele como a descrição remota usando setRemoteDescription().
  4. Bob executa o método createAnswer() do RTCPeerConnection, transmitindo a descrição remota que ele recebeu de Alice para que uma sessão local possa ser gerada e compatível com a dela. O callback createAnswer() recebe um RTCSessionDescription. Bob define isso como a descrição local e envia para Alice.
  5. Quando Alice recebe a descrição da sessão de Beto, ela a define como a descrição remota com setRemoteDescription.
  6. Ping!
.

Os objetos RTCSessionDescription são blobs que estão em conformidade com o Session Description Protocol (SDP). Serializado, um objeto SDP é semelhante ao seguinte:

v=0
o=- 3883943731 1 IN IP4 127.0.0.1
s=
t=0 0
a=group:BUNDLE audio video
m=audio 1 RTP/SAVPF 103 104 0 8 106 105 13 126

// ...

a=ssrc:2223794119 label:H4fjnMzxy3dPIgQ7HxuCTLb4wLLLeRHnFxh810

A aquisição e a troca de informações de rede e mídia podem ser feitas simultaneamente, mas ambos os processos precisam ser concluídos antes que o streaming de áudio e vídeo entre pares possa começar.

A arquitetura de oferta/resposta descrita anteriormente é chamada de Protocolo de estabelecimento de sessão JavaScript ou JSEP. Há uma excelente animação explicando o processo de sinalização e streaming no vídeo de demonstração do Ericsson para a primeira implementação do WebRTC.

Diagrama da arquitetura do JSEP
Arquitetura do JSEP

Depois que o processo de sinalização é concluído com sucesso, os dados podem ser transmitidos diretamente ponto a ponto, entre o autor da chamada e o recebedor da chamada ou, se isso falhar, por um servidor de redirecionamento intermediário. Falaremos mais sobre isso depois. Streaming é o trabalho de RTCPeerConnection.

RTCPeerConnection

RTCPeerConnection é o componente WebRTC que lida com a comunicação estável e eficiente de dados de streaming entre pares.

Veja a seguir um diagrama de arquitetura WebRTC mostrando o papel de RTCPeerConnection. Como você vai notar, as partes verdes são complexas!

Diagrama da arquitetura do WebRTC
Arquitetura WebRTC (de webrtc.org)

Do ponto de vista do JavaScript, o principal ponto que você precisa entender neste diagrama é que o RTCPeerConnection protege os desenvolvedores Web das inúmeras complexidades que espreitam por trás deles. Os codecs e protocolos usados pelo WebRTC realizam uma enorme quantidade de trabalho para viabilizar a comunicação em tempo real, mesmo em redes não confiáveis:

  • Ocultação da perda de pacotes
  • Cancelamento de eco
  • Adaptabilidade da largura de banda
  • Buffer de instabilidade dinâmico
  • Controle automático de ganho
  • Redução e supressão de ruído
  • Limpeza de imagens

O código W3C anterior mostra um exemplo simplificado de WebRTC de uma perspectiva de sinalização. A seguir, há tutoriais de dois apps WebRTC que funcionam. O primeiro é um exemplo simples para demonstrar RTCPeerConnection, e o segundo é um cliente de chat por vídeo totalmente operacional.

RTCPeerConnection sem servidores

O código a seguir foi extraído de amostras de WebRTC de conexão de peering, que tem RTCPeerConnection local e remoto (e vídeo local e remoto) em uma página da Web. Isso não é muito útil. O autor da chamada e o recebedor da chamada estão na mesma página, mas torna o funcionamento da API RTCPeerConnection um pouco mais claro, porque os objetos RTCPeerConnection na página podem trocar dados e mensagens diretamente sem precisar usar mecanismos de sinalização intermediários.

Neste exemplo, pc1 representa o app semelhante local (autor da chamada) e pc2 representa o participante remoto (pessoa que faz a chamada).

Autor da chamada

  1. Crie uma nova RTCPeerConnection e adicione o stream de getUserMedia(): ```js // "Servers" é um arquivo de configuração opcional. Consulte a discussão sobre TURN e STUN mais tarde. pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) =&gt; { pc1.addTrack(track, localStream); });
  1. Crie uma oferta e a defina como a descrição local para pc1 e como a descrição remota para pc2. Isso pode ser feito diretamente no código sem usar a sinalização porque o autor da chamada e o recebedor da chamada estão na mesma página: js pc1.setLocalDescription(desc).then(() => { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); trace('pc2 setRemoteDescription start'); pc2.setRemoteDescription(desc).then(() => { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError );

Pessoa que vai receber a chamada

  1. Crie pc2 e, quando o stream de pc1 for adicionado, mostre-o em um elemento de vídeo: js pc2 = new RTCPeerConnection(servers); pc2.ontrack = gotRemoteStream; //... function gotRemoteStream(e){ vid2.srcObject = e.stream; }

RTCPeerConnection mais servidores de API

No mundo real, o WebRTC precisa de servidores, mesmo que simples. Por isso, pode acontecer o seguinte:

  • Os usuários se descobrem e trocam detalhes do mundo real, como nomes.
  • Os apps clientes (peers) WebRTC trocam informações de rede.
  • Os colegas trocam dados sobre mídia, como formato e resolução de vídeo.
  • Os apps clientes WebRTC passam por gateways NAT e firewalls.

Em outras palavras, o WebRTC precisa de quatro tipos de funcionalidade do lado do servidor:

  • Descoberta e comunicação de usuários
  • Sinalização
  • Travessia de firewall/NAT
  • Servidores de redirecionamento em caso de falha na comunicação ponto a ponto

A travessia de NAT, as redes ponto a ponto e os requisitos para criar um aplicativo de servidor para descoberta e sinalização de usuários estão fora do escopo deste artigo. Basta dizer que o protocolo STUN e a extensão dele, TURN, são usados pelo framework ICE para permitir que o RTCPeerConnection lide com a travessia de NAT e outras variações de rede.

O ICE é uma estrutura para conectar pares, como dois clientes de chat por vídeo. Inicialmente, a ICE tenta conectar pares diretamente com a menor latência possível pelo UDP. Nesse processo, os servidores STUN têm uma única tarefa: permitir que um par por trás de um NAT descubra o endereço público e a porta. Para mais informações sobre o STUN e o TURN, consulte Criar os serviços de back-end necessários para um app WebRTC.

Encontrar candidatos a conexão
Como encontrar candidatos para conexão

Se o UDP falhar, a ICE tentará usar o TCP. Se a conexão direta falhar, especialmente por causa da travessia de NAT da empresa e de firewalls, a ICE usa um servidor TURN intermediário (retransmissão). Em outras palavras, primeiro a ICE usa o STUN com o UDP para conectar diretamente os pares e, se isso falhar, volta para um servidor de redirecionamento TURN. A expressão como encontrar candidatos se refere ao processo de encontrar interfaces e portas de rede.

Caminhos de dados WebRTC
Caminhos de dados WebRTC

O engenheiro do WebRTC Justin Uberti fornece mais informações sobre ICE, STUN e TURN na apresentação WebRTC do Google I/O 2013 (em inglês). Os slides da apresentação mostram exemplos de implementações de servidor TURN e STUN.

Um cliente simples de chat por vídeo

Um bom lugar para testar o WebRTC, com sinalização e travessia de NAT/firewall usando um servidor STUN, é a demonstração do chat por vídeo em appr.tc. Este app usa o adapter.js, um paliativo para isolar apps de mudanças nas especificações e diferenças de prefixo.

O código é deliberadamente detalhado em registro. Verifique o console para entender a ordem dos eventos. Confira a seguir um tutorial detalhado do código.

Topologias de rede

O WebRTC, conforme implementado atualmente, só oferece suporte à comunicação um para um, mas pode ser usado em cenários de rede mais complexos, como com vários pares, cada um se comunicando diretamente entre si ou por uma unidade de controle multiponto (MCU, na sigla em inglês), um servidor que pode lidar com um grande número de participantes e fazer encaminhamento de stream seletivo, além de mixar ou gravar áudio e vídeo.

Diagrama de topologia da unidade de controle multiponto
Exemplo de topologia de unidade de controle multiponto

Muitos apps WebRTC atuais só demonstram comunicação entre navegadores da Web, mas os servidores de gateway podem permitir que um app WebRTC em execução em um navegador interaja com dispositivos, como telefones (também conhecidos como PSTN) e com sistemas VOIP. Em maio de 2012, a Doubango Telecom abriu o código do cliente SIP SIP 5 criado com WebRTC e WebSocket, que (entre outros possíveis usos) permite videochamadas entre navegadores e aplicativos executados em iOS e Android. No Google I/O, o Tethr e o Tropo demonstraram um framework para comunicações de desastres em uma pasta usando uma celular do OpenBTS (link em inglês) para permitir a comunicação entre feature phone e computadores pelo WebRTC. Comunicação por telefone sem uma operadora!

Demonstração de Tethr/Tropo no Google I/O 2012
Tethr/Tropo: comunicações sobre desastres em uma pasta

API RTCDataChannel<

Assim como áudio e vídeo, o WebRTC oferece suporte à comunicação em tempo real para outros tipos de dados.

A API RTCDataChannel permite a troca ponto a ponto de dados arbitrários com baixa latência e alta capacidade de processamento. Para demonstrações de página única e para aprender a criar um app simples de transferência de arquivos, consulte os exemplos de WebRTC e o codelab de WebRTC (links em inglês), respectivamente.

Há muitos casos de uso em potencial para a API, incluindo:

  • Jogos
  • Apps da área de trabalho remota
  • Chat de texto em tempo real
  • Transferência de arquivo
  • Redes descentralizadas

A API tem vários recursos para aproveitar ao máximo o RTCPeerConnection e permitir uma comunicação ponto a ponto avançada e flexível:

  • Aproveitando a configuração da sessão RTCPeerConnection
  • Vários canais simultâneos com priorização
  • Semântica de entrega confiável e não confiável
  • Segurança integrada (DTLS) e controle de congestionamento
  • Capacidade de usar com ou sem áudio ou vídeo

A sintaxe é deliberadamente semelhante à WebSocket com um método send() e um evento message:

const localConnection = new RTCPeerConnection(servers);
const remoteConnection = new RTCPeerConnection(servers);
const sendChannel =
  localConnection.createDataChannel('sendDataChannel');

// ...

remoteConnection.ondatachannel = (event) => {
  receiveChannel = event.channel;
  receiveChannel.onmessage = onReceiveMessage;
  receiveChannel.onopen = onReceiveChannelStateChange;
  receiveChannel.onclose = onReceiveChannelStateChange;
};

function onReceiveMessage(event) {
  document.querySelector("textarea#send").value = event.data;
}

document.querySelector("button#send").onclick = () => {
  var data = document.querySelector("textarea#send").value;
  sendChannel.send(data);
};

A comunicação ocorre diretamente entre navegadores, portanto, o RTCDataChannel pode ser muito mais rápido que o WebSocket, mesmo que um servidor de redirecionamento (TURN) seja necessário para lidar com falhas em firewalls e NATs.

O RTCDataChannel está disponível para Chrome, Safari, Firefox, Opera e Samsung Internet. O jogo Cube Slam usa a API para comunicar o estado do jogo. Jogue com um amigo ou com o urso! A plataforma inovadora Sharefest, que permite o compartilhamento de arquivos por RTCDataChannel e peerCDN, ofereceu uma visão geral de como o WebRTC poderia permitir a distribuição de conteúdo ponto a ponto.

Para saber mais sobre o RTCDataChannel, confira a especificação do protocolo de rascunho do IETF.

Segurança

Um plug-in ou app de comunicação em tempo real pode comprometer a segurança de várias maneiras. Exemplo:

  • Mídia ou dados não criptografados podem ser interceptados entre navegadores ou entre um navegador e um servidor.
  • Um app pode gravar e distribuir vídeo ou áudio sem que o usuário saiba.
  • Malware ou vírus podem estar instalados junto com um plug-in ou aplicativo aparentemente inofensivo.

O WebRTC tem vários recursos para evitar esses problemas:

  • As implementações WebRTC usam protocolos seguros, como DTLS e SRTP.
  • A criptografia é obrigatória para todos os componentes WebRTC, inclusive os mecanismos de sinalização.
  • O WebRTC não é um plug-in. Seus componentes são executados na sandbox do navegador e não em um processo separado. Os componentes não exigem instalação separada e são atualizados sempre que o navegador é atualizado.
  • O acesso à câmera e ao microfone precisa ser concedido de maneira explícita e, quando a câmera ou o microfone estão em execução, isso é claramente exibido na interface do usuário.

Uma discussão completa sobre a segurança para streaming de mídia está fora do escopo deste artigo. Para mais informações, consulte a Arquitetura de segurança proposta do WebRTC proposta pelo IETF.

Conclusão

As APIs e os padrões do WebRTC podem democratizar e descentralizar as ferramentas de comunicação e criação de conteúdo, incluindo telefonia, jogos, produção de vídeos, produção de músicas e coleta de notícias.

A tecnologia não é muito mais disruptiva.

Como o blogueiro Phil Edholm colocou, "Potencialmente, WebRTC e HTML5 poderiam permitir a mesma transformação para a comunicação em tempo real que o navegador original fez para informações".

Ferramentas para desenvolvedores

Saiba mais

Padrões e protocolos

Resumo do suporte do WebRTC

APIs MediaStream e getUserMedia

  • Chrome para computador 18.0.1008 e mais recente; Chrome para Android 29 e mais recentes
  • Opera 18 e superior Opera para Android 20 e versões mais recentes
  • Opera 12, Opera Mobile 12 (baseado no mecanismo Presto)
  • Firefox 17 e mais recente
  • Microsoft Edge 16 e mais recentes
  • Safari 11.2 e superior no iOS e 11.1 e superior no MacOS
  • UC 11.8 e mais recentes no Android
  • Samsung Internet 4 e mais recente

API RTCPeerConnection.

  • Chrome para computador 20 e superior Chrome para Android 29 e versões mais recentes (sem sinalização)
  • Opera 18 e mais recentes (ativado por padrão); Opera para Android 20 e versões mais recentes (ativado por padrão)
  • Firefox 22 e superior (ativado por padrão)
  • Microsoft Edge 16 e mais recentes
  • Safari 11.2 e superior no iOS e 11.1 e superior no MacOS
  • Samsung Internet 4 e mais recente

API RTCDataChannel.

  • Versão experimental no Chrome 25, mas mais estável (e com interoperabilidade com o Firefox) no Chrome 26 e superior Chrome para Android 29 e mais recentes
  • Versão estável (e com interoperabilidade com o Firefox) no Opera 18 e mais recentes Opera para Android 20 e versões mais recentes
  • Firefox 22 e superior (ativado por padrão)

Para informações mais detalhadas sobre o suporte multiplataforma para APIs, como getUserMedia e RTCPeerConnection, consulte caniuse.com e Status da plataforma do Chrome (links em inglês).

As APIs nativas do RTCPeerConnection também estão disponíveis na documentação em webrtc.org (link em inglês).