写在前面

在开始之前,需要对如何建立点对点连接有一个了解,参考我的另一篇博文:WebRTC之点对点连接。下图是来自参考博文中的一张图片。

基础想法

基础架构如下:

客户端主要在于处理从WebSockets接收到的消息,并且有着发起连接和被动接受连接的功能。

实现
  1. 连接建立成功时,注册用户身份,表明想加入的房间号。

    ws.onopen = function () {console.log("connect success ... ");// 初始化当前用户身份let urlParams = urlSearch();user = {name: urlParams['name'],roomId: urlParams['roomId']};console.log("current user...", user);ws.send(JSON.stringify({msgType: requestType.USER_IDENTITY,msgBody: user}));};
    
  2. 通过web sockets 发起创建多个连接的请求。

    // call 按钮的点击事件中执行
    ws.send(JSON.stringify({msgType: requestType.CLIENT_MULTIPLY_CONNECTION_CREATEQUE,msgBody: user}));
    
  3. 接收服务器响应的房间成员信息,并创建多个用户连接(封装一个具有username和连接属性的对象),发送多个用户offer(username和offer)给信令服务器

    // web socket 接收到该消息
    ws.onmessage = function (evt) {// 接收到成员消息响应,创建多个连接if(result.msgType === requestType.SERVER_CALLEESRESP){console.log("接收到创建多个连接消息响应" + result.msgBody);createConnections(result.msgBody).catch((error)=>{console.log("创建成员连接出错..." , result.msgBody,error);});}};// 创建多个点对点连接和video元素
    async function createConnections(userNames) {const tempPcs = [];userNames.forEach(function (username){tempPcs.push({userName: username,pc: createRTCPeerConnection(username,createRemoteVideo(username))});});// 发送多个用户的username和offerconst offers = [];for (let i = 0; i < tempPcs.length; i++) {const pcc = tempPcs[i];const offer = await pcc.pc.createOffer(offerOptions);pcc.pc.setLocalDescription(offer).catch(()=>{console.log(pcc.userName + ">>> setLocalDescription error" , offer);});console.log("offer 创建完成...",offer);offers.push({userName: pcc.userName,sdp: offer});}if(offers.length !== 0){console.log("发送 多个offer消息...",offers);ws.send(JSON.stringify({msgType: requestType.SDP_OFFER,msgBody: offers}));}
    }// 创建点对点连接
    function createRTCPeerConnection(username,remoteVideo){const configuration = getSelectedSdpSemantics();console.log('RTCPeerConnection configuration:', configuration);const pc = new RTCPeerConnection(configuration);console.log(username+'>>> Created peer connection object pc');pc.addEventListener('icecandidate', e => onIceCandidate(e,username));pc.addEventListener('iceconnectionstatechange', e => onIceStateChange(pc, e));pc.addEventListener('track', e => {if (remoteVideo.srcObject !== e.streams[0]) {remoteVideo.srcObject = e.streams[0];console.log(username+'>>> pc received remote stream');}});localStream.getTracks().forEach(track => pc.addTrack(track, localStream));pcs.push({userName: username,pc: pc});return pc;
    }
    //
    function createRemoteVideo(id) {let remoteVideo = document.createElement('video');remoteVideo.playsinline = true;remoteVideo.autoplay = true;remoteVideo.id=id;//获取body节点localVideo.parentNode.insertBefore(remoteVideo, localVideo.nextSibling);return remoteVideo;
    }
  4. 客户端接收到offer消息时,创建连接,响应answer;并发起创建多个连接的请求消息,收到信令服务器响应的成员信息,创建多个连接,发送多个用户offer给信令服务器,并将之前创建的用户连接放入连接池中。

    // 接收到offer消息时if(result.msgType === requestType.SDP_OFFER){console.log("接收到offer消息" , result.msgBody);// 创建const rtcPeerConnection = createRTCPeerConnection(result.msgBody.userName, createRemoteVideo(result.msgBody.userName));rtcPeerConnection.setRemoteDescription(JSON.parse(msgBody.sdp)).catch((error)=>{console.log(result.msgBody.userName + ">>> setRemoteDesc error" , msgBody.sdp,error);});// 应答rtcPeerConnection.createAnswer().catch((error)=>{console.log(result.msgBody.userName + ">>> createAnswer error" , error);}).then(answer=>{rtcPeerConnection.setLocalDescription(answer).catch(()=>{console.log(result.msgBody.userName + ">>> setLocalDesc error" , answer);});// 响应answerws.send(JSON.stringify({msgType: requestType.SDP_ANSWER,msgBody: {userName:msgBody.userName,sdp: answer}}));});// 发送创建多个请求消息console.log("发送创建多个请求消息...");ws.send(JSON.stringify({msgType: requestType.CLIENT_MULTIPLY_CONNECTION_CREATEQUE,msgBody: user}));}
    
  5. 客户端收到单个answer消息时,放入对应用户连接的desc

    // 接收到answer消息时if(result.msgType === requestType.SDP_ANSWER){console.log("接收到answer消息...");pcs.forEach(function (pcc) {if(pcc.userName === msgBody.userName){pcc.pc.setRemoteDescription(JSON.parse(msgBody.sdp)).catch(()=>{console.log(msgBody.userName + ">>> setRemoteDesc error" + msgBody.sdp);});}});}
    
  6. 客户端设置发送candidate(包含用户信息和candidate)

    async function onIceCandidate(event,username) {try {console.log(username+">>> event.candidate..." + event.candidate);ws.send(JSON.stringify({msgType: requestType.SDP_CANDIDATE,msgBody: {userName: username,sdp: event.candidate}}));console.log(username+">>> send candidate msg success");} catch (e) {onAddIceCandidateError(pc, e);}
    }
    
  7. 客户端收到单个candidate消息时,添加到对应用户连接的IceCandidate中

    // 接收到candidate消息时if(result.msgType === requestType.SDP_CANDIDATE){console.log("接收到candidate消息...");pcs.forEach(function (pcc) {console.log(pcc.userName + "----" + msgBody.userName);if(pcc.userName === msgBody.userName){pcc.pc.addIceCandidate(JSON.parse(msgBody.sdp)).catch((error)=>{console.log(msgBody.userName + ">>> addIceCandidate error" , msgBody.sdp,error);});console.log(`${pcc.pc} addIceCandidate success`);}});}
    

推荐博文


参考博文


https://blog.csdn.net/heqinghua217/article/details/52174541 webRtc+websocket多人视频通话

WebRTC实现多人视频聊天之客户端设计相关推荐

  1. WebRTC实现多人视频聊天

    写在前面 实现房间内人员的视频聊天,由于并未很完善,所以需要严格按照步骤来,当然基于此完善,就是时间的问题了. 架构 整个设计架构如下: 图片来自于参考博文.我使用的是第一种Mesh 架构,无需任何流 ...

  2. WebRTC实现多人视频聊天之信令服务器设计

    基础设想 信令服务器主要负责转发 SDP ,当然,我也可以选择将我的业务逻辑写在里面(生产环境不推荐这样做).选择基于Web Sockets主要是因为这块比较熟悉,并且双向连接,我们能够基于此做的事非 ...

  3. 教你用WebRTC撸一个多人视频聊天

    之前公司准备用 webRTC 来实现视频聊天,研究了几天,撸了个 demo 出来,(虽然最后并没有采用这项技术,囧),但是还是写一个出来吧! WebRTC简单介绍 WebRTC (Web Real-T ...

  4. 实践:《从头到脚撸一个多人视频聊天 — 前端 WebRTC 实战(一)》

    2019独角兽企业重金招聘Python工程师标准>>> 请先阅读原文,链接:从头到脚撸一个多人视频聊天 - 前端 WebRTC 实战(一),本文只涉及实践过程中的问题 1.video ...

  5. Android 集成 Agora SDK 快速体验 RTC 版多人视频聊天|掘金技术征文

    RTC (Real-Time Communication) 作为实时通讯领域的"新贵",在互动直播.远程控制.多人视频会议.屏幕共享等领域广受好评,如果你还不了解 RTC ,Tak ...

  6. 【游戏开发实战】Unity从零开发多人视频聊天功能,无聊了就和自己视频聊天(附源码 | Mirror | 多人视频 | 详细教程)

    文章目录 一.前言 二.思考问题与解决方案 1.思考问题 2.解决方案 2.1.Unity中如何开启摄像头并对图像进行采样 2.2.图像如何中转给其他客户端 2.3.如何实现清晰度切换 2.4.客户端 ...

  7. (Agora声网)多人视频聊天应用的开发(二)一对一聊天

    转载于:Android多人视频聊天应用的开发(二)一对一聊天-玖哥的书房-51CTO博客 http://blog.51cto.com/dongfeng9ge/2095626 本系列文章结合声网官方在G ...

  8. Android多人视频聊天应用的开发(二)一对一聊天

    在上一篇<Android多人视频聊天应用的开发(一)快速集成>中我们讨论了如何配置Agora Android SDK,本文我们将探索使用Agora进行一对一视频聊天的奥秘. 鉴权 APP ...

  9. 都秀多人视频聊天软件【常用软件】

    都秀视频聊天软件是北京都秀网络科技有限公司基于宽带网络推出的"全新网络多人视频聊天工具".都秀聊天室整合了文本.语音.视频等多种互联网通信形式于一身,旨在为广大互联网用户提供融合数 ...

最新文章

  1. 如何取消JS事件的派发——stopPropagation()
  2. 【公司金融课堂学习笔记】1、企业融资—风险投资
  3. 百度SEO优化技术点总结
  4. 执行计划生成及查看的几种方法
  5. 刻不容缓!联合国加开会议讨论「如何限制杀人机器人」
  6. 37. 错误与异常处理(1)
  7. 山石防火墙增加端口映射
  8. 如何将txt文件转为EXCEL文件?
  9. docker学习系列:设置阿里云容器加速器
  10. 上下文切换调优-性能设计沉思录(9)
  11. 单片机炫彩灯实训报告_单片机实验报告一-流水灯实验
  12. 【Windows】之电脑之间共享文件(亲测可行)
  13. 夏天摆地摊,卖什么产品赚钱比较快呢?
  14. jdk重复安装,Error:Registry key ‘Software\JavaSoft\Java Runtime Environment\CurrentVersion(已解决)
  15. [zabbix]cat ‘/home/cjw/create (1).sql/data‘ | mysql -uzabbix -p123456 -Dzabbix ERROR 1049 (42000):
  16. Consumer消息拉取和消费流程分析
  17. 攻防世界 Misc 适合作为桌面
  18. php微信红包雨效果,微信红包雨特效口令大全 微信红包雨特效口令有哪些
  19. 计算机word文本段落位置互换,切换、调换、互换word段落的位置
  20. AcWing-算法提高课【合集】

热门文章

  1. PAT (Advanced Level) Practice A1090 Highest Price in Supply Chain (25 分)(C++)(甲级)(树,深度)
  2. Lua - 输出打印table表
  3. web浏览器博物馆_Web-Based Interactive Storytelling (2)
  4. 计算机u盘 硬盘无法读取,电脑无法识别usb设备,电脑无法识别u盘,移动硬盘解决方法汇总...
  5. 奥鹏福建师范大学2021年2月考试《计算机应用基础》作业56754
  6. 【Android】多功能二维码实现思路,自动连接WI-FI
  7. PUTTY连接之诡异现象:虚拟机连接方式
  8. 江南电子计算机研究所,我的中国“芯” | 江南计算所SW1600:国产超算“神威蓝光”的“心脏”-控制器/处理器-与非网...
  9. Dubbo 启动报java.lang.NoClassDefFoundError: org/apache/curator/RetryPolicy
  10. 方向标 | c++ | 动态规划