直播系统源码中关于直播间人数统计功能的开发流程

通常在直播系统源码中,直播间人数是非常重要的统计数据,由于需要统计实时的人数,因此需要如下处理。
1.当用户进入和退出直播间,触发进入和退出直播间的广播,通知客户端增减人数。
2.当新用户进入直播间时,要给该用户提供相应的房间人数的数据
3.在数据库中存储累计人数,用于统计
4.Redis中存储用户列表,方便用户列表的相关功能使用
处理代码如下:
1.进入房间部分

//进入房间
	socket.on('conn', function(data) {

		if(!data || !data.token){
				return !1;
		}
		userid=data.uid;
		old_socket = sockets[userid];
		if (old_socket && old_socket != socket) {
			
			if(data.uid != data.roomnum && data.uid==old_socket.roomnum){
                /* 进房间 但旧链接是 主播 */
                var data_str='{"retmsg":"ok","retcode":"000000","msg":[{"msgtype":"1","_method_":"StartEndLive","action":"19","ct":"直播关闭"}]}';
				old_socket.emit('broadcastingListen',[data_str]);
			}else if(data.uid== data.roomnum && data.stream==old_socket.stream){
                /* 主播重连 */
				old_socket.reusing = 1;
				//console.log("重用");
			}else if(data.uid== data.roomnum && data.stream!=old_socket.stream){
                /* 主播多端开播 */
				var data_str='{"retmsg":"ok","retcode":"000000","msg":[{"msgtype":"1","_method_":"StartEndLive","action":"19","ct":"直播关闭"}]}';
				old_socket.emit('broadcastingListen',[data_str]);
			}
			old_socket.disconnect()
		}
		
		clientRedis.get(data.token,function(error,res){
			if(error){
				return;
			}else if(res==null){
				//console.log("[获取token失败]"+data.uid);
			}else{
				if(res != null){
					
					var userInfo = evalJson(res);
					if(userInfo['id'] == data.uid ){
						//console.log("[初始化验证成功]--"+data.uid+"---"+data.roomnum+'---'+data.stream);
						//获取验证token
						socket.token   = data.token; 
						socket.roomnum = data.roomnum;
						socket.stream = data.stream;
						socket.nicename = userInfo['user_nicename'];
						socket.level = userInfo['level'];
						socket.avatar = userInfo['avatar'];
						socket.sign = Number(userInfo['sign']);
						socket.usertype   = parseInt(userInfo['usertype']);
						socket.uid     = data.uid;
						socket.reusing = 0;
						
						socket.join(data.roomnum);
						sockets[userid] = socket;
						socket.emit('conn',['ok']);
                        
						if( socket.roomnum!=socket.uid && socket.uid >0 ){
                            /* 处理有时 无座驾信息会崩溃的问题 */
                            var car_id='0';
                            var car_swf='';
                            var car_swftime='';
                            var car_words='';
                            if(userInfo.hasOwnProperty("car")){
                                var carinfo=userInfo['car'];
                                if(carinfo.hasOwnProperty("id")){
                                    car_id=carinfo['id'];
                                }
                                if(carinfo.hasOwnProperty("swf")){
                                    car_swf=carinfo['swf'];
                                }
                                if(carinfo.hasOwnProperty("swftime")){
                                    car_swftime=carinfo['swftime'];
                                }
                                if(carinfo.hasOwnProperty("words")){
                                    car_words=carinfo['words'];
                                }
                            }
                            
							var data_obj={
                                            "msg":[
                                                {
                                                    "_method_":"SendMsg",
                                                    "action":"0",
                                                    "ct":{
                                                        "id":''+userInfo['id'],
                                                        "user_nicename":''+userInfo['user_nicename'],
                                                        "avatar":userInfo['avatar'],
                                                        "avatar_thumb":userInfo['avatar_thumb'],
                                                        "level":''+userInfo['level'],
                                                        "usertype":''+userInfo['usertype'],
                                                        "vip_type":''+userInfo['vip']['type'],
                                                        "guard_type":''+userInfo['guard_type'],
                                                        "liangname":''+userInfo['liang']['name'],
                                                        "car_id":''+car_id,
                                                        "car_swf":''+car_swf,
                                                        "car_swftime":''+car_swftime,
                                                        "car_words":''+car_words
                                                    },
                                                    "msgtype":"0"
                                                }
                                            ],
                                            "retcode":"000000",
                                            "retmsg":"OK"
                                        };
	//发送进入房间消息
							process_msg(io,socket.roomnum,JSON.stringify(data_obj));
							if(socket.stream){
								clientRedis.zadd('user_'+socket.stream,socket.sign,userInfo['id']);	
							}
						}						
						 
						sendSystemMsg(socket,"直播内容包含任何低俗、暴露和涉黄内容,账号会被封禁;安全部门会24小时巡查哦~");
						return;
					}else{
						socket.disconnect();
					}
				}
			}
			
			socket.emit('conn',['no']);
		});
        
		
	});

2.离开房间部分

 //资源释放
	socket.on('disconnect', function() { 
			/* numscount--; 
            if(numscount<0){
				numscount=0;
			}   */
          			
			if(socket.roomnum ==null || socket.token==null || socket.uid <=0){
				return !1;
			}
				
			d.run(function() {
				/* 用户连麦 */
				clientRedis.hget('ShowVideo',socket.roomnum,function(error,res){
                    if(error){
                        return !1;
                    }
                    if(!res){
                        return !1;
                    }
                    var res_j=JSON.parse(res);
                    
                    if( socket.uid == res_j['uid'] || socket.uid == socket.roomnum ){
                        clientRedis.hdel('ShowVideo',socket.roomnum);
                        var data_obj={
                                        "msg":[
                                            {
                                                "_method_":"ConnectVideo",
                                                "action":"5",
                                                "msgtype":"10",
                                                "uid":""+socket.uid,
                                                "uname":""+socket.nicename
                                            }
                                        ],
                                        "retcode":"000000",
                                        "retmsg":"OK"
                                    };
                        process_msg(io,socket.roomnum,JSON.stringify(data_obj));									
                    }	
					 
				});
				
				
				if(socket.roomnum==socket.uid){
					/* 主播 */ 
					if(socket.reusing==0){
						request(config['WEBADDRESS']+"?service=Live.stopRoom&uid="+socket.uid + "&token=" + socket.token+ "&type=1&stream=" + socket.stream,function(error, response, body){
                            var data_obj={
                                        "retmsg":"ok",
                                        "retcode":"000000",
                                        "msg":[
                                            {
                                                "msgtype":"1",
                                                "_method_":"StartEndLive",
                                                "action":"18",
                                                "ct":"直播关闭"
                                            }
                                        ]
                                    };
                            process_msg(io,socket.roomnum,JSON.stringify(data_obj));
                            // console.log('关播');
                            // console.log(FormatNowDate());
                            // console.log('uid---'+socket.uid);
                        });
                        endLiveConnect(io,socket.uid);
					}
                    
                    
                    
				}else{
					/* 观众 */
                    clientRedis.zrem('user_'+socket.stream,socket.uid,function(error,res){
						if(error) return;
						if(res){
							var data_obj={
                                            "msg":[
                                                {
                                                    "_method_":"disconnect",
                                                    "action":"1",
                                                    "ct":{
                                                        "id":''+socket.uid,
                                                        "user_nicename":''+socket.nicename,
                                                        "avatar":socket.avatar,
                                                        "level":''+socket.level
                                                    },
                                                    "msgtype":"0",
                                                    "uid":''+socket.uid,
                                                    "uname":socket.nicename
                                                }
                                            ],
                                            "retcode":"000000",
                                            "retmsg":"OK"
                                        };
							process_msg(io,socket.roomnum,JSON.stringify(data_obj));	
						}
						
					});
					
				}
				////console.log(socket.roomnum+"==="+socket.token+"===="+socket.uid+"======"+socket.stream);
				
				socket.leave(socket.roomnum);
				delete io.sockets.sockets[socket.id];
				sockets[socket.uid] = null;
				delete sockets[socket.uid];

			});
	});

});

3.用户进入房间返回数据与缓存操作

	public function enterRoom() {
		$rs = array('code' => 0, 'msg' => '', 'info' => array());
		
		$uid=$this->uid;
		$token=checkNull($this->token);
		$liveuid=$this->liveuid;
		$city=checkNull($this->city);
		$stream=checkNull($this->stream);
        
        $checkToken=checkToken($uid,$token);
		if($checkToken==700){
			$rs['code'] = $checkToken;
			$rs['msg'] = '您的登陆状态失效,请重新登陆!';
			return $rs;
		}
        
        
		$isban = isBan($uid);
		if(!$isban){
			$rs['code']=1001;
			$rs['msg']='该账号已被禁用';
			return $rs;
		}

		
		$domain = new Domain_Live();
        
        $domain->checkShut($uid,$liveuid);
		$userinfo=getUserInfo($uid);
		
		$carinfo=getUserCar($uid);
		$userinfo['car']=$carinfo;
		$issuper='0';
		if($userinfo['issuper']==1){
			$issuper='1';
			DI()->redis  -> hset('super',$userinfo['id'],'1');
		}else{
			DI()->redis  -> hDel('super',$userinfo['id']);
		}
		if(!$city){
			$city='好像在火星';
		}
		
		$data=array('city'=>$city);
		$domain2 = new Domain_User();
		$info = $domain2->userUpdate($uid,$data);
		$userinfo['city']=$city;

		$usertype = isAdmin($uid,$liveuid);
		$userinfo['usertype'] = $usertype;
        
        $stream2=explode('_',$stream);
		$showid=$stream2[1];
        
        $contribution='0';
        if($showid){
            $contribution=$domain->getContribut($uid,$liveuid,$showid);
        }

		$userinfo['contribution'] = $contribution;

		
		unset($userinfo['issuper']);
        
        /* 守护 */
        $domain_guard = new Domain_Guard();
		$guard_info=$domain_guard->getUserGuard($uid,$liveuid);
        
		$guard_nums=$domain_guard->getGuardNums($liveuid);
        $userinfo['guard_type']=$guard_info['type'];
        /* 等级+100 保证等级位置位数相同,最后拼接1 防止末尾出现0 */
        $userinfo['sign']=$userinfo['contribution'].'.'.($userinfo['level']+100).'1';
		
		DI()->redis  -> set($token,json_encode($userinfo));
		
        /* 用户列表 */
        $userlists=$this->getUserList($liveuid,$stream);
        
        /* 用户连麦 */
		$linkmic_uid='0';
		$linkmic_pull='';
		$showVideo=DI()->redis  -> hGet('ShowVideo',$liveuid);
		// file_put_contents('./showVideo.txt',date('Y-m-d H:i:s').' 提交参数信息 liveuid:'.json_encode($liveuid)."\r\n",FILE_APPEND);
		// file_put_contents('./showVideo.txt',date('Y-m-d H:i:s').' 提交参数信息 showVideo:'.json_encode($showVideo)."\r\n",FILE_APPEND);
		if($showVideo){
            $showVideo_a=json_decode($showVideo,true);
			$linkmic_uid=$showVideo_a['uid'];
			$linkmic_pull=$this->getPullWithSign($showVideo_a['pull_url']);
		}
        
        /* 主播连麦 */
        $pkinfo=array(
            'pkuid'=>'0',
            'pkpull'=>'0',
            'ifpk'=>'0',
            'pk_time'=>'0',
            'pk_gift_liveuid'=>'0',
            'pk_gift_pkuid'=>'0',
        );
        $pkuid=DI()->redis  -> hGet('LiveConnect',$liveuid);
        //file_put_contents('./LiveConnect.txt',date('Y-m-d H:i:s').' 提交参数信息 进房间:'."\r\n",FILE_APPEND);
        //file_put_contents('./LiveConnect.txt',date('Y-m-d H:i:s').' 提交参数信息 uid:'.json_encode($uid)."\r\n",FILE_APPEND);
        //file_put_contents('./LiveConnect.txt',date('Y-m-d H:i:s').' 提交参数信息 liveuid:'.json_encode($liveuid)."\r\n",FILE_APPEND);
        if($pkuid){
            $pkinfo['pkuid']=$pkuid;
            /* 在连麦 */
            $pkpull=DI()->redis  -> hGet('LiveConnect_pull',$pkuid);
            $pkinfo['pkpull']=$this->getPullWithSign($pkpull);
            $ifpk=DI()->redis  -> hGet('LivePK',$liveuid);
            if($ifpk){
                $pkinfo['ifpk']='1';
                $pk_time=DI()->redis  -> hGet('LivePK_timer',$liveuid);
                if(!$pk_time){
                    $pk_time=DI()->redis  -> hGet('LivePK_timer',$pkuid);
                }
                $nowtime=time();
                if($pk_time && $pk_time >0 && $pk_time< $nowtime){
                    $cha=5*60 - ($nowtime - $pk_time);
                    $pkinfo['pk_time']=(string)$cha;
                    
                    $pk_gift_liveuid=DI()->redis  -> hGet('LivePK_gift',$liveuid);
                    if($pk_gift_liveuid){
                        $pkinfo['pk_gift_liveuid']=(string)$pk_gift_liveuid;
                    }
                    $pk_gift_pkuid=DI()->redis  -> hGet('LivePK_gift',$pkuid);
                    if($pk_gift_pkuid){
                        $pkinfo['pk_gift_pkuid']=(string)$pk_gift_pkuid;
                    }
                    
                }else{
                    $pkinfo['ifpk']='0';
                }
            }

        }
		//file_put_contents('./LiveConnect.txt',date('Y-m-d H:i:s').' 提交参数信息 pkinfo:'.json_encode($pkinfo)."\r\n",FILE_APPEND);
		$configpri=getConfigPri();

        
	    $info=array(
			'votestotal'=>$userlists['votestotal'],
			'barrage_fee'=>$configpri['barrage_fee'],
			'userlist_time'=>$configpri['userlist_time'],
			'chatserver'=>$configpri['chatserver'],
			'linkmic_uid'=>$linkmic_uid,
			'linkmic_pull'=>$linkmic_pull,
			'nums'=>$userlists['nums'],
			'speak_limit'=>$configpri['speak_limit'],
			'barrage_limit'=>$configpri['barrage_limit'],
			'coin'=>$userinfo['coin'],
			'vip'=>$userinfo['vip'],
			'liang'=>$userinfo['liang'],
			'issuper'=>(string)$issuper,
			'usertype'=>(string)$usertype,
		);
		$info['isattention']=(string)isAttention($uid,$liveuid);
		$info['userlists']=$userlists['userlist'];
        
        /* 守护 */
        $info['guard']=$guard_info;
        $info['guard_nums']=$guard_nums;
        
        /* 主播连麦/PK */
        $info['pkinfo']=$pkinfo;
        
        /* 红包 */
        $key='red_list_'.$stream;
        $nums=DI()->redis->lSize($key);
        $isred='0';
        if($nums>0){
            $isred='1';
        }
		$info['isred']=$isred;
        
        /* 奖池 */
        $info['jackpot_level']='-1';
		$jackpotset = getJackpotSet();
        if($jackpotset['switch']){
            $jackpotinfo = getJackpotInfo();
            $info['jackpot_level']=$jackpotinfo['level'];
        }
        
		$rs['info'][0]=$info;
		return $rs;
	}	

以上就是直播系统源码中关于直播间人数统计功能的大致开发流程,这对于平常的团队来说可能会存在一定的难度,但是如果是交给专业的团队,各方面实现和最终效果也会更好一些。
声明:本文由美狐原创,未经允许禁止转载,谢谢合作。

发布了119 篇原创文章 · 获赞 27 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/yun_bao_2144899870/article/details/103714360