How RTCPeerConnection Works in JavaScript
The RTCPeerConnection interface is the core component of
the WebRTC standard used to establish, maintain, and terminate
peer-to-peer audio and video communications in JavaScript. This article
provides a straightforward breakdown of how
RTCPeerConnection handles media acquisition, session
negotiation through the offer/answer model, NAT traversal via ICE, and
the continuous streaming of real-time tracks between web browsers.
1. Initializing the Connection and Adding Tracks
To manage real-time media, a JavaScript application first captures
audio and video streams from local user devices using
navigator.mediaDevices.getUserMedia(). Once the media is
acquired, an instance of RTCPeerConnection is created, and
the tracks are attached directly to the connection.
const peerConnection = new RTCPeerConnection(configuration);
const localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
localStream.getTracks().forEach(track => {
peerConnection.addTrack(track, localStream);
});The configuration object typically contains a list of STUN and TURN server URLs required to navigate through firewalls and Network Address Translation (NAT).
2. Session Negotiation via the Offer/Answer Model
Peers exchange metadata about codecs, encryption, and network
capabilities using the Session Description Protocol (SDP). Because
RTCPeerConnection does not have a built-in messaging
channel for signaling, an external mechanism like WebSockets is used to
exchange this data.
- Creating the Offer: The initiating peer creates an
SDP offer using
createOffer()and applies it locally usingsetLocalDescription(). - Sending the Offer: The offer is sent to the remote peer via the signaling server.
- Receiving and Responding: The remote peer receives
the offer, applies it using
setRemoteDescription(), generates an SDP answer usingcreateAnswer(), and sets it as its local description. - Finalizing the Exchange: The initiating peer
receives the answer and applies it using
setRemoteDescription().
3. Network Traversal with ICE Candidates
While SDP describes the media formats, Interactive Connectivity Establishment (ICE) determines the best network path to transmit the media packets.
- Candidate Gathering: The
RTCPeerConnectiongathers local IP addresses and contacts STUN/TURN servers to discover public addresses and relay candidates. - Exchange: When an ICE candidate is discovered, the
icecandidateevent fires. The application sends this candidate to the remote peer via the signaling channel. - Pairing: The receiving peer adds the candidate to
its connection using
addIceCandidate(). The peers test these connectivity pairs until the optimal direct or relayed path is established.
peerConnection.onicecandidate = (event) => {
if (event.candidate) {
signalingChannel.send(JSON.stringify({ candidate: event.candidate }));
}
};4. Receiving and Rendering Media Tracks
When the remote peer adds tracks and the connection succeeds, the
track event triggers on the receiving peer’s
RTCPeerConnection. This event exposes the incoming
MediaStreamTrack, which can be attached to an HTML
<video> or <audio> element for
playback.
peerConnection.ontrack = (event) => {
const remoteVideo = document.getElementById('remoteVideo');
if (remoteVideo.srcObject !== event.streams[0]) {
remoteVideo.srcObject = event.streams[0];
}
};5. Monitoring Connection State and Termination
RTCPeerConnection exposes connection lifecycle states
through the connectionstatechange event. The states
progress through connecting, connected,
disconnected, failed, or
closed.
To terminate a session, the application calls
peerConnection.close(), which stops ICE processing,
detaches media streams, and releases network sockets and hardware
resources.