2023.5.20第二阶段冲刺日报
Posted Arkiya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2023.5.20第二阶段冲刺日报相关的知识,希望对你有一定的参考价值。
再之前的第二阶段冲刺中,我们尝试了在安卓端进行视频会议,并取得了一定的成果,在安卓端进行尝试的一个主要原因是再web端进行视频通话等需要进行服务器的搭建,而我们之前从未接触过这个领域因此。产生了决定先从安卓端开始,对这一过程进行一定的了解,但是安卓端的话我们之前的代码不能很好的利用,因此在接下来的冲刺阶段我们决定继续攻克web端。
因此我们需要从最基础的搭建服务器开始,通过查阅资料,需要使用webtrc
最简单的Web视频会议,只需要架设一个Web服务器,服务器兼具信令交换的能力(信令服务也可以独立部署),两个浏览器通过Web Server交换会话信息,就能建立P2P通道来传输媒体流,进行1v1的视频会议。两个浏览器向Web服务器请求页面,并进行SDP交换,然后在浏览器之间直接建立P2P Transport,进行媒体流传输。这是最简单的WebRTC应用形式。
通过在网上查阅资料,找到了一个较为基础的代码,在接下来将基于这个代码进行学习,并在此基础上进行改进融入我们的代码中
<?php header("Content-type:text/html;charset=utf8"); //获取room 和 title $room = @$_GET["room"]; $title = @$_GET["title"]; $uid = time(); //访问时间设置为uid //获取roomtoken if(empty($room)||empty($title)) echo "failure"; exit; $room = "zt".$room; $uid = "ztu".$uid; $expireTime = time()+60*60*24; //1天后过期 //test $appid = "七牛appid"; //申请地址:https://doc.qnsdk.com/rtn $secretKey = "七牛sk"; $accessKey = "七牛ak"; //base64 以下为php版校验key function base64_urlSafeEncode($data) $find = array(\'+\', \'/\'); $replace = array(\'-\', \'_\'); return str_replace($find, $replace, base64_encode($data)); //data $tokenDesc = array( \'appId\' => $appid, \'roomName\' => $room, \'userId\' => $uid, \'expireAt\' => $expireTime, \'permission\' => "user" ); $tokenDescJson = json_encode($tokenDesc); $encodedTokenDesc = base64_urlSafeEncode($tokenDescJson); $sign = hash_hmac(\'sha1\', $encodedTokenDesc, $secretKey, TRUE); $encodedSign = base64_urlSafeEncode($sign); $roomToken = $accessKey.":".$encodedSign.":".$encodedTokenDesc; ?> <html> <head> <title><?php echo $title; ?>-视频会议</title> <meta name="decorator" content="default"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0"> <style type="text/css"> bodyposition: relative;margin:0;padding:0;overflow:hidden;background-color:#212121;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale*box-sizing:border-box;margin: 0px;padding: 0px; html,bodywidth: 100%;height: 100%; .bigdwidth: 100%;height: 100% .titleposition: absolute;left: 0px; top: 10px; color: #fff; font-size: 14px; width:100%; text-align:center; .fqrposition: absolute;right: 10px; top: 10px; color: #fff; font-size: 14px; .wjtoutline: none;width: 50px; height:50px; border-radius: 50px; border: none; background: url("./wjt.png") no-repeat; background-size: 50px 50px;position: absolute;bottom: 10px; left: 48%; .gdoutline: none;width: 50px; height:50px; border-radius: 50px; border: none; background: url("./gd.png") no-repeat; background-size: 50px 50px;position: absolute;bottom: 10px; left: 48%; .mylistwidth: 100%;height: 5rem;position: absolute;left: 0px;bottom: 70px; .listdisplay: block; height: 5rem; .list .onewidth: 100px;height: 100%; margin-left: 10px; float: left; position: relative;background-color: #4a4a4a; cursor: pointer .one_videowidth: 100%; height: 100%; .one_textposition: absolute; left: 0px; width: 100%;bottom: 5px;width: 100%; text-align: center; color: #fff;font-size: 12px; #share-2position: absolute;left: 10px; bottom: 10px; videowidth:100%; height:100%; audiovisibility:hidden .maxposition: fixed!important; z-index: -1!important;left: 0px!important; top: 0px!important; width: 100%!important; height: 100%!important;bottom: auto!important;background-color:#212121!important; .max .one_textdisplay:none; </style> </head> <body onbeforeunload="checkLeave()"> <!--房间标题--> <div class="title"><?php echo $title; ?></div> <!--挂断按钮--> <button class="wjt" onclick="myleave(this)"></button> <!--已在线人--> <div class="mylist"> <div class="list"> <div class="one max" onclick="swithDialog(\'local\')"> <div class="one_video" id="videolocal" ></div> <div class="one_text">本机</div> </div> </div> </div> <!--分享--> <script type="text/javascript" src="./jquery-1.10.2.js"></script> <link rel="stylesheet" href="./share.min.css" /> <script type="text/javascript" src="./jquery.share.min.js?V4"></script> <div id="share-2"></div> <script type="text/javascript"> if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) else $(\'#share-2\').share(sites: [\'qq\', \'weibo\',\'wechat\']); </script> <script type="text/javascript" src="./scrollBar.js"></script> <script type="text/javascript" src="./pili-rtc-web.js"></script> <script> var RoomToken = \'<?php echo $roomToken; ?>\'; // 确认引入成功 console.log("current version", QNRTC.version); var myRoom_this = null; // 这里采用的是 async/await 的异步方案,您也可以根据需要或者习惯替换成 Promise 的写法 async function joinRoom() $(".wjt").attr("class","gd"); // 初始化一个房间 Session 对象, 这里使用 Stream 模式 const myRoom = new QNRTC.StreamModeSession(); myRoom_this = myRoom; // 这里替换成刚刚生成的 RoomToken await myRoom.joinRoomWithToken(RoomToken); console.log("joinRoom success!"); //显示已连接的流视频 autoSubscribe(myRoom); //播放本地视频摄像头 try await publish(myRoom); catch(e) alert("权限获取失败,请允许摄像头访问"); // 增加一个函数 publish,用于采集并发布自己的媒体流 // 这里的参数 myRoom 是指刚刚加入房间时初始化的 Session 对象 async function publish(myRoom) // 调用采集模块采集本地的音频和视频数据,返回一个包含这些数据的 Stream 对象 const localStream = await QNRTC.deviceManager.getLocalStream( audio: enabled: true , video: enabled: true , ); // 将刚刚的 Stream 对象发布到房间中 await myRoom.publish(localStream); console.log("publish success!"); // 在这里添加 // 获取页面上的一个元素作为播放画面的父元素 const localElement = document.getElementById("videolocal"); // 调用 Stream 对象的 play 方法在这个元素下播放媒体流,其中第二个参数代表 静音播放 localStream.play(localElement, true); if(confirm("我们将采集您的摄像头/麦克风数据并与房间其他用户进行音视频通话")) joinRoom();//启动 // 这里的参数 myRoom 是指刚刚加入房间时初始化的 Session 对象, 同上 // userId 是指订阅对象的用户名 async function subscribe(myRoom, userId) //判断是否存在该视频 if($("#video"+userId).length==0) var html = \'<div class="one" onclick="swithDialog(\\\'\'+userId+\'\\\')">\\n\' + \' <div class="one_video" id="video\'+userId+\'" ></div>\\n\' + \' <div class="one_text">\'+userId+\'</div>\\n\' + \' </div>\'; $(".list").append(html); // 调用订阅方法发起订阅,成功会返回一个 Stream 对象,这就是远端的流了 const remoteStream = await myRoom.subscribe(userId); // 选择页面上的一个元素作为父元素,播放远端的流 const remoteElement = document.getElementById("video"+userId); remoteStream.play(remoteElement); // 这里的参数 myRoom 是指刚刚加入房间时初始化的 Session 对象, 同上 function autoSubscribe(myRoom) const users = myRoom.users; console.log("room current users", users) // 遍历房间当前所有用户 for (const user of users) // 如果存在一个用户,用户名不是自己并且已经发布 // 就可以发起订阅了 if (user.userId !== myRoom.userId && user.published) // 调用我们刚刚编写的 subscribe 方法 // 注意这里我们没有使用 async/await,而是使用了 Promise,大家可以思考一下为什么 subscribe(myRoom, user.userId) .then(() => console.log("subscribe success!")) .catch(e => console.error("subscribe error", e)); //width change $(".list").css("width",$(".list .one").length*110+"px"); $(".mylist").scrollBar(); // 接下来我们需要处理第二种情况,也就是监听事件来感知房间内有用户发布了 myRoom.on("user-publish", (user) => console.log("user", user.userId, "is published!"); subscribe(myRoom, user.userId) .then(() => console.log("subscribe success!")) .catch(e => console.error("subscribe error", e)); ); //远程用户离开房间 myRoom.on("user-leave",(user)=> console.log("user", user.userId, "go leave!"); if($("#video"+user.userId).length>0)//存在用户 $("#video"+user.userId).parent(".one").remove();//去掉UI ); //离开房间 function myleave(obj) $(obj).attr("class","wjt"); myRoom_this.leaveRoom(); //交换窗口 function swithDialog(zid) $("#video"+zid).parent(".one").addClass("max"); $("#video"+zid).parent(".one").siblings().removeClass("max"); //离开页面 function checkLeave() myRoom_this.leaveRoom(); </script> </body> </html>
第二阶段冲刺
时间:12:00-12:15
地点:基教
内容:对第二阶段冲刺进行整体部署,任务分配,详细讨论第二阶段冲刺的计划
照片:
燃尽图
以上是关于2023.5.20第二阶段冲刺日报的主要内容,如果未能解决你的问题,请参考以下文章