Cómo comenzar a usar WebRTC

WebRTC es un nuevo frente en la larga guerra por una Web abierta y sin restricciones.

Brendan Eich, inventor de JavaScript

Comunicación en tiempo real sin complementos

Imagina un mundo en el que tu teléfono, tu TV y tu computadora puedan comunicarse en una plataforma común. Imagina que fue fácil agregar el chat de video y el uso compartido de datos entre pares a tu aplicación web. Esa es la visión de WebRTC.

¿Quieres probarla? WebRTC está disponible para computadoras de escritorio y dispositivos móviles en Google Chrome, Safari, Firefox y Opera. Un buen punto de partida es la app de videochat en appr.tc:

  1. Abre appr.tc en el navegador.
  2. Haz clic en Unirse para unirte a una sala de chat y dejar que la app use tu cámara web.
  3. Abre la URL que se muestra al final de la página en una pestaña nueva o, mejor aún, en otra computadora.

Inicio rápido

¿No tienes tiempo para leer este artículo o solo quieres código?

Como alternativa, puedes ir directamente al codelab de WebRTC, una guía paso a paso en la que se explica cómo compilar una app de videochat completa, incluido un servidor de señalización simple.

Una breve historia de WebRTC

Uno de los últimos desafíos más importantes para la Web es permitir la comunicación humana a través de la voz y el video: la comunicación en tiempo real, o RTC. La RTC debe ser tan natural en una aplicación web como cuando se ingresa texto en una entrada de texto. Sin ella, tu capacidad para innovar y desarrollar nuevas formas de interacción entre las personas es limitada.

Históricamente, la RTC ha sido corporativa y compleja, y requiere que las costosas tecnologías de audio y video se otorguen licencia o se desarrollen en las instalaciones. Integrar la tecnología de RTC con el contenido, los datos y los servicios existentes ha sido difícil y lleva mucho tiempo, especialmente en la Web.

El chat de video de Gmail se hizo popular en 2008 y, en 2011, Google presentó Hangouts, que utiliza Talk (al igual que Gmail). Google compró GIPS, una empresa que desarrolló muchos componentes necesarios para la RTC, como códecs y técnicas de cancelación del eco. Google creó código abierto para las tecnologías desarrolladas por GIPS y colaboró con los organismos de estándares relevantes del Internet Engineering Task Force (IETF) y el World Wide Web Consortium (W3C) para garantizar el consenso de la industria. En mayo de 2011, Ericsson compiló la primera implementación de WebRTC.

WebRTC implementó estándares abiertos para comunicación de video, audio y datos en tiempo real y sin complementos. La necesidad era real:

  • Muchos servicios web usaban la RTC, pero necesitaban descargas, aplicaciones nativas o complementos. Entre ellas se incluían Skype, Facebook y Hangouts.
  • La descarga, instalación y actualización de complementos es compleja y molesta.
  • Los complementos son difíciles de implementar, depurar, solucionar problemas, probar y mantener, y pueden requerir licencias e integración con tecnología compleja y costosa. A menudo, es difícil persuadir a los usuarios para que instalen complementos en primer lugar.

Los principios rectores del proyecto WebRTC son que sus APIs deben ser de código abierto, gratuitas, estandarizadas, integradas en navegadores web y más eficientes que las tecnologías existentes.

¿Dónde estamos ahora?

WebRTC se usa en varias apps, como Google Meet. WebRTC también se integró con las apps nativas WebKitGTK+ y Qt.

WebRTC implementa estas tres APIs: - MediaStream (también conocido como getUserMedia) - RTCPeerConnection - RTCDataChannel

Las APIs se definen en estas dos especificaciones:

Las tres APIs son compatibles con dispositivos móviles y computadoras de escritorio con Chrome, Safari, Firefox, Edge y Opera.

getUserMedia: Para demostraciones y código, consulta las muestras de WebRTC o prueba los increíbles ejemplos de Chris Wilson que usan getUserMedia como entrada para el audio web.

RTCPeerConnection: Para obtener una demostración simple y una app de videochat completamente funcional, consulta Conexión de intercambio de tráfico de muestras de WebRTC y appr.tc, respectivamente. Esta app usa adapter.js, una corrección de compatibilidad de JavaScript que mantiene Google con la ayuda de la comunidad de WebRTC, para abstraer las diferencias del navegador y los cambios de especificaciones.

RTCDataChannel: Para ver esto en acción, consulta los ejemplos de WebRTC para ver una de las demostraciones de canales de datos.

En el codelab de WebRTC, se muestra cómo usar las tres APIs para compilar una app simple para videochat y compartir archivos.

Tu primer WebRTC

Las apps de WebRTC deben realizar varias acciones:

  • Obtén transmisión de audio, video y otros datos.
  • Obtén información de la red, como direcciones IP y puertos, y también intercámbiala con otros clientes de WebRTC (conocidos como pares) para habilitar la conexión, incluso a través de NAT y firewalls.
  • Coordinar la comunicación de indicadores para informar errores e iniciar o cerrar sesiones
  • Intercambia información sobre el contenido multimedia y la capacidad del cliente, como la resolución y los códecs.
  • Comunicar datos de transmisión, video o audio

Para adquirir y comunicar datos de transmisión, WebRTC implementa las siguientes APIs:

  • MediaStream obtiene acceso a flujos de datos, por ejemplo, de la cámara y el micrófono del usuario.
  • RTCPeerConnection habilita las llamadas de audio o video con servicios para la encriptación y la administración del ancho de banda.
  • RTCDataChannel permite la comunicación entre pares de datos genéricos.

(Más adelante, se analizará detalladamente los aspectos de red y señalización de WebRTC).

API de MediaStream (también conocida como API de getUserMedia)

La API de MediaStream representa transmisiones sincronizadas de contenido multimedia. Por ejemplo, una transmisión que se toma de la entrada de la cámara y el micrófono tiene pistas de video y audio sincronizadas. (No confundas MediaStreamTrack con el elemento <track>, que es algo completamente diferente).

Probablemente, la forma más fácil de entender la API de MediaStream es observarla en el exterior:

  1. En el navegador, ve a Muestras de WebRTC getUserMedia.
  2. Abre la consola.
  3. Inspecciona la variable stream, que está en alcance global.

Cada MediaStream tiene una entrada, que puede ser un MediaStream generado por getUserMedia(), y una salida, que se puede pasar a un elemento de video o a una RTCPeerConnection.

El método getUserMedia() toma un parámetro de objeto MediaStreamConstraints y muestra un Promise que se resuelve en un objeto MediaStream.

Cada MediaStream tiene un label, como 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'. Los métodos getAudioTracks() y getVideoTracks() muestran un array de MediaStreamTrack.

Para el ejemplo de getUserMedia, stream.getAudioTracks() muestra un array vacío (porque no hay audio) y, suponiendo que hay una cámara web que funciona, stream.getVideoTracks() muestra un array de un MediaStreamTrack que representa la transmisión de la cámara web. Cada MediaStreamTrack tiene un tipo ('video' o 'audio'), un label (algo como 'FaceTime HD Camera (Built-in)') y representa uno o más canales de audio o video. En este caso, solo hay una pista de video y no hay audio, pero es fácil imaginar casos de uso en los que hay más, como una app de chat que obtiene transmisiones desde la cámara frontal, la cámara posterior, el micrófono y una app que comparte su pantalla.

Se puede adjuntar un MediaStream a un elemento de video configurando el atributo srcObject. Anteriormente, esto se hacía configurando el atributo src en la URL de un objeto creada con URL.createObjectURL(), pero quedó obsoleto.

getUserMedia también se puede usar como nodo de entrada para la API de 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);
});

Las aplicaciones y extensiones basadas en Chromium también pueden incorporar getUserMedia. Si agregas los permisos audioCapture o videoCapture al manifiesto, permitirás que se soliciten y otorguen permisos solo una vez durante la instalación. Luego de esa fecha, no se le solicitará permiso al usuario para acceder a la cámara o al micrófono.

El permiso solo se debe otorgar una vez para getUserMedia(). La primera vez, se mostrará el botón Permitir en la barra de información del navegador. Chrome dio de baja el acceso HTTP para getUserMedia() a fines de 2015 porque se lo clasificó como una función potente.

El objetivo es habilitar un MediaStream para cualquier fuente de datos de transmisión, no solo una cámara o un micrófono. Esto permitiría la transmisión desde datos almacenados o fuentes de datos arbitrarios, como sensores y otras entradas.

getUserMedia() realmente cobra vida en combinación con otras APIs y bibliotecas de JavaScript:

  • Webcam Toy es una app de cabina de fotos que usa WebGL para agregar efectos raros y maravillosos a las fotos que se pueden compartir o guardar de forma local.
  • FaceKat es un juego de seguimiento de rostros creado con headtrackr.js.
  • La Cámara ASCII usa la API de Canvas para generar imágenes ASCII.
Imagen ASCII generada por idevelop.ro/ascii-camera
Arte ASCII de gUM

Restricciones

Se pueden usar restricciones para establecer valores de resolución de video para getUserMedia(). Esto también permite admitir otras restricciones, como la relación de aspecto, el modo orientado (cámara frontal o posterior), la velocidad de fotogramas, la altura y el ancho, y un método applyConstraints().

Para ver un ejemplo, consulta Muestras de WebRTC getUserMedia: selección de resolución.

Establecer un valor de restricción no permitido genera un DOMException o un OverconstrainedError si, por ejemplo, no está disponible una resolución solicitada. Si quieres ver esto en acción, consulta los ejemplos de WebRTC getUserMedia: selección de la resolución para acceder a una demostración.

Captura de pantalla y pestaña

Las apps de Chrome también permiten compartir un video en vivo de una sola pestaña del navegador o todo el escritorio a través de las APIs de chrome.tabCapture y chrome.desktopCapture. Para obtener una demostración y más información, consulta Compartir pantalla con WebRTC. El artículo tiene algunos años de antigüedad, pero sigue siendo interesante).

También es posible usar la captura de pantalla como una fuente de MediaStream en Chrome con la restricción chromeMediaSource experimental. Ten en cuenta que la captura de pantalla requiere HTTPS y solo debe usarse para el desarrollo, ya que se habilita mediante una marca de línea de comandos, como se explica en esta entrada.

Señalización: información sobre el control de sesiones, la red y el contenido multimedia

WebRTC usa RTCPeerConnection para comunicar datos de transmisión entre navegadores (también conocidos como pares), pero también necesita un mecanismo que coordine la comunicación y envíe mensajes de control, un proceso conocido como señalización. WebRTC no especifica los métodos y protocolos de señalización. La señalización no forma parte de la API de RTCPeerConnection.

En cambio, los desarrolladores de apps WebRTC pueden elegir el protocolo de mensajería que prefieran, como SIP o XMPP, y cualquier canal de comunicación dúplex (doble) adecuado. El ejemplo appr.tc usa XHR y la API de canal como mecanismo de señalización. El codelab usa Socket.io que se ejecuta en un servidor de nodos.

La señalización se utiliza para intercambiar tres tipos de información:

  • Mensajes de control de sesiones: para inicializar o cerrar la comunicación y notificar errores.
  • Configuración de red: al mundo exterior, ¿cuál es la dirección IP y el puerto de tu computadora?
  • Capacidades multimedia: ¿Qué códecs y resoluciones pueden manejar tu navegador y el navegador con el que quiere comunicarse?

El intercambio de información a través de la señalización debe haberse completado correctamente antes de que pueda comenzar la transmisión entre pares.

Por ejemplo, imagina que Alicia quiere comunicarse con Roberto. A continuación, verás una muestra de código de la especificación de WebRTC de W3C, que muestra el proceso de señalización en acción. El código asume la existencia de algún mecanismo de señalización creado en el método createSignalingChannel(). Además, ten en cuenta que, en Chrome y Opera, RTCPeerConnection actualmente tiene el prefijo.

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

Primero, Alicia y Roberto intercambian información de red. (La expresión encontrar candidatos se refiere al proceso de encontrar interfaces de red y puertos con el framework ICE).

  1. Alice crea un objeto RTCPeerConnection con un controlador onicecandidate, que se ejecuta cuando los candidatos de red están disponibles.
  2. Alice envía datos de candidatos serializados a Roberto a través del canal de indicadores que usa, como WebSocket o algún otro mecanismo.
  3. Cuando Roberto recibe un mensaje de candidato de Alicia, llama a addIceCandidate para agregar al candidato a la descripción de par remoto.

Los clientes de WebRTC (también conocidos como pares, o Alicia y Bob en este ejemplo) también deben determinar e intercambiar información multimedia de audio y video locales y remotas, como las capacidades de resolución y códec. La indicación para intercambiar información de configuración de medios se realiza mediante el intercambio de una oferta y una respuesta mediante el protocolo de descripción de sesión (SDP):

  1. Alicia ejecuta el método RTCPeerConnection createOffer(). El resultado que se muestra se pasa como una RTCSessionDescription: descripción de la sesión local de Alice.
  2. En la devolución de llamada, Alicia establece la descripción local con setLocalDescription() y, luego, envía esta descripción de la sesión a Roberto a través de su canal de señalización. Ten en cuenta que RTCPeerConnection no comenzará a recopilar candidatos hasta que se llame a setLocalDescription(). Esta información está codificada en el borrador de JSEP IETF.
  3. Roberto establece la descripción que Alicia le envió como descripción remota mediante setRemoteDescription().
  4. Roberto ejecuta el método RTCPeerConnection createAnswer() y le pasa la descripción remota que recibió de Alicia para que se pueda generar una sesión local que sea compatible con la suya. La devolución de llamada createAnswer() recibe una RTCSessionDescription. Roberto la establece como la descripción local y se la envía a Alice.
  5. Cuando Alicia obtiene la descripción de la sesión de Roberto, la establece como la descripción remota con setRemoteDescription.
  6. ¡Ping!

Los objetos RTCSessionDescription son BLOB que cumplen con el Session Description Protocol, SDP. Serializado: un objeto SDP se ve de la siguiente manera:

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

La adquisición y el intercambio de información de redes y medios se pueden realizar simultáneamente, pero ambos procesos deben haberse completado antes de que pueda comenzar la transmisión de audio y video entre pares.

La arquitectura de oferta y respuesta descrita anteriormente se denomina Protocolo de establecimiento de sesiones de JavaScript o JSEP. (Hay una excelente animación en la que se explica el proceso de señalización y transmisión en el video de demostración de Ericsson para su primera implementación de WebRTC).

Diagrama de la arquitectura de JSEP
Arquitectura de JSEP

Una vez que el proceso de señalización se haya completado correctamente, los datos podrán transmitirse directamente entre pares, entre el emisor y el destinatario, o, si eso falla, a través de un servidor intermediario de retransmisión (más adelante hablaremos de ello). La transmisión es el trabajo de RTCPeerConnection.

RTCPeerConnection

RTCPeerConnection es el componente de WebRTC que controla la comunicación estable y eficiente de los datos de transmisión entre pares.

A continuación, se muestra un diagrama de la arquitectura de WebRTC en el que se muestra la función de RTCPeerConnection. Como notarás, las partes verdes son complejas.

Diagrama de la arquitectura de WebRTC
Arquitectura de WebRTC (de webrtc.org)

Desde la perspectiva de JavaScript, el aspecto principal que debes comprender de este diagrama es que RTCPeerConnection protege a los desarrolladores web de las numerosas complejidades que acechan debajo. Los códecs y protocolos que utiliza WebRTC realizan una gran cantidad de trabajo para posibilitar la comunicación en tiempo real, incluso en redes poco confiables:

  • Ocultamiento de pérdida de paquetes
  • Cancelación de eco
  • Adaptabilidad al ancho de banda
  • Almacenamiento en búfer de jitter dinámico
  • Control automático de ganancia
  • Reducción y supresión de ruido
  • Limpieza de imágenes

El código W3C anterior muestra un ejemplo simplificado de WebRTC desde una perspectiva de señalización. A continuación, se explican dos apps de WebRTC en funcionamiento. El primero es un ejemplo simple para demostrar RTCPeerConnection y el segundo es un cliente de videochat completamente operativo.

RTCPeerConnection sin servidores

El siguiente código se tomó de la conexión de intercambio de tráfico de muestras de WebGL, que tiene RTCPeerConnection local y remoto (y video local y remoto) en una página web. Esto no constituye nada muy útil (el llamador y el destinatario están en la misma página), pero el funcionamiento de la API de RTCPeerConnection es un poco más claro, ya que los objetos RTCPeerConnection de la página pueden intercambiar datos y mensajes directamente sin tener que usar mecanismos intermedios de señalización.

En este ejemplo, pc1 representa al par local (emisor) y pc2 representa al par remoto (destinatario).

Emisor

  1. Crea una nueva RTCPeerConnection y agrega el flujo desde getUserMedia(): ```js // Servers es un archivo de configuración opcional. (Consulta el debate sobre TURN y STUN más adelante). pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) => { pc1.addTrack(track, localStream); });
  1. Crea una oferta y establécela como descripción local de pc1 y como descripción remota de pc2. Esto se puede hacer directamente en el código sin usar la señalización, ya que tanto el llamador como el destinatario se encuentran en la misma página: js pc1.setLocalDescription(desc).then(() => { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); trace('pc2 setRemoteDescription start'); pc2.setRemoteDescription(desc).then(() => { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError );

Callee

  1. Crea pc2 y, cuando se agregue la transmisión de pc1, muéstrala en un elemento de video: js pc2 = new RTCPeerConnection(servers); pc2.ontrack = gotRemoteStream; //... function gotRemoteStream(e){ vid2.srcObject = e.stream; }

RTCPeerConnection API más servidores

En el mundo real, WebRTC necesita servidores, aunque es sencillo, de modo que pueden ocurrir las siguientes situaciones:

  • Los usuarios se descubren entre sí e intercambian detalles del mundo real, como nombres.
  • Las apps cliente de WebRTC (interesados) intercambian información de red.
  • Las apps similares intercambian datos sobre contenido multimedia, como el formato y la resolución de los videos.
  • Las aplicaciones de cliente WebRTC atraviesan puertas de enlace NAT y firewalls.

En otras palabras, WebRTC necesita cuatro tipos de funciones del servidor:

  • Descubrimiento y comunicación de usuarios
  • Señalización
  • Recorrido de NAT/firewall
  • Servidores de retransmisión en caso de que falle la comunicación entre pares

El recorrido de NAT, las redes entre pares y los requisitos de creación de una app de servidor para el descubrimiento y la señalización de usuarios están fuera del alcance de este artículo. Basta con decir que el framework ICE usa el protocolo STUN y su extensión TURN para que RTCPeerConnection pueda lidiar con el cruce de NAT y otros comportamientos de la red.

ICE es un framework para conectar a tus colegas, como dos clientes de videochat. Inicialmente, ICE intenta conectar los pares directamente con la latencia más baja posible a través de UDP. En este proceso, los servidores STUN tienen una sola tarea: habilitar un par detrás de una NAT para averiguar su dirección pública y puerto. (Para obtener más información sobre STUN y TURN, consulta Cómo compilar los servicios de backend necesarios para una app de WebRTC).

Busca candidatos de conexión
Busca candidatos de conexión

Si el UDP falla, ICE intenta usar TCP. Si la conexión directa falla, en especial debido al cruce de NAT y los firewalls de la empresa, ICE utiliza un servidor TURN intermedio (retransmisión). En otras palabras, ICE primero usa STUN con UDP para conectar los pares directamente y, si eso falla, recurre a un servidor de retransmisión TURN. La expresión buscar candidatos hace referencia al proceso de encontrar interfaces y puertos de red.

Ruta de acceso de datos de WebRTC
Rutas de los datos de WebRTC

El ingeniero de WebRTC, Justin Uberti, proporciona más información sobre ICE, STUN y TURN en la presentación de WebRTC de Google I/O de 2013. (Las diapositivas de la presentación brindan ejemplos de implementaciones de servidores TURN y STUN).

Un cliente de videochat sencillo

La demostración del videochat se encuentra en appr.tc, y es un buen lugar para probar WebRTC, además de señalización y NAT/firewall transversal mediante un servidor STUN. Esta app usa adapter.js, una corrección de compatibilidad para aislar las apps de los cambios de especificaciones y las diferencias de prefijos.

El código se agrega de forma intencional en su registro. Consulta la consola para comprender el orden de los eventos. A continuación, se brinda una explicación detallada del código.

Topologías de red

WebRTC implementada actualmente solo admite la comunicación uno a uno, pero se podría utilizar en situaciones de red más complejas, como la comunicación directa entre varios pares o a través de una unidad de control de varios puntos (MCU), un servidor que puede manejar grandes cantidades de participantes y realizar reenvíos selectivos de transmisiones, así como mezclar o grabar audio y video.

Diagrama de topología de unidades de control de varios puntos
Ejemplo de topología de Unidad de control multipunto

Muchas apps de WebRTC existentes solo demuestran la comunicación entre navegadores web, pero los servidores de puerta de enlace pueden habilitar una app de WebRTC que se ejecuta en un navegador para interactuar con dispositivos, como teléfonos (también conocidos como RTC) y con sistemas VoIP. En mayo de 2012, Doubango Telecom creó con código abierto el cliente SIP de SIP creado con WebRTC y WebSocket, que (entre otros usos potenciales) permite realizar videollamadas entre navegadores y apps que se ejecutan en iOS y Android. En Google I/O, Tethr y Tropo demostraron un framework para comunicaciones ante desastres en un maletín con una celda de OpenBTS para permitir la comunicación entre teléfonos de gama media y computadoras a través de WebRTC. Comunicación telefónica sin operador

Demostración de Tethr/Tropo en Google I/O 2012
Tethr/Tropo: Comunicaciones ante desastres en un maletín

API de RTCDataChannel<

Además de audio y video, WebRTC admite la comunicación en tiempo real para otros tipos de datos.

La API de RTCDataChannel permite el intercambio entre pares de datos arbitrarios con baja latencia y alta capacidad de procesamiento. Para ver demostraciones de una sola página y aprender a compilar una app simple de transferencia de archivos, consulta los ejemplos de WebRTC y el codelab de WebRTC, respectivamente.

Existen muchos casos de uso potenciales para la API, incluidos los siguientes:

  • Videojuegos
  • Apps de escritorio remoto
  • Chat de texto en tiempo real
  • Transferencia de archivos
  • Redes descentralizadas

La API tiene varias funciones para aprovechar RTCPeerConnection al máximo y permitir una comunicación entre pares potente y flexible:

  • Se aprovecha la configuración de la sesión de RTCPeerConnection
  • Varios canales simultáneos con priorización
  • Semántica de entrega confiable y poco confiable
  • Seguridad integrada (DTLS) y control de congestión
  • Capacidad de uso con o sin audio o video

La sintaxis es similar a WebSocket deliberadamente con un método send() y un 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);
};

La comunicación se produce directamente entre los navegadores, por lo que RTCDataChannel puede ser mucho más rápido que WebSocket, incluso si se requiere un servidor de retransmisión (TURN) cuando falla la perforación para lidiar con firewalls y NAT.

RTCDataChannel está disponible en Chrome, Safari, Firefox, Opera y Samsung Internet. El juego Cube Slam usa la API para comunicar el estado del juego. Juega con un amigo o juega con el oso. La innovadora plataforma Sharefest habilitó el uso compartido de archivos a través de RTCDataChannel y peerCDN para dar una idea de cómo WebRTC podría habilitar la distribución de contenido entre pares.

Para obtener más información sobre RTCDataChannel, consulta la especificación de protocolo de borrador de IETF.

Seguridad

Existen varias formas en las que una app o complemento de comunicación en tiempo real puede poner en riesgo la seguridad. Por ejemplo:

  • Es posible que se intercepten los datos o el contenido multimedia sin encriptar entre los navegadores o entre un navegador y un servidor.
  • Una app puede grabar y distribuir video o audio sin que el usuario lo sepa.
  • Se puede instalar software malicioso o virus junto con una app o complemento aparentemente inocuo.

WebRTC tiene varias funciones para evitar estos problemas:

  • Las implementaciones de WebRTC usan protocolos seguros, como DTLS y SRTP.
  • La encriptación es obligatoria para todos los componentes de WebRTC, incluidos los mecanismos de señalización.
  • WebRTC no es un complemento. Sus componentes se ejecutan en la zona de pruebas del navegador y no en un proceso independiente. Los componentes no requieren instalación separada y se actualizan cada vez que se actualiza el navegador.
  • El acceso a la cámara y al micrófono se debe otorgar de manera explícita y, cuando estos estén funcionando, esto se mostrará claramente en la interfaz de usuario.

Un análisis completo de la seguridad para los medios de transmisión está fuera del alcance de este artículo. Para obtener más información, consulta la arquitectura de seguridad propuesta de WebRTC propuesta por el IETF.

Conclusión

Las APIs y los estándares de WebRTC pueden democratizar y descentralizar las herramientas para la creación de contenido y la comunicación, como la telefonía, los videojuegos, la producción de videos, la creación de música y la recopilación de noticias.

La tecnología no puede ser mucho más disruptiva que esto.

Tal como lo expresó el blogger Phil Edholm: "Posiblemente, WebRTC y HTML5 podrían habilitar la misma transformación para la comunicación en tiempo real que el navegador original utilizó para obtener información".

Herramientas para desarrolladores

Más información

Estándares y protocolos

Resumen de compatibilidad de WebRTC

APIs de MediaStream y getUserMedia

  • Chrome para computadoras de escritorio 18.0.1008 y versiones posteriores; Chrome para Android 29 y versiones posteriores
  • Opera 18 y versiones posteriores; Opera para Android 20 y versiones posteriores
  • Opera 12, Opera Mobile 12 (basado en el motor Presto)
  • Firefox 17 y versiones posteriores
  • Microsoft Edge 16 y versiones posteriores
  • Safari 11.2 y versiones posteriores en iOS y 11.1 y versiones posteriores en MacOS
  • UC 11.8 y versiones posteriores en Android
  • Samsung Internet 4 y versiones posteriores

API RTCPeerConnection

  • Chrome 20 y versiones posteriores; Chrome para Android 29 y versiones posteriores (sin marcas)
  • Opera 18 y versiones posteriores (activadas de forma predeterminada); Opera para Android 20 y versiones posteriores (activadas de forma predeterminada)
  • Firefox 22 y versiones posteriores (activado de forma predeterminada)
  • Microsoft Edge 16 y versiones posteriores
  • Safari 11.2 y versiones posteriores en iOS y 11.1 y versiones posteriores en MacOS
  • Samsung Internet 4 y versiones posteriores

API RTCDataChannel

  • Versión experimental en Chrome 25, pero más estable (y con interoperabilidad con Firefox) en Chrome 26 y versiones posteriores; Chrome para Android 29 y versiones posteriores
  • Versión estable (y con interoperabilidad con Firefox) en Opera 18 y versiones posteriores; Opera para Android 20 y versiones posteriores
  • Firefox 22 y versiones posteriores (activado de forma predeterminada)

Para obtener información más detallada sobre la compatibilidad multiplataforma para APIs, como getUserMedia y RTCPeerConnection, consulta caniuse.com y Estado de la plataforma de Chrome.

Las APIs nativas para RTCPeerConnection también están disponibles en la documentación de webrtc.org.