Começar a usar o WebRTC

O WebRTC é uma nova frente na longa guerra por uma Web aberta e livre.

Brendan Eich, inventor do JavaScript

Comunicação em tempo real sem plug-ins

Imagine um mundo onde seu smartphone, sua TV e seu computador possam 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 computador e dispositivos móveis no Google Chrome, Safari, Firefox e Opera. Um bom ponto de partida é o aplicativo simples de chat por vídeo em appr.tc:

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

Início rápido

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

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

Uma história muito curta do WebRTC

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

Historicamente, o RTC é empresarial e complexo, exigindo tecnologias caras de áudio e vídeo para serem licenciadas ou desenvolvidas internamente. Integrar a tecnologia RTC aos conteúdos, dados e serviços existentes tem sido difícil e demorado, principalmente na Web.

O bate-papo por vídeo do Gmail se tornou popular em 2008 e, em 2011, o Google lançou o Hangouts, que usa o Talk (assim como o Gmail). O Google comprou o GIPS, uma empresa que desenvolveu vários 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 interagiu com órgãos de normalização relevantes da Internet Engineering Task Force (IETF) e do 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 sem plug-ins. A necessidade era real:

  • Muitos serviços da Web usavam o RTC, mas precisavam de downloads, aplicativos nativos ou plug-ins. Entre elas, o Skype, o Facebook e o Hangouts.
  • Fazer o download, instalar e atualizar plug-ins é complexo, propenso a erros e irritante.
  • Os plug-ins são difíceis de implantar, depurar, solucionar problemas, testar e manter, e podem exigir licenciamento e integração com tecnologia complexa e cara. Muitas vezes, é difícil persuadir as pessoas a instalar plug-ins.

Os princípios orientadores do projeto WebRTC são que as APIs devem ser de código aberto, sem custo financeiro, padronizadas, incorporadas a 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) - RTCPeerConnection - RTCDataChannel

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

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

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

RTCPeerConnection: para ver uma demonstração simples e um app de chat por vídeo totalmente funcional, consulte WebRTC exemplos de conexão de peering e appr.tc, respectivamente. Esse app usa o adapter.js, um paliativo JavaScript mantido pelo Google com a ajuda da comunidade WebRTC, para abstrair as diferenças do navegador e as mudanças nas especificações.

RTCDataChannel: para ver isso em ação, consulte exemplos de WebRTC para conferir uma das demonstrações do canal de dados.

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

Seu primeiro WebRTC

Os apps WebRTC precisam fazer várias coisas:

  • Receber streaming de áudio, vídeo e outros dados.
  • Receba informações de rede, como endereços IP e portas, 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 da 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.
  • Transmitir 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 videochamadas com recursos de criptografia e gerenciamento de largura de banda.
  • O RTCDataChannel permite a comunicação ponto a ponto de dados genéricos.

Você verá uma discussão detalhada sobre os aspectos de rede e sinalização do WebRTC posteriormente.

API MediaStream (também conhecida como API getUserMedia)

A API MediaStream representa fluxos de mídia sincronizados. Por exemplo, um stream feito com a câmera e o 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 é analisá-la:

  1. No navegador, acesse os 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 se refere a um objeto MediaStream.

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

No exemplo de getUserMedia, stream.getAudioTracks() retorna uma matriz vazia (porque não há áudio) e, supondo que uma webcam esteja conectada, stream.getVideoTracks() retorna uma matriz de uma MediaStreamTrack representando a transmissão 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. Nesse 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 streamings da câmera frontal, da câmera traseira, do microfone e de um app que compartilha a tela.

Para anexar um MediaStream a um elemento de vídeo, defina o atributo srcObject. Antes, isso era feito definindo o atributo src como um URL de objeto criado com URL.createObjectURL(), mas isso foi descontinuado.

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 ela seja solicitada e concedida apenas uma vez na instalação. Depois disso, a permissão de acesso à câmera ou ao microfone não vai ser solicitada.

A permissão só precisa ser concedida uma vez para getUserMedia(). Na primeira vez, um botão "Permitir" é exibido na barra de informações do navegador. O acesso HTTP para getUserMedia() foi descontinuado 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 um microfone. Isso permitiria o streaming de dados armazenados ou fontes de dados arbitrárias, como sensores ou outras entradas.

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

  • O Webcam Toy é um app de cabine de fotos que usa WebGL para adicionar efeitos estranhos e maravilhosos às fotos que podem ser compartilhadas ou salvas localmente.
  • O FaceKat é um jogo de rastreamento facial 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 do gom!

Restrições

Restrições podem ser usadas para 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().

Por exemplo, consulte Exemplos de WebRTC getUserMedia: selecionar resolução.

Definir um valor de restrição não permitido vai fornecer uma DOMException ou um 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 ver 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 tem alguns anos, mas ainda é interessante.)

Também é possível usar a captura de tela como uma fonte MediaStream no Chrome com a restrição experimental chromeMediaSource. A captura de tela exige HTTPS e só deve ser usada para desenvolvimento por ser ativada por 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 (duplex) adequado. O exemplo appr.tc usa o XHR e a API Channel como mecanismo de sinalização. O codelab usa o Socket.io (em inglês) em execução em um servidor de nó.

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

  • Mensagens de controle de sessão: para inicializar ou fechar a comunicação e relatar erros.
  • Configuração de 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 manipulados pelo seu navegador e pelo navegador com o qual ele deseja se comunicar?

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

Por exemplo, imagine que Alice quer se comunicar com Bob. Veja um exemplo de código da especificação WebRTC do W3C (em inglês), 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(). No Chrome e no Opera, RTCPeerConnection é prefixado atualmente.

// 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 Beto trocam informações de rede. A expressão encontrar candidatos refere-se 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 que estiver usando, como WebSocket ou outro mecanismo.
  3. Quando Bob recebe uma mensagem candidata a Alice, ele chama addIceCandidate para adicionar o candidato à descrição do peering 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 resolução e recursos de codec. A sinalização para trocar informações de configuração de mídia troca uma oferta e uma resposta usando o protocolo de descrição da sessão (SDP, na sigla em inglês):

  1. Alice executa o método RTCPeerConnection createOffer(). O retorno recebe um RTCSessionDescription, que é a descrição da sessão local de Alice.
  2. No callback, Alice define a descrição local usando setLocalDescription() e, em seguida, envia a descrição dessa sessão a Bob pelo canal de sinalização. Observe que RTCPeerConnection não começará a reunir candidatos até que setLocalDescription() seja chamado. Isso está codificado no rascunho do JSEP IETF.
  3. Bob define a descrição que Alice enviou como a descrição remota usando setRemoteDescription().
  4. Bob executa o método createAnswer() RTCPeerConnection, transmitindo a descrição remota que ele recebeu da Alice para que seja gerada uma sessão local compatível com a dela. O callback createAnswer() recebe um RTCSessionDescription. Bob define isso como a descrição local e a envia para Alice.
  5. Quando Alice recebe a descrição da sessão de Bob, 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 Protocolo de descrição da sessão (SDP). Serializado, um objeto SDP tem a seguinte aparência:

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 os pares possa começar.

A arquitetura de oferta/resposta descrita anteriormente é chamada JavaScript Session Estament Protocol, ou JSEP. Há uma excelente animação explicando o processo de sinalização e streaming no vídeo de demonstração do Ericsson (em inglês) para a primeira implementação do WebRTC.

Diagrama da arquitetura do JSEP
Arquitetura do JSEP

Quando 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 (vamos saber mais sobre isso depois). O streaming é o job 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 que mostra o papel de RTCPeerConnection. Como você notará, as partes verdes são complexas!

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

Do ponto de vista do JavaScript, o principal elemento a entender nesse diagrama é que o RTCPeerConnection protege os desenvolvedores da Web das inúmeras complexidades que estão por trás. Os codecs e protocolos usados pelo WebRTC fazem um enorme trabalho para possibilitar 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âmica
  • 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. Confira a seguir instruções 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 retirado de exemplos de WebRTC para 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, porque o autor da chamada e o recebedor da chamada estão na mesma página, mas deixa 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 peering local (autor da chamada) e pc2 representa o peering remoto (recebedor da chamada).

Autor da chamada

  1. Crie um novo RTCPeerConnection e adicione o stream de getUserMedia(): ```js // "Servidores" é um arquivo de configuração opcional. (Consulte a discussão sobre TURN e STUN mais tarde.) pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEvery((track) => { 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 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 );

Destinatário da 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; }

API RTCPeerConnection mais servidores

No mundo real, o WebRTC precisa de servidores, por mais simples que seja, então pode acontecer o seguinte:

  • Os usuários se descobrem e trocam detalhes do mundo real, como nomes.
  • Apps clientes WebRTC (pares) trocam informações de rede.
  • Os pares trocam dados sobre mídia, como formato e resolução do vídeo.
  • Os apps cliente 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 NAT/firewall
  • Servidores de redirecionamento caso a comunicação ponto a ponto falhe

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

A ICE é um framework para conectar pontos, como dois clientes de chat por vídeo. Inicialmente, a ICE tenta conectar pares diretamente com a menor latência possível por UDP. Nesse processo, os servidores STUN têm uma única tarefa: permitir que um terminal atrás de um NAT descubra seu endereço público e 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.

Como encontrar candidatos à conexão
Como encontrar candidatos para conexão

Se o UDP falhar, o ICE tentará usar o TCP. Se a conexão direta falhar, principalmente devido à travessia de NAT empresarial e a firewalls, o ICE usa um servidor TURN intermediário (redirecionamento). Em outras palavras, o ICE primeiro usa o STUN com UDP para conectar pontos diretamente e, em caso de falha, recorre a um servidor de redirecionamento TURN. A expressão encontrar candidatos refere-se 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 de 2013 (em inglês). Os slides da apresentação mostram exemplos de implementações de servidores TURN e STUN.

Um cliente simples de chat por vídeo

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

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

Topologias de rede

O WebRTC, atualmente implementado, só oferece suporte à comunicação um para um, mas pode ser usado em cenários de rede mais complexos, como quando vários pares se comunicam 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 o encaminhamento seletivo de stream, além de misturar ou gravar áudio e vídeo.

Diagrama da topologia da unidade de controle multiponto
Exemplo de topologia de unidade de controle de vários pontos

Muitos aplicativos WebRTC existentes demonstram apenas a comunicação entre navegadores da Web, mas os servidores de gateway podem permitir que um aplicativo WebRTC em execução em um navegador interaja com dispositivos, como telefones (também conhecidos como RPTC) e com sistemas VOIP. Em maio de 2012, a Doubango Telecom abriu o código do cliente SIP SIP5 criado com WebRTC e WebSocket, que (entre outros possíveis usos) permite videochamadas entre navegadores e apps em execução no iOS e no Android. No Google I/O, a Tethr e a Tropo demonstraram um framework para comunicações de desastres em uma pasta usando uma célula OpenBTS para possibilitar a comunicação entre feature phone e computadores pelo WebRTC. Comunicação telefônica sem operadora!

Demonstração do 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 suporta 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. Para ver demonstrações de uma única página e aprender a criar um app simples de transferência de arquivos, consulte os exemplos de WebRTC e o codelab de WebRTC, respectivamente.

Existem muitos casos de uso potenciais para a API, incluindo:

  • Jogos
  • Apps da Área de trabalho remota
  • Bate-papo por texto em tempo real
  • Transferência de arquivo
  • Redes descentralizadas

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

  • Uso da configuração de sessão de 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
  • Uso 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 os navegadores, de modo que o RTCDataChannel pode ser muito mais rápido que o WebSocket, mesmo que um servidor de redirecionamento (TURN) seja necessário quando a furação para lidar com firewalls e NATs falhar.

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 permitiu o compartilhamento de arquivos por RTCDataChannel e peerCDN, deu uma ideia de como o WebRTC poderia permitir a distribuição de conteúdo ponto a ponto.

Para mais informações sobre o RTCDataChannel, confira a especificação do protocolo de rascunho (em inglês) do IETF.

Segurança

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

  • Mídias 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 ser instalados junto com um plug-in ou app 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, incluindo mecanismos de sinalização.
  • WebRTC não é um plug-in. Os componentes dele 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 explicitamente e, quando a câmera ou o microfone estão em execução, isso é claramente mostrado pela interface do usuário.

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

Conclusão

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

A tecnologia não é muito mais disruptiva do que isso.

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

Ferramentas para desenvolvedores

Saiba mais

Padrões e protocolos

Resumo do suporte WebRTC

APIs MediaStream e getUserMedia

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

API RTCPeerConnection.

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

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 superior
  • Versão estável (com interoperabilidade com o Firefox) no Opera 18 e mais recentes; Opera para Android 20 e mais recentes
  • Firefox 22 e mais recentes (ativado por padrão)

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

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