Vue、WebRTC、SocketIO、Node和Redis助力多人视频会议(上)

几个月来疫情持续蔓延,大家使用视频会议应用的次数也水涨船高。无论身处何地,只要有视频应用我们就能与朋友见面。那我们为什么不试着定制一款自己的会议应用,让会话变得更加真实呢? 话不多说,我们直接开始吧!


Zoom截图

实现这个目标不需要我们从头开始。在之前的文章中,我已经介绍过构建具有一对一私人视频功能的应用所需的各个步骤。那么我们就以此为基础对其进行完善,最后添加多对多视频的功能就大功告成了。

(因为下文我们会提到一些在上一篇文章中解释过的概念,如果你之前没有读过,我建议你先移步上一篇文章。)

基于需求,视频会议应具备以下功能:

创建会议的用户自动成为管理员,只有他/她能邀请其他人进入会议;

管理员只能邀请同一公共房间的用户进入会议;

无论是启动会议还是加入会议,用户都不能与其他用户私下交谈;

已经进入某个会议的用户不能进行私聊,也就是说没有人可以和他/她对话;

如果管理员结束会议,所有用户会自动退出会议;
2
测试视频会议功能

在深入探讨实现细节之前,我们先来了解一下webRTC多方架构的主要方法。

网状结构( Mesh

Mesh是最简单的一种架构。所有端之间都是相互连接的,会直接把自己的媒体发送到其他所有端上。
3
Mesh webRTC架构

优点:

. 基本和简单的webRTC实现

. 不需要多媒体中心服务器

缺点:

. 加载和带宽消耗(N-1上行和下行链路)过多;

. 不能扩展容纳过多端(最多4-6个端)。

混合和MCU (Multipoint Conference Unit)

每个端将其媒体发送到中心服务器,并从中心服务器接收媒体。MCU作为一个混合点,接收、解码和混合来自所有端的媒体,最后以单一流的形式发送给所有用户。

4

MCU混合架构

优点:

. 在客户端基本实现webRTC

. 每个端都有1个上行和下行链路

缺点:

. 需要具备强大处理能力的服务器端(解码和编码每个端的媒体)。

比如Kurento提供MCU媒体服务器来实现视频应用(下文提到的SFU拓扑结构除外)。

路由和 SFU(Selective Forward Unit)

每个端将自己的媒体发送到中心服务器,并从它那里接收所有其他的媒体流。SFU就像一个媒体的路由器,接收所有用户的媒体流,然后决定将哪些流发送给哪些用户。
5
SFU路由架构

优点:

. 服务器端计算成本较低(比MCU低)

. 非对称带宽(1个上行链路和N-1个下行链路)即可,适合ADSL连接。

缺点:

. 服务器端设计和实现较复杂。

SFU有三种不同的方法路由媒体:多单播、同播和SVC(可扩展视频编码)。像OpenViduMediasoup等供应商都提供了这几种拓扑。

给予我们的需求,我们决定实现第一种方法——最多支持3个端口的网状拓扑(但还是能扩展到更多用户的)。接下来我们来讨论下实现的细节。

完善措施

在开始讨论构建app的细节前,我们先进一步改进之前的架构,以期获取更简洁、架构更合理的代码。

WebRTC 通信机制

如前所述,在mesh架构中,所有的端与端之间都是直接连接的,之前私聊中两端间建立连接的机制和配置都没变。因此,我们在WebRTC.js文件中把这些相关项当作一个mixin单拎出来了:


export const videoConfiguration = {

data() {

return {

constraints: {}, // Media constraints

configuration: servers, // TURN/STUN ice servers

// Offer config

offerOptions: {

offerToReceiveAudio: 1,

offerToReceiveVideo: 1

},

// Local video

myVideo: undefined,

localStream: undefined,

username: ""

}

},

created() {

this.username = this.$store.state.username

},

// Method implementations

methods: {

async getUserMedia() { ... },

getAudioVideo() { ... },

async setRemoteDescription(remoteDesc, pc) {

try {

log(`${this.username} setRemoteDescription: start`)

await pc.setRemoteDescription(remoteDesc)

log(`${this.username} setRemoteDescription: finished`)

} catch (error) {

log(`Error setting the RemoteDescription in ${this.username}. Error: ${error}`)

}

},

async createOffer(pc, to, room, conference = false) { ... },

async createAnswer(pc, to, room, conference) { ... },

async handleAnswer(desc, pc, from, room, conference = false) { ... },

sendSignalingMessage(desc, offer, to, room, conference) { ... },

addLocalStream(pc) { ... },

addCandidate(pc, candidate) { ... },

onIceCandidates(pc, to, room, conference = false) { ... },

},

}

(WebRTC mixin)

文章地址:https://levelup.gitconnected.com/multiparty-video-conference-using-vue-webrtc-socketio-node-redis-e8c5a059d332

原文作者:Adrián García Diéguez

推荐阅读
作者信息
jemmayb
TA 暂未填写个人简介
文章
26
相关专栏
开源技术
63 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和 Agora 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。