WebRTC: from the first signal to the first frame
A practical introduction to signaling, ICE, STUN and TURN—and the connection states that make a real-time experience dependable.
WebRTC connects real-time audio, video and data between endpoints. A working call needs more than a camera preview: the participants must exchange connection information, find a usable network path and handle the states between connecting and disconnecting.
This introduction focuses on the connection lifecycle. It is a starting point for a one-to-one calling application, not a complete production signaling server.
Start with signaling
Before media can flow, peers need a way to exchange an offer, an answer and network candidates. WebRTC does not prescribe the application's signaling transport. A separate channel—often a WebSocket connection—carries those messages.
Think of signaling as coordination. It tells each endpoint how to negotiate the session; it is not automatically the route carrying the video. The session description contains information about the proposed media and connection, rather than the video frames themselves. See MDN's signaling guide.
For an application design, keep message responsibilities explicit. An offer belongs to a particular session. A candidate belongs to the connection being negotiated. Authentication, room membership and handling simultaneous negotiation deserve their own deliberate decisions.
Find a usable network path
ICE coordinates connectivity checks. STUN can help discover an endpoint's externally visible address. When a suitable direct path is unavailable, TURN provides a relay. A successful test on one home network does not demonstrate that a call will work through every firewall or NAT arrangement.
An SFU is a different piece of infrastructure: it forwards media among participants, commonly for group calls. It is not another name for a TURN relay. These mechanisms can appear together in a deployment. MDN's protocol overview explains these roles.
A useful validation plan includes an intentionally relayed call. Check that the chosen candidate pair matches the path you expected rather than assuming that a visible video proves the fallback works.
Design the connection states
Make connecting and recovering visible. Avoid presenting every interruption as a permanent failure, but do not leave a visitor staring at an indefinite spinner.
A small state listener is a useful starting point:
const peer = new RTCPeerConnection();
peer.addEventListener('connectionstatechange', () => {
const state = peer.connectionState;
console.log('Peer connection state:', state);
// Update the interface for this state.
});
This fragment observes a connection; it does not establish a call. A complete application must configure its ICE services, acquire or attach media, exchange signaling messages and implement negotiation. See the connection workflow in MDN.
In the interface, preserve the person's intent across recovery. Keep the distinction between muting a microphone, losing connectivity and leaving the call. Those events may look similar to another participant, but they need different actions from the application.
Measure beyond “connected”
RTCPeerConnection.getStats() returns a report of connection statistics. Its entries can help inspect transport and media behavior; available fields depend on the report type. Start by examining the entries rather than treating every record as the same shape. MDN documents the method and its report.
const report = await peer.getStats();
for (const entry of report.values()) {
if (entry.type === 'inbound-rtp') {
console.log(entry);
}
}
For a debugging session, record what the person experienced alongside the technical observations: time to usable media, interruptions and whether recovery restored the task. Avoid collecting raw session descriptions or personal identifiers unless there is a clear operational need and an appropriate data-handling policy.
A practical first milestone
Build a small call between two endpoints. Then deliberately deny media permission, interrupt connectivity, test a relayed path and leave the session. Confirm that each outcome has clear feedback and releases the resources it owns.
A dependable real-time interface explains what is happening before, during and after the first frame. That is the part worth designing alongside the transport.