WebRTC y HTML: Arquitectura real de la transmisión de video P2P
Entiende cómo funciona WebRTC, el rol exacto de HTML5 y por qué el video peer-to-peer necesita mucha más infraestructura de red de la que crees. Guía visual para ingenieros.
Contenido de la guía ⌄
- Qué vas a entender en esta guía
- El flujo de conexión paso a paso
- La secuencia real del handshake
- Captura y preparación local
- Creación de la oferta
- Respuesta del peer remoto
- Intercambio de candidatos ICE
- Conexión y renderizado final
- Qué problema resuelve cada etapa
- Cómo se ve esta secuencia en código
- El papel exacto de HTML dentro de WebRTC
- Qué hace HTML cuando entra un flujo multimedia
- Reserva una superficie visible
- Recibe un objeto reproducible
- Diferencia vista local y vista remota
- Expone comportamiento visible
- La parte difícil de verdad: SDP, ICE, STUN y TURN
- Qué resuelve realmente cada pieza
- Los peers no viven en una red simple
- Hace falta descubrir candidatos útiles
- La ruta directa no siempre gana
- La llamada exitosa es una decisión de conectividad
- Señalización, STUN y TURN no son la misma infraestructura
WebRTC no es simplemente “mandar video entre dos navegadores”. Es una arquitectura donde la negociación, la conectividad y el transporte de medios viven en capas distintas. El flujo puede terminar siendo peer-to-peer, sí, pero antes de eso hace falta resolver cómo se presentan los peers, cómo describen sus capacidades y cómo descubren una ruta de red viable.
Qué vas a entender en esta guía
Por qué WebRTC no empieza en el canal de medios, sino en una fase previa de señalización, acuerdo técnico y descubrimiento de conectividad.
Cómo el navegador usa elementos como <video> y objetos como MediaStream para volver visible la llamada.
Qué hacen SDP, ICE, STUN y TURN antes de que el usuario vea el primer frame de video remoto en pantalla.
Confusión central: WebRTC no es “poner dos videos y conectarlos”. Primero hay una fase de coordinación externa. Solo cuando negociación y conectividad quedan resueltas aparece el flujo que HTML puede renderizar.
El flujo de conexión paso a paso
Una llamada WebRTC no empieza cuando el usuario ve el video remoto en pantalla. Empieza antes, en una secuencia donde dos navegadores deben acordar cómo quieren comunicarse y descubrir si realmente pueden alcanzarse a través de la red.
Esa secuencia se suele resumir como handshake. Primero se prepara el estado local, después se intercambian descripciones de sesión, luego se prueban rutas de conectividad y solo al final aparece el flujo remoto que HTML termina mostrando en <video>.
Idea central: en WebRTC, una pantalla negra casi nunca significa “falló el video”. Normalmente significa que falló antes una parte del handshake: la oferta, la respuesta, los candidatos ICE o la asociación final del flujo remoto al DOM.
La secuencia real del handshake
Captura y preparación local
El peer que inicia obtiene cámara o micrófono, crea su RTCPeerConnection y añade las pistas del flujo local. Aquí todavía no existe una llamada establecida: solo se prepara el punto de partida.
Creación de la oferta
El peer llamador genera una Offer en formato SDP. Esa oferta describe cómo quiere negociar la sesión y qué capacidades presenta como parte inicial del acuerdo técnico.
Respuesta del peer remoto
El peer receptor recibe la oferta, la registra como descripción remota, genera una Answer y devuelve su propia descripción de sesión. En este punto ambos lados ya comparten una base común de negociación.
Intercambio de candidatos ICE
En paralelo a la oferta y la respuesta, cada peer empieza a reunir rutas posibles de conectividad. Esos candidatos ICE también viajan por señalización y permiten descubrir si habrá camino directo o si hará falta infraestructura adicional.
Conexión y renderizado final
Cuando una ruta viable queda seleccionada, el transporte de medios se estabiliza y el navegador receptor dispara ontrack. Solo ahí el flujo remoto puede asociarse a <video> y aparecer en pantalla.
Qué problema resuelve cada etapa
| Etapa | Qué resuelve | Resultado esperado |
|---|---|---|
| Captura local | Preparar el flujo y la conexión base del peer que inicia | Existe estado local listo para negociar |
| Offer / Answer | Acordar parámetros de sesión y capacidades | Ambos peers entienden cómo quieren comunicarse |
| ICE | Descubrir rutas viables de conectividad | Existe un camino de red usable entre ambos lados |
| ontrack | Entregar el flujo remoto a la aplicación | El video puede inyectarse en HTML |
Cómo leer el diagrama: la oferta SDP, la respuesta SDP y los candidatos ICE viajan por el canal de señalización. El flujo de medios aparece después, cuando la conectividad ya fue resuelta entre los peers.
Cómo se ve esta secuencia en código
El navegador no ejecuta el handshake como una sola función mágica. Lo que ves en la práctica es una secuencia de pasos donde la aplicación crea la conexión, adjunta pistas locales, genera la oferta, escucha candidatos ICE y finalmente espera ontrack para asociar el flujo remoto a HTML.
Lectura correcta del snippet: este código no representa toda una videollamada. Representa el esqueleto mental del peer que inicia la conexión.
handshake-minimo.js · esqueleto mental del lado llamador
Este fragmento no representa una aplicación completa. Su función es mostrar, en orden, los pasos mínimos que ejecuta el peer que crea la conexión: preparar la sesión, generar la oferta, enviar candidatos ICE y esperar el flujo remoto.
const peerConnection = new RTCPeerConnection(config);
localStream.getTracks().forEach((track) => {
peerConnection.addTrack(track, localStream);
});
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
signalingServer.send("offer", offer);
peerConnection.onicecandidate = (event) => {
if (event.candidate) {
signalingServer.send("ice-candidate", event.candidate);
}
};
peerConnection.ontrack = (event) => {
const remoteVideo = document.getElementById("video-remoto");
remoteVideo.srcObject = event.streams[0];
};
Qué debe quedarle claro al lector al terminar esta parte: en WebRTC el video remoto no aparece porque dos navegadores “se encontraron”. Aparece porque antes lograron negociar la sesión, compartir información de red y estabilizar una ruta de conectividad suficiente para transportar medios.
El papel exacto de HTML dentro de WebRTC
Cuando se habla de WebRTC, mucha gente mete en el mismo saco cosas que pertenecen a capas distintas. La red, la negociación y el transporte de medios suelen llevarse toda la atención, pero el usuario nunca “ve ICE”, nunca “ve SDP” y nunca “ve TURN”. Lo que realmente ve es una interfaz donde aparece una vista local, un video remoto, estados de reproducción y permisos asociados al navegador.
Ahí es donde entra HTML. Su papel no consiste en transportar audio o video a través de internet. Su papel consiste en materializar los flujos que el navegador ya capturó o recibió, asociarlos a elementos visuales y volver posible la experiencia real de una llamada dentro del DOM.
Elementos como <video> no participan en Offer, Answer ni en el intercambio de candidatos ICE. Esa parte vive en APIs como RTCPeerConnection.
Cuando el navegador ya tiene un MediaStream, HTML ofrece la superficie donde ese flujo se reproduce, se silencia, ocupa espacio en layout y se integra con la interfaz.
La llamada no termina cuando existe conectividad. Termina de volverse producto cuando el flujo remoto queda asociado a un elemento visible, entendible y controlable dentro de la página.
Idea clave: WebRTC resuelve cómo capturar, negociar y recibir medios; HTML resuelve cómo esos medios aparecen en pantalla como parte real de la experiencia del usuario.
Qué hace HTML cuando entra un flujo multimedia
Reserva una superficie visible
El elemento <video> define dónde se va a mostrar el flujo, con qué tamaño, dentro de qué jerarquía visual y bajo qué reglas de layout.
Recibe un objeto reproducible
La aplicación asigna un MediaStream a srcObject. A partir de ahí el navegador ya puede tratar el flujo como contenido multimedia embebido en la interfaz.
Diferencia vista local y vista remota
El flujo local suele mostrarse para feedback inmediato del usuario, mientras que el flujo remoto representa la llegada efectiva del medio desde el otro peer.
Expone comportamiento visible
Atributos como autoplay, playsinline y muted condicionan cómo se reproduce el video dentro del navegador.
Detalle importante: el video local suele renderizarse con muted para evitar realimentación de audio y para cumplir mejor con restricciones de reproducción automática del navegador. No es un adorno: suele ser parte del comportamiento correcto.
La estructura HTML mínima no “hace WebRTC” por sí sola, pero deja preparada la superficie exacta donde el navegador va a mostrar la vista local y la vista remota de la llamada.
<section class="call-ui">
<video id="video-local" autoplay playsinline muted></video>
<video id="video-remoto" autoplay playsinline></video>
</section>
| Elemento | Qué aporta | Por qué importa |
|---|---|---|
| <video id="video-local"> | Muestra el flujo capturado localmente | Da feedback inmediato al usuario sobre cámara y composición |
| autoplay | Intenta reproducir el flujo sin interacción manual | Hace viable una experiencia de llamada en tiempo real |
| playsinline | Evita comportamientos intrusivos de pantalla completa en móvil | Conserva la llamada dentro del layout normal de la interfaz |
| muted | Silencia la vista local | Evita eco y ayuda con políticas del navegador |
En JavaScript, el puente real entre WebRTC y HTML aparece cuando un MediaStream termina asignado a srcObject. Ahí deja de ser un flujo abstracto y se convierte en video visible dentro del DOM.
const localVideo = document.getElementById("video-local");
const remoteVideo = document.getElementById("video-remoto");
const localStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
});
localVideo.srcObject = localStream;
const peerConnection = new RTCPeerConnection(config);
localStream.getTracks().forEach((track) => {
peerConnection.addTrack(track, localStream);
});
peerConnection.ontrack = (event) => {
remoteVideo.srcObject = event.streams[0];
};
getUserMedia() obtiene cámara y micrófono, y localVideo.srcObject muestra inmediatamente la vista local. Aquí HTML todavía no recibe nada remoto: solo materializa captura local.
Cuando ontrack se dispara, el navegador ya recibió un flujo remoto desde la conexión. En ese instante, asignarlo a remoteVideo.srcObject es lo que vuelve visible la llegada del otro peer.
Resultado esperado de esta parte: el lector ya no debería confundir el papel de HTML con el papel de WebRTC. WebRTC resuelve la comunicación de medios; HTML resuelve cómo esa comunicación se vuelve visible, usable y comprensible dentro de la interfaz.
La parte difícil de verdad: SDP, ICE, STUN y TURN
Hasta aquí ya vimos que WebRTC no arranca con el video, sino con una fase previa de negociación. Pero incluso después de intercambiar una oferta y una respuesta, todavía queda un problema más duro: que ambos peers encuentren una ruta real de conectividad a través de internet.
Ahí es donde aparecen cuatro piezas que suelen confundirse entre sí: SDP, ICE, STUN y TURN. No hacen lo mismo, no viven en la misma capa y no resuelven el mismo tipo de problema. Entender esa diferencia es lo que separa una explicación superficial de un modelo mental realmente útil.
SDP es una descripción de sesión. Le dice al otro peer qué tipo de intercambio se quiere negociar: medios, códecs, direcciones, puertos y parámetros de comunicación. Es un bloque de acuerdo técnico, no el canal por donde viaja el video.
ICE es el mecanismo que reúne y prueba rutas posibles de conectividad. Su trabajo no es “servir” la llamada, sino descubrir cuál camino de red puede funcionar entre ambos peers en condiciones reales.
STUN ayuda al peer a descubrir cómo se ve desde fuera de su red local. En otras palabras, le permite averiguar una dirección pública candidata que luego puede usarse dentro del proceso de conectividad.
Cuando la ruta directa falla, TURN actúa como relevo. El medio deja de viajar de forma estrictamente directa entre peers y pasa por infraestructura intermedia para que la llamada siga siendo viable.
Mito común: “si WebRTC es peer-to-peer, entonces siempre conecta directo”. Realidad: WebRTC intenta primero la ruta más directa posible, pero en internet real puede terminar necesitando ayuda de STUN para descubrirse o de TURN para relevar tráfico cuando NATs, firewalls o políticas de red impiden la conexión directa.
Qué resuelve realmente cada pieza
| Pieza | Qué hace | Qué no hace |
|---|---|---|
| SDP | Describe la sesión y sus parámetros de negociación | No descubre rutas ni retransmite medios |
| ICE | Reúne y evalúa candidatos de conectividad | No reemplaza a HTML ni es el video mismo |
| STUN | Ayuda a conocer una dirección pública utilizable | No funciona como relevo permanente del medio |
| TURN | Releva tráfico cuando no hay ruta directa viable | No es la primera opción si existe conectividad directa |
La forma más útil de pensarlo es esta: SDP describe, ICE explora, STUN ayuda a descubrir y TURN rescata la conectividad cuando lo directo no alcanza. Son piezas complementarias, no sinónimos.
Los peers no viven en una red simple
Normalmente cada navegador está detrás de un router, NAT o firewall. Eso significa que su dirección visible dentro de la red local no basta para establecer una llamada desde internet abierta.
Hace falta descubrir candidatos útiles
WebRTC reúne distintas rutas posibles y las intercambia entre peers. Algunas fallan, otras son inviables y otras terminan siendo la base de la conexión.
La ruta directa no siempre gana
En condiciones ideales, los peers logran una conexión directa. Pero cuando la red impone demasiadas restricciones, la llamada puede depender de TURN para mantenerse funcional.
La llamada exitosa es una decisión de conectividad
El usuario solo ve que “la videollamada abrió”, pero por debajo ocurrió una selección de ruta donde WebRTC evaluó qué camino era realmente viable.
Señalización, STUN y TURN no son la misma infraestructura
| Componente | Papel dentro del sistema | Cuándo participa |
|---|---|---|
| Signaling | Intercambiar Offer, Answer y candidatos ICE | Antes y durante la fase de negociación |
| STUN | Ayudar a descubrir direcciones públicas candidatas | Durante la búsqueda de conectividad |
| TURN | Relevar tráfico cuando no hay ruta directa útil | Cuando la conexión directa falla o no es viable |
Idea clave: peer-to-peer describe el destino deseado del flujo de medios, no garantiza por sí mismo que internet vaya a permitir una ruta directa entre dos navegadores reales.
En código, esta diferencia suele aparecer concentrada en la configuración inicial de RTCPeerConnection. Ahí la aplicación declara qué servidores de apoyo usará para el proceso de conectividad.
const peerConnection = new RTCPeerConnection({
iceServers: [
{ urls: "stun:stun.example.com:3478" },
{
urls: "turn:turn.example.com:3478",
username: "usuario",
credential: "clave",
},
],
});
La conexión declara infraestructura auxiliar para el proceso de ICE. No está diciendo todavía “por aquí viajará el video”, sino “estas son las ayudas disponibles para descubrir o sostener conectividad”.
Ver un servidor TURN configurado no significa que siempre se usará. Solo significa que existe como recurso de respaldo cuando la ruta directa o semidirecta no logra establecerse.
Qué debe quedarle claro al lector al terminar esta parte: SDP, ICE, STUN y TURN no son nombres decorativos del ecosistema WebRTC. Son piezas distintas que explican por qué una videollamada real necesita describir la sesión, descubrir rutas posibles y, a veces, apoyarse en infraestructura adicional para no fallar.
Comentarios y valoraciones
No hay comentarios aún. ¡Sé el primero en opinar!