编程语言
首页 > 编程语言> > webrtc实现视频群聊系列文章终章之完成即时通讯+多人视频会议(开放源码)

webrtc实现视频群聊系列文章终章之完成即时通讯+多人视频会议(开放源码)

作者:互联网

引言

前面几篇文章讲了使用webrtc实现本地模拟通话视频聊天,现实网络1对1视频聊天以及屏幕分享和聊天随时切换的文章,接下来就下来实战怎么利用webrtc实现多人群视频通话,会议

思路

  1. 因为webrtc是点对点的,通过前面文章我们也实现了相应的效果,但是多对多的实现思路也是基于此的,条件是:一对一维护一个PeerConnection,多对多维护nPeerConnection
  2. 简单的讲就是每个客户端维护会议室中自己和其他会议室所有人的链接信息PeerConnection
  3. 当会议室中有人加入进来之后,加入的一方通知服务器自己加入,服务器发送通知给其他已经在会议室的人
  4. 等到初始化完成每个客户端的PeerConnection后,最后加入的用户向每个成员发送offer
  5. 每个成员监听到offer后响应answer
  6. 通过onicecandidate 实现多端ICE候选,最后检测每个客户端视频加入到本地video标签并以各个用户名称命名元素ID
  7. 流程基本不变,和点对点的一样,只不过在web端多了一些操作,以前是一个发送一个接受响应,现在是一个发送,多个监听响应

演示

源码地址

具体代码实现


//初始化 PeerConnection
initPeer(peerName,e){
    const that = this;
    console.log(peerName+"初始化PeerConnection")
    let peer_tep = new PeerConnection(this.iceServers);
    peer_tep.addStream(that.localStream);
    peer_tep.onicecandidate = function(event) {
        console.log("监听ice候选信息",event.candidate)
        if (event.candidate) {
            let candidate_data = {userId:that.userInfo.userId,username:that.userInfo.username,candidate:event.candidate}
            let params = {userId:that.userInfo.userId,targetId:e.userId,targetName:e.username,targetType:2,data:candidate_data}
            that.socket.emit("candidate",params)
        }else{
            console.log("ICE收集已经完成")
        }
    };
    peer_tep.onaddstream = (event) => {
        console.log("监听到视频加入 加入用户 ",e.username)
        that.createEleVideo(event.stream,e.username)
    };
    that.userPeerList[peerName] = peer_tep;
},


//创建连接
async onCreateOffer() {
    const that = this;
    console.log("开始创建offer")
    for(const ele of that.groupUserList){
        let peerName = that.userInfo.username+"-"+ele.username;
        if(that.userInfo.username !== ele.username){
            //创建offer
            let offer = await that.userPeerList[peerName].createOffer(that.offerOption);
            //设置本地描述
            await that.userPeerList[peerName].setLocalDescription(offer)
            //远程发送到服务器 并转发到其他的客户端
            let data = {offer:offer,userId:that.userInfo.userId,username:that.userInfo.username,info:"发送offer"}
            let params = {userId:that.userInfo.userId,targetId:ele.userId,targetName:ele.username,targetType:2,data:data}
            that.socket.emit("offer",params)
        }
    }
},

//监听 Ice 候选
async onIceCandidate(data) {
    const that = this;
    let peerName = that.userInfo.username+"-"+data.data.username;
    await that.userPeerList[peerName].addIceCandidate(data.data.candidate)
},
//监听远端offer
async onOffer(data) {
    const that = this;
    let peerName = that.userInfo.username+"-"+data.data.username;
    await that.userPeerList[peerName].setRemoteDescription(data.data.offer)
    // 接收端创建 answer
    let answer = await that.userPeerList[peerName].createAnswer();
    // 接收端设置本地 answer 描述
    await that.userPeerList[peerName].setLocalDescription(answer);
    //发送到呼叫端 answer
    let answer_data = {userId:that.userInfo.userId,username:that.userInfo.username,answer:answer}
    let params = {userId:that.userInfo.userId,targetId:data.data.userId,targetName:data.data.username,targetType:data.targetType,data:answer_data}
    that.socket.emit("answer",params)
},
//监听远程响应
async onAnswer(data) {
    const that = this;
    let peerName = that.userInfo.username+"-"+data.data.username;
    // 发送端 设置远程 answer 描述
    await that.userPeerList[peerName].setRemoteDescription(data.data.answer);
},

//追加视频
createEleVideo(stream,id){
    console.log("createEleVideo",stream);
    let ele = document.getElementById("ManyToManyVideo");
    let old = document.getElementById(id);

    if(old){
        old.srcObject = stream;
    }else{
        let video = document.createElement('video');
        video.controls = true;
        video.autoplay = true;
        video.width = 230;
        video.height = 200;
        video.volume = 0.1;
        video.id = id;
        video.srcObject = stream;
        ele.append(video);
    }
},

最后

标签:username,群聊,userId,peerName,let,userInfo,终章,开放源码,data
来源: https://www.cnblogs.com/wangsr-suc/p/13638217.html