一对一WebRTC视频通话系列(五)——综合调试和功能完善

本系列博客主要记录一对一WebRTC视频通话实现过程中的一些重点,代码全部进行了注释,便于理解WebRTC整体实现。


本专栏知识点是通过<零声教育>的音视频流媒体高级开发课程进行系统学习,梳理总结后写下文章,对音视频相关内容感兴趣的读者,可以点击观看课程网址:零声教育


一对一WebRTC视频通话系列往期博客

一对一WebRTC视频通话系列(一)—— 创建页面并显示摄像头画面
一对一WebRTC视频通话系列(二)——websocket和join信令实现
一对一WebRTC视频通话系列(三)——leave和peer-leave信令实现
一对一WebRTC视频通话系列(四)——offer、answer、candidate信令实现


主要完成工作:
(1)点击离开时,要将RTCPeerConnection关闭(close);
(2)点击离开时,要将本地摄像头和麦克风关闭;
(3)检测到客户端退出时,服务器再次检测该客户端是否已经退出房间。
(4)RTCPeerConnection时传入ICE server的参数,以便当在公网环境下可以进行正常通话

一、客户端

(1)点击离开时,要将RTCPeerConnection关闭(close);
(2)点击离开时,要将本地摄像头和麦克风关闭;
点击离开按钮后,
doLeave() -> hangup() -> closeLocalStream()

  1. doLeave()函数:发送消息离开房间。
    首先,创建一个jsonMsg对象,包含命令(cmd)、房间ID(roomId)和本地用户ID(localUserId)。
    使用JSON.stringify()方法将jsonMsg对象转换为字符串。
    调用zeroRTCEngine.sendMessage()方法将消息发送给服务器。
    输出消息内容到控制台。
    调用hangup()函数关闭本地视频流和RTCPeerConnection

  2. hangup()函数:关闭本地视频流和RTCPeerConnection
    设置localVideo.srcObject为null,不显示本地流。
    设置remoteVideo.srcObject为null,不显示对方。
    调用closeLocalStream()函数关闭本地流。
    检查pc变量是否为null,如果是,则关闭RTCPeerConnection

  3. closeLocalStream()函数:关闭本地视频流。
    检查localStream变量是否为null,如果是,则停止所有视频流。

  4. openLocalStream(stream)函数:用于打开本地流。
    检查stream变量是否为null,如果是,则输出日志信息,并调用doJoin()函数

function doLeave() {var jsonMsg = {'cmd': 'leave','roomId': roomId,'uid': localUserId,};var message = JSON.stringify(jsonMsg); //将json对象转换为字符串zeroRTCEngine.sendMessage(message);   //设计方法:用实现方法而不是直接用变量    console.info("doLeave message: " + message);hangup();
}function hangup() {localVideo.srcObject = null;//0.不显示本地流remoteVideo.srcObject = null;//1.不显示对方closeLocalStream();//2.关闭本地流if(pc != null){pc.close();//3.关闭RTCPeerConnectionpc = null;}
}
function closeLocalStream() {if(localStream != null){localStream.getTracks().forEach(function(track){track.stop();});localStream = null;}
}

关闭远程视频流,关闭RTCPeerConnection对象。

function handleRemotePeerLeave(message) {console.info("handleRomotePeerLeave message: " + message.remoteUid);remoteVideo.srcObject = null;if(pc != null){pc.close();//关闭RTCPeerConnectionpc = null;}
}

二、服务端

(3)检测到客户端退出时,服务器再次检测该客户端是否已经退出房间。

var server = ws.createServer(function (conn) {console.log("New connection");conn.sendText('我收到你的连接了')conn.client = null;//1.对应客户端信息// 监听客户端发送的消息conn.on("text", function (str) {console.info("Received msg:"+str);var jsonMsg = JSON.parse(str);switch(jsonMsg.cmd){case SIGNAL_TYPE_JOIN:conn.client = handleJoin(jsonMsg, conn); //2.返回值需要修改break;case SIGNAL_TYPE_LEAVE:handleLeave(jsonMsg);break;case SIGNAL_TYPE_OFFER:handleOffer(jsonMsg);break;case SIGNAL_TYPE_ANSWER:handleAnswer(jsonMsg);break;                 case SIGNAL_TYPE_CANDIDATE:handleCandidate(jsonMsg);break;}});// 连接关闭时的输出conn.on("close", function (code, reason) {console.log("Connection closed,code: " + code + " reason:" + reason); if(conn.client != null){ //3.如果客户还未删除//强制让客户端从房间退出handleForceLeave(conn.client);}});// 监听连接错误conn.on("error", function (error) {console.error("发生错误:", error);})
}).listen(port);

当连接关闭时,如果连接的客户端对象尚未删除,调用handleForceLeave函数强制让客户端从房间退出。

实现原理:
通过监听用户连接对象的 client.onclose 事件来触发 handleForceLeave 函数,并在其中强制离开用户。
1.首先,从用户连接对象中获取房间ID和用户ID。
2.然后,在全局变量roomTableMap 中查找房间ID对应的房间对象。
3.判断用户ID是否存在于房间内。如果不在房间内,则输出日志并返回。
4.如果用户已经在房间内,则输出日志并从房间对象中移除用户ID。
5.判断房间对象中是否还有其他用户。如果有其他用户,则给所有房间内其他用户发送用户离开消息。

function handleForceLeave(client){// 获取房间ID和用户IDvar roomId = client.roomId;var uid = client.uid;// 1.先查找房间号var roomMap = roomTableMap.get(roomId);if(roomMap == null){console.error("roomId: " + roomId + " is not exist");return;}// 2.判别uid是否在房间内if(roomMap.contains(uid) == false)  {console.info("uid: " + uid + " have leave roomId " + roomId);return;}// 3.说明客户端没有正常离开,所以我们要强制离开程序console.info("uid: " + uid + " force leave roomId " + roomId);roomMap.remove(uid);if(roomMap.size() >= 1){var clients = roomMap.getEntrys();for(var i in clients){jsonMsg = {'cmd':SIGNAL_TYPE_PEER_LEAVE,'remoteUid':uid}// 给所有房间内其他用户发送用户离开消息var msg = JSON.stringify(jsonMsg);var remoteUid = clients[i].key;var remoteClient =roomMap.get(remoteUid);if(remoteClient){console.info("notify peer "+ remoteClient.uid +" uid " + uid + " leave room");remoteClient.conn.sendText(msg);}}}    
}

三、公网通讯

(4)RTCPeerConnection时传入ICE server的参数,以便当在公网环境下可以进行正常通话

3.1 启动coturn

# nohup是重定向命令,输出都将附加到当前目录的 nohup.out 文件中; 命令后加 & ,后台执行起来后按
ctr+c,不会停止
sudo nohup turnserver -L 0.0.0.0 -a -u sxl:zxc -v -f -r nort.gov &
# 前台启动
sudo turnserver -L 0.0.0.0 ‐a -u sxl:zxc -v -f -r nort.gov
#然后查看相应的端口号3478是否存在进程
sudo lsof -i:3478

安装 sysstat包,查看网络情况

sudo apt-get install sysstat
sudo sar -n DEV 1

3.2修改配置文件

修改客户端main.js代码,

    var defaultConfiguration = {  bundlePolicy: "max-bundle",rtcpMuxPolicy: "require",iceTransportPolicy:"relay",//relay 或者 all// 修改ice数组测试效果,需要进行封装iceServers: [{"urls": ["turn:192.168.226.3:3478?transport=udp","turn:192.168.226.3:3478?transport=tcp"       // 可以插入多个进行备选],"username": "sxl","credential": "zxc"},{"urls": ["stun:192.168.226.3:3478"]}]};

new RTCPeerConnection()时,使用defaultConfiguration参数来创建对象。

pc = new RTCPeerConnection(defaultConfiguration);

测试

设置configuration,先设置为relay中继模式,只有relay中继模式可用的时候,才能部署到公网去(部署到公网后也先测试relay)。
使用realy中继:
在这里插入图片描述
使用局域网P2P
在这里插入图片描述
可以看出采用realy中继通信下,网络流量明显大于p2p。
下图显示了网络协商打印情况:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/681465.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity VR在编辑器下开启Quest3透视(PassThrough)功能

现在有个需求是PC端串流在某些特定时候需要开启透视。我研究了两天发现一些坑,记录一下方便查阅,也给没踩坑的朋友一些思路方案。 先说结论,如果要打PC端或者在Unity编辑器中开启,那么OpenXR当前是不行的可能还需要一个长期的过程,必须需要切换到Oculus。当然Unity官方指…

VisualGDB:Linux静态库项目创建、编译及库的使用

接上篇《VisualGDB&#xff1a;Linux动态库项目创建、编译及库的使用》&#xff0c;静态库的创建和使用与动态库基本无差别&#xff0c;唯一需要做的就是指定项目生成静态库。 一、指定项目生成静态库 二、重新构建和编译项目 这里注意&#xff0c;同样要copy一个libxxx.so格式…

AlphaFold 3来了!闭源但可供科研使用,DeepMind 子公司近水楼台先推进商用?

这里是引用 当地时间 5 月 8 日&#xff0c;Google DeepMind 联合其子公司 Isomorphic Labs 重磅发布 AlphaFold 3。 DeepMind 表示&#xff0c;AlphaFold 3 以前所未有的精确度成功预测了所有生命分子&#xff08;蛋白质、DNA、RNA、配体等&#xff09;的结构和相互作用。与现…

企业级通用业务 Header 处理方案

目录 01: 处理 PC 端基础架构 02: 通用组件&#xff1a;search 搜索框能力分析 03: 通用组件&#xff1a;search 搜索框样式处理 04: 通用组件&#xff1a;Button 按钮能力分析 05: 通用组件&#xff1a;Button 按钮功能实现 06: 通用组件&#xff1a;完善 search 基本…

地图位置的二维码怎么做?在线制作地图二维码的方法

怎么定位一个位置做成二维码呢&#xff1f;随着互联网的不断发展&#xff0c;现在通过扫描二维码来获取导航位置的方式有很多的场景都在应用。这种方式的好处在于其他人都可以通过这个二维码来获取位置&#xff0c;有利于分享。 导航地图二维码可以在电脑的二维码生成器上快速…

推荐 3 个 yyds 的开源项目!

本期推荐开源项目目录&#xff1a; 1. AI 搜索引擎 2. 大模型聊天框架 3. 模仿抖音的移动端短视频 01 AI 搜索引擎 Perplexica 是一个开源的、由 AI 驱动的搜索引擎。它深入互联网寻找答案&#xff0c;不仅搜索网络&#xff0c;还理解您的问题。 Perplexica 受到 Perplexity AI…

安卓使用Fiddler抓包 2024

简介 最近试了一下安卓使用fiddler 抓包&#xff0c;发现https包基本都会丢失。原因是Anandroid 7版本针对ssl安全性做了加强&#xff0c;不认可用户的证书。我们要做的就是把fiddler导出的证书进过处理后放置到系统证书目录下面&#xff0c;这样才能抓包https请求。 这里使用…

分割模型Maskformer系列

maskformer&#xff1a;Per-Pixel Classification is Not All You Need for Semantic Segmentation 论文地址&#xff1a;https://arxiv.org/pdf/2107.06278 1.概述 传统的语义分割方法通常采用逐像素分类&#xff08;per-pixel classification&#xff09;&#xff0c;而实…

Ubuntu20.4中复现Graspness

Ubuntu20.4中复现Graspness 文章目录 Ubuntu20.4中复现Graspness1.安装cuda和cudnn2.安装pytorch3.安装MinkowskiEngine4.编译graspnetAPI5. RuntimeError: "floor" "_vml_cpu" not implemented for IntRefernece &#x1f680;非常重要的环境配置&#x1…

uniapp:抖音PK进度条(nvue)

nvue中,仿抖音PK进度条效果, <template><view class="index" :style="{width:windowWidth+px,height:index_windowHeight+px,paddingTop:windowTop+px}"><view class="pk"><text class="pk_jindu_left_val fsz-24 …

UE和three.js的区别

UE&#xff08;Unreal Engine&#xff09;和three.js都是用于创建3D图形的软件平台&#xff0c;但它们在功能、目标和应用场景方面存在一些差异。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 功能 UE 是一款功能全面的3D游戏引擎&…

Excel操作之工具类

需求&#xff1a;根据指定的路径下模版进行解析 将模版上传到指定的文件服务器。 1&#xff1a;将路径下的excel文件进行解析 下载 A:创建excel表格对应的字段注解 ExcelColumn Retention(RetentionPolicy.RUNTIME) Target(ElementType.FIELD) public interface ExcelColumn …