Começar a usar o WebRTC

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

Brendan Eich, inventor do JavaScript

Comunicação em tempo real sem plug-ins

Imagine um mundo em que seu smartphone, TV e computador possam se comunicar em uma plataforma comum. Imagine que é fácil adicionar chat por vídeo e 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 em computadores e dispositivos móveis no Google Chrome, Safari, Firefox e Opera. Um bom lugar para começar é o app de chat por vídeo simples 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 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 só quer o código?

Como alternativa, acesse diretamente o codelab do WebRTC, um guia detalhado que explica como criar um app de chat por vídeo completo, incluindo um servidor de sinalização simples.

Uma breve história do WebRTC

Um dos últimos grandes desafios da Web é permitir a comunicação humana por voz e vídeo: comunicação em tempo real ou RTC, na sigla em inglês. O RTC precisa ser tão natural em um app da Web quanto digitar texto em uma entrada de texto. Sem ela, sua capacidade de inovar e desenvolver novas maneiras de interação das pessoas é limitada.

Historicamente, o RTC era corporativo e complexo, exigindo que tecnologias de áudio e vídeo caras fossem licenciadas ou desenvolvidas internamente. A integração da tecnologia RTC com conteúdo, dados e serviços existentes tem sido difícil e demorado, principalmente na Web.

O chat 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 a GIPS, uma empresa que desenvolveu muitos componentes necessários para o RTC, como codecs e técnicas de cancelamento de eco. O Google disponibilizou em código aberto as tecnologias desenvolvidas pelo GIPS e se envolveu com os órgãos de padrões relevantes do 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, apps nativos ou plug-ins. Isso incluiu o Skype, o Facebook e o Hangouts.
  • Fazer o download, instalar e atualizar plug-ins é um processo complexo, propenso a erros e irritante.
  • Os plug-ins são difíceis de implantar, depurar, resolver problemas, testar e manter e podem exigir licenciamento e integração com tecnologias complexas e caras. Muitas vezes, é difícil convencer as pessoas a instalar plugins.

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

Onde estamos agora?

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

O WebRTC implementa estas três APIs: - MediaStream (também conhecida como getUserMedia) - RTCPeerConnection - RTCDataChannel

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

Todas as três APIs têm suporte para dispositivos móveis e computadores com Chrome, Safari, Firefox, Edge e Opera.

getUserMedia: para demonstrações e código, consulte Exemplos do WebRTC ou confira os exemplos incríveis de Chris Wilson que usam getUserMedia como entrada para áudio da Web.

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

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

O codelab do 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 do WebRTC precisam fazer várias coisas:

  • Receber áudio, vídeo ou outros dados por streaming.
  • Receber informações de rede, como endereços IP e portas, e trocá-las com outros clientes do WebRTC (conhecidos como peers) para permitir a conexão, mesmo por NATs e firewalls.
  • coordenar a comunicação de sinalização para informar erros e iniciar ou encerrar sessões.
  • Troca de informações sobre mídia e recursos do cliente, como resolução e codecs.
  • Transmitir áudio, vídeo ou dados.

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

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

Mais adiante, vamos discutir em detalhes os aspectos de rede e sinalização do WebRTC.

API MediaStream (também conhecida como API getUserMedia)

A API MediaStream representa streams de mídia sincronizados. Por exemplo, um stream feito a partir da entrada da câmera e do microfone tem faixas de vídeo e áudio sincronizadas. Não confunda MediaStreamTrack com o elemento <track>, que é completamente diferente.

A maneira mais fácil de entender a API MediaStream é analisar o uso dela:

  1. No navegador, acesse Exemplos do 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 uma RTCPeerConnection.

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

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

No exemplo 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 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. 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 transmissões da câmera frontal, da câmera traseira, do microfone e um app que compartilha a tela.

Um MediaStream pode ser anexado a um elemento de vídeo definindo o atributo srcObject. Antes, isso era feito definindo o atributo src como um URL de objeto criado com URL.createObjectURL(), mas essa prática foi descontinuada.

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

As extensões e os apps baseados no Chromium também podem incorporar getUserMedia. Adicionar as permissões audioCapture e/ou videoCapture ao manifesto permite que a permissão seja solicitada e concedida apenas uma vez durante a instalação. Depois disso, a permissão para acessar a câmera ou o microfone não é solicitada ao usuário.

A permissão só precisa ser concedida uma vez para getUserMedia(). Na primeira vez, um botão "Permitir" é exibido na infobar do navegador. O acesso HTTP para getUserMedia() foi descontinuado pelo Chrome no final de 2015 porque foi classificado como um recurso poderoso.

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

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

  • O Webcam Toy é um app de cabine fotográfica que usa o WebGL para adicionar efeitos estranhos e incríveis a fotos que podem ser compartilhadas ou salvas localmente.
  • FaceKat é um jogo de rastreamento facial criado com headtrackr.js.
  • A ASCII Camera usa a API Canvas para gerar imagens ASCII.
Imagem ASCII gerada por idevelop.ro/ascii-camera
Um ASCII art!

Restrições

As 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 de orientação (câmera frontal ou traseira), frame rate, altura e largura e um método applyConstraints().

Para conferir um exemplo, consulte Exemplos de WebRTC getUserMedia: selecione a resolução.

A definição de um valor de restrição não permitido gera uma DOMException ou uma OverconstrainedError se, por exemplo, uma resolução solicitada não estiver disponível. Para conferir isso em ação, consulte Exemplos de WebRTC getUserMedia: selecione a resolução para conferir 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 o WebRTC. O artigo tem alguns anos, mas ainda é interessante.)

Também é possível usar a captura de tela como uma origem de MediaStream no Chrome usando a restrição experimental chromeMediaSource. A captura de tela exige HTTPS e só deve ser usada para desenvolvimento, porque é ativada por uma flag de linha de comando, conforme explicado neste post.

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 apps do WebRTC podem escolher o protocolo de mensagens que preferirem, como SIP ou XMPP, e qualquer canal de comunicação duplex (bidirecional) adequado. O exemplo appr.tc usa XHR e a API Channel como mecanismo de sinalização. O codelab usa o Socket.io em execução em um servidor do Node.

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 informar erros.
  • Configuração de rede: qual é o endereço IP e a porta do seu computador para o mundo externo?
  • Recursos de mídia: quais codecs e resoluções podem ser processados pelo seu navegador e pelo navegador com que ele quer se comunicar?

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

Por exemplo, imagine que Alice quer se comunicar com Bob. Confira um exemplo de código da especificação do 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(). Além disso, no Chrome e no Opera, RTCPeerConnection tem um prefixo.

// 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 de rede e portas usando a estrutura ICE.

  1. Alice cria um objeto RTCPeerConnection com um gerenciador onicecandidate, que é executado quando os candidatos de rede ficam disponíveis.
  2. Alice envia dados candidatos serializados para Bob por qualquer canal de sinalização que esteja usando, 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 peer remoto.

Os clientes do WebRTC (também conhecidos como pares, ou Alice e Bob neste exemplo) também precisam determinar e trocar informações de mídia de áudio e vídeo locais e remotas, como resolução e recursos de codec. A sinalização para trocar informações de configuração de mídia é feita trocando uma oferta e uma resposta usando o Protocolo de Descrição de Sessão (SDP):

  1. A Alice executa o método createOffer() RTCPeerConnection. O retorno é transmitido a uma RTCSessionDescription, a descrição da sessão local de Alice.
  2. No callback, Alice define a descrição local usando setLocalDescription() e envia essa descrição de sessão para Bob 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 JSEP IETF.
  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() RTCPeerConnection, transmitindo a descrição remota que ele recebeu de Alice para que uma sessão local possa ser gerada e seja 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 de sessão (SDP). Um objeto SDP serializado tem esta 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 pares possa começar.

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

Diagrama de arquitetura do JSEP
Arquitetura JSEP

Depois que o processo de sinalização for concluído, os dados poderão ser transmitidos diretamente de um peer para outro, entre o autor da chamada e o destinatário, ou, se isso falhar, por um servidor de retransmissão intermediário (mais detalhes a seguir). O streaming é o trabalho de RTCPeerConnection.

RTCPeerConnection

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

Confira a seguir um diagrama de arquitetura do WebRTC que mostra a função de RTCPeerConnection. As partes verdes são complexas.

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

Do ponto de vista do JavaScript, a principal coisa a entender neste diagrama é que 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 trabalho enorme para tornar possível a comunicação em tempo real, mesmo em redes não confiáveis:

  • Ocultar perda de pacotes
  • Cancelamento de eco
  • Adaptabilidade de largura de banda
  • Armazenamento em buffer de instabilidade dinâmica
  • Controle automático de ganho
  • Redução e supressão de ruído
  • Limpeza de imagem

O código anterior do W3C mostra um exemplo simplificado do WebRTC do ponto de vista da sinalização. Confira a seguir os tutoriais de dois apps WebRTC em funcionamento. 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 é retirado de Exemplos de conexão de peer do WebRTC, que tem RTCPeerConnection e remoto local (e vídeo local e remoto) em uma página da Web. Isso não é muito útil, porque o autor da chamada e o chamado 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 peer local (autor da chamada) e pc2 representa o peer remoto (destinatário).

Autor da chamada

  1. Crie um novo RTCPeerConnection e adicione a transmissão de getUserMedia(): ```js // Servers é um arquivo de configuração opcional. (Consulte a discussão sobre TURN e STUN mais adiante.) pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) => { pc1.addTrack(track, localStream); });
  1. Crie uma oferta e defina-a como a descrição local de pc1 e a descrição remota de pc2. Isso pode ser feito diretamente no código sem usar sinalização, porque o autor da chamada e o destinatário 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 );

Chamada

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

RTCPeerConnection API plus servidores

No mundo real, o WebRTC precisa de servidores, por mais simples que sejam, para que o seguinte possa acontecer:

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

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

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

A travessia de NAT, a rede ponto a ponto e os requisitos para criar um app 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 TURN são usados pelo framework ICE para permitir que RTCPeerConnection lide com a travessia de NAT e outras variações de rede.

O ICE é um framework para conectar pares, como dois clientes de chat por vídeo. Inicialmente, o 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 peer atrás de um NAT descubra o endereço e a porta públicos. Para mais informações sobre STUN e TURN, consulte Criar os serviços de back-end necessários para um app WebRTC.

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

Se o UDP falhar, o ICE vai tentar o TCP. Se a conexão direta falhar, principalmente devido a travessias NAT corporativas e firewalls, o ICE vai usar um servidor TURN intermediário (relay). Em outras palavras, o ICE primeiro usa STUN com UDP para conectar pares diretamente e, se isso falhar, volta para um servidor de retransmissão TURN. A expressão encontrar candidatos se refere ao processo de encontrar interfaces e portas de rede.

Caminhos de dados do WebRTC
Caminhos de dados do WebRTC

O engenheiro do WebRTC Justin Uberti fornece mais informações sobre ICE, STUN e TURN na apresentação do WebRTC do Google I/O de 2013. 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 experimentar o WebRTC, 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 adapter.js, um paliativo para isolar apps de mudanças de especificação e diferenças de prefixo.

O código é deliberadamente detalhado no 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, oferece suporte apenas à comunicação individual, mas pode ser usado em cenários de rede mais complexos, como com vários pares que se comunicam diretamente 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 transmissão seletivo, além de mixagem ou gravação de áudio e vídeo.

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

Muitos apps WebRTC existentes demonstram apenas a 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 disponibilizou o cliente SIP sipml5 (em inglês) de código aberto, criado com o WebRTC e o WebSocket. Entre outros usos, ele permite fazer chamadas de vídeo entre navegadores e apps executados no iOS e no Android. No Google I/O, a Tethr e a Tropo demonstraram um framework para comunicações em caso de desastres em uma pasta usando uma célula OpenBTS para permitir a comunicação entre feature phones e computadores pelo WebRTC. Comunicação telefônica sem operadora

Demonstração do Tethr/Tropo no Google I/O 2012
Tethr/Tropo: comunicações de desastre em um estojo

API RTCDataChannel<

Além de á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 alto rendimento. Para ver demonstrações de uma página só e aprender a criar um app simples de transferência de arquivos, consulte os exemplos do WebRTC e o codelab do WebRTC, respectivamente.

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

  • Jogos
  • Apps de á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 poderosa e flexível:

  • Como aproveitar 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
  • Controle de congestionamento e segurança integrada (DTLS)
  • Possibilidade de uso com ou sem áudio ou vídeo

A sintaxe é deliberadamente semelhante ao 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. Portanto, o RTCDataChannel pode ser muito mais rápido que o WebSocket, mesmo que um servidor de retransmissão (TURN) seja necessário quando a perfuração de buracos falhar para lidar com firewalls e NATs.

O RTCDataChannel está disponível no Chrome, Safari, Firefox, Opera e Samsung Internet. O jogo Cube Slam usa a API para comunicar o estado do jogo. Escolha um amigo ou o urso! A plataforma inovadora Sharefest permitiu o compartilhamento de arquivos por RTCDataChannel, e o peerCDN ofereceu um vislumbre de como o WebRTC pode permitir a distribuição de conteúdo ponto a ponto.

Para mais informações sobre RTCDataChannel, consulte o draft spec do protocolo do IETF.

Segurança

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

  • Dados ou mídias 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 com um plug-in ou app aparentemente inofensivo.

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

  • As implementações do WebRTC usam protocolos seguros, como DTLS e SRTP.
  • A criptografia é obrigatória para todos os componentes do WebRTC, incluindo mecanismos de sinalização.
  • O WebRTC não é um plug-in. Os componentes são executados no sandbox do navegador, e não em um processo separado. Os componentes não precisam de 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 é mostrado claramente pela interface do usuário.

Uma discussão completa sobre a segurança de mídia de streaming está fora do escopo deste artigo. Para mais informações, consulte a proposta de arquitetura de segurança do WebRTC (link em inglês) proposta pelo IETF.

Conclusão

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

A tecnologia não poderia ser mais disruptiva do que isso.

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

Ferramentas para desenvolvedores

Saiba mais

Padrões e protocolos

Resumo de suporte do WebRTC

APIs MediaStream e getUserMedia

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

API RTCPeerConnection.

  • Chrome para área de trabalho 20 e versões mais recentes; Chrome para Android 29 e versões mais recentes (sem flag)
  • Opera 18 e mais recentes (ativado por padrão); Opera para Android 20 e mais recentes (ativado por padrão)
  • Firefox 22 e versões mais recentes (ativado por padrão)
  • Microsoft Edge 16 e versões mais recentes
  • Safari 11.2 e mais recentes no iOS e 11.1 e mais recentes no MacOS
  • Samsung Internet 4 e versões mais recentes

API RTCDataChannel.

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

Para informações mais detalhadas sobre o suporte multiplataforma a APIs, como getUserMedia e RTCPeerConnection, consulte caniuse.com e Status da plataforma do Chrome.

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