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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Full-Stack Cultivation Path
Focused on sharing practical tech content about TypeScript, Vue 3, front-end architecture, and source code analysis.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
