WebRTC Front‑End Deep Dive: 1v1 Call Demo and Multi‑Party Architecture Guide

This article walks through building a 1v1 WebRTC audio/video call demo with Vue, explains the underlying PeerConnection setup, media control, and datachannel messaging, then expands to discuss real‑world challenges, adaptive solutions, and compares Mesh, SFU, and MCU multi‑party architectures.

Full-Stack Cultivation Path
Full-Stack Cultivation Path
Full-Stack Cultivation Path
WebRTC Front‑End Deep Dive: 1v1 Call Demo and Multi‑Party Architecture Guide

1v1 Audio/Video Call Demo

Two local browser windows simulate users "ZhuanZhuan" and "CaiHuoXia". The demo shows how to start the browsers, initiate a video call, grant media permissions, and display local and remote video streams. It also demonstrates sending a text message during the call and toggling the video mode with a code snippet.

Video‑mode toggle example:

// Switch video track enabled state
senders.find(s => s.track.kind === 'video').track.enabled = !send.track.enabled;

1v1 Call Implementation Details

Caller initialization – The initCallerInfo function creates a PeerConnection, obtains local media, adds each track, renders the preview, registers event callbacks, creates an SDP offer, and sends it through the signaling server.

async initCallerInfo(callerId, calleeId) {
  // initialize PeerConnection object
  this.localRtcPc = new PeerConnection();

  // get local media (audio & video)
  const localStream = await this.getLocalUserMedia({ audio: true, video: true });

  // add each track to PeerConnection
  localStream.getTracks().forEach(track => this.localRtcPc.addTrack(track));

  // render local stream to preview element
  await this.setDomVideoStream("localdemo", localStream);

  // register event handlers
  this.onPcEvent(this.localRtcPc, callerId, calleeId);

  // create and set offer SDP
  const offer = await this.localRtcPc.createOffer();
  await this.localRtcPc.setLocalDescription(offer);

  // send offer via signaling server
  this.linkSocket.emit("offer", { targetUid: calleeId, userId: callerId, offer });
}

Callback listeners – The onPcEvent function creates a data channel, handles remote tracks, negotiation, and ICE candidate exchange.

onPcEvent(pc, localUid, remoteUid) {
  // create a data channel
  that.channel = pc.createDataChannel('chat');

  // handle remote media tracks
  pc.ontrack = function(event) {
    that.setRemoteDomVideoStream('remoteVideo', event.track);
  };

  // negotiation needed
  pc.onnegotiationneeded = function(e) {
    console.log('重新协商', e);
  };

  // ICE candidate handling
  pc.onicecandidate = function(event) {
    if (event.candidate) {
      that.linkSocket.emit('candidate', {
        targetUid: remoteUid,
        userId: localUid,
        candidate: event.candidate,
      });
    } else {
      console.log('在此次协商中,没有更多的候选了');
    }
  };
}

Answer side – The onRemoteOffer function sets the remote description, creates an answer, sets the local description, and sends the answer back.

async onRemoteOffer(fromUid, offer) {
  // set remote description
  await this.localRtcPc.setRemoteDescription(offer);

  // create answer SDP
  const answer = await this.localRtcPc.createAnswer();

  // set local description
  await this.localRtcPc.setLocalDescription(answer);

  // send answer via signaling server
  this.linkSocket.emit('answer', { targetUid: fromUid, userId: getParams('userId'), answer });
}

Media stream changes – Using RTCRtpSender to enable/disable video, switch camera or screen share, and replace tracks.

// toggle video mode (audio/video)
const senders = this.localRtcPc.getSenders();
const send = senders.find(s => s.track.kind === 'video');
send.track.enabled = !send.track.enabled;

// screen share / camera switch
const stream = await this.getShareMedia();
const [videoTrack] = stream.getVideoTracks();
const send = senders.find(s => s.track.kind === 'video');
send.replaceTrack(videoTrack);

Datachannel IM – Creating a data channel for P2P text transmission and handling open/message events.

// create data channel
this.channel = pc.createDataChannel('my channel', { protocol: 'json', ordered: true });

pc.ondatachannel = function(ev) {
  console.log('Data channel is created!');
  ev.channel.onopen = function() { console.log('Data channel ------------open----------------'); };
  ev.channel.onmessage = function(ev) { console.log('Data channel ------------msg----------------'); };
};

Practical Issues and Solutions

Network problems : jitter and latency – use adaptive bitrate, packet‑loss retransmission, and STUN/TURN servers for NAT traversal.

Device compatibility : diverse browsers/devices – perform extensive compatibility testing, dynamically adjust resolution/frame‑rate, and apply progressive enhancement.

Security : data protection – employ end‑to‑end encryption (E2EE), strong algorithms such as AES and DTLS, and implement authentication/authorization.

Data storage : persistence – use distributed databases, encrypt stored data, and provide regular backup/recovery mechanisms.

Multi‑Party Communication Architectures

Mesh – each participant establishes direct P2P connections with all others. Advantages: no media server bandwidth, simple topology. Disadvantages: bandwidth and CPU load grow exponentially with participants; unsuitable for large meetings.

SFU (Selective Forwarding Unit) – a server forwards each client’s media streams to others without mixing. Advantages: saves client bandwidth, scales to many participants. Disadvantages: server must handle high forwarding load. Common tools: Mediasoup, SRS.

MCU (Multipoint Conferencing Unit) – a central server decodes, mixes, and re‑encodes streams into a single composite stream. Advantages: light client load, unified view. Disadvantages: high server CPU and bandwidth demand. Common tools: Jitsi, SRS.

Typical Application Scenarios

Live streaming : low‑latency transmission, multi‑stream forwarding, interactive features. Tools: SRS, FFmpeg.

Group meetings : multi‑stream management, dynamic layout, noise suppression. Tools: Mediasoup (SFU), Jitsi (MCU).

Online education : split‑screen, real‑time Q&A, high‑quality audio/video. Tools: Agora SDK, Zoom SDK.

Remote collaboration : screen sharing, file sync, recording. Tools: MS Teams, Zoom, Slack‑WebRTC integration.

Conclusion

The series explores WebRTC from a front‑end developer’s viewpoint, starting with a basic 1v1 audio/video call demo, then expanding to media control, datachannel IM, and finally comparing Mesh, SFU, and MCU architectures for multi‑party scenarios. It also outlines real‑world challenges—network variability, device diversity, security, and storage—and provides concrete mitigation strategies, equipping developers to design robust, scalable real‑time communication solutions.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

FrontendVueMCUWebRTCVideo CallMeshSFU
Full-Stack Cultivation Path
Written by

Full-Stack Cultivation Path

Focused on sharing practical tech content about TypeScript, Vue 3, front-end architecture, and source code analysis.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.