李勇

1.修复nodeId比较大小踢人的逻辑,改为加入课堂时间戳来比较;2,修复音视频禁用状态同步的问题;3.修复视频界面名字显示不出的问题

... ... @@ -63,7 +63,7 @@ export default class MessageEntrance extends Emiter {
super();
this.lastClassActiveTime=0;//最后一次课堂激活的时间戳
//sdk 信息
GlobalConfig.sdkVersion = "v2.34.5.20171127";
GlobalConfig.sdkVersion = "v2.34.16.20171128";
loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
console.log("sdkVersion:" + GlobalConfig.sdkVersion);
//设置
... ... @@ -101,9 +101,9 @@ export default class MessageEntrance extends Emiter {
_webRtc.on('*', (type, data) => this._emit(type, data));
_webRtc.on(MessageTypes.USER_DEVICE_STATUS_CHAANGE, this.userDeviecStatusChange.bind(this)); //监听摄像头和麦克风的开启状态
_webRtc.on(MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE, this.mediaPublishStatusChange.bind(this)); //webRtc推流状态发生改变
_webRtc.on(WebRtcApe.RE_JOIN_CHANNEL, this._webRtcRejoinChannel.bind(this)); //重先加入音视频频道
_webRtc.on(MessageTypes.MEDIA_ENABLED_CHANGE, this._mediaEnabledChange.bind(this)); //音视频禁用状态改变 广播消息
_webRtc.on(MessageTypes.UPDATE_USER_MEDIA_MUTED_STATUS, this._updateUserMediaMutedStatus.bind(this)); //音视频禁用状态改变(自己),同步更新
_webRtc.on(WebRtcApe.RE_JOIN_CHANNEL, this._webRtcRejoinChannel.bind(this)); //重先加入音视频频道
_webRtc.on(WebRtcApe.UPDATE_USER_MEDIA_MUTED_STATUS, this._updateUserMediaMutedStatus.bind(this)); //音视频禁用状态改变(自己),同步更新
// Sass平台层
_sass = Sass;
... ... @@ -647,23 +647,23 @@ export default class MessageEntrance extends Emiter {
//如果没有名字的时候需要随机生成
let randUserId =parseInt(Math.random()*1000)+"_"+parseInt(Math.random()*1000)+"_"+parseInt(Math.random()*1000);
let randUserId =EngineUtils.creatRandomNum(3,".");//parseInt(Math.random()*1000)+"_"+parseInt(Math.random()*1000)+"_"+parseInt(Math.random()*1000);
let randUserName=EngineUtils.creatRandomNum(2,".");
if (GlobalConfig.userRole == ApeConsts.host) {
randUserId = "T" + randUserId;
randUserName= "T" + randUserName;
randUserId = "1_" + randUserId;
randUserName= "1_" + randUserName;
} else if (GlobalConfig.userRole == ApeConsts.assistant) {
randUserId = "A" + randUserId;
randUserName= "A" + randUserName;
randUserId = "2_" + randUserId;
randUserName= "2_" + randUserName;
} else if (GlobalConfig.userRole == ApeConsts.presenter) {
randUserId = "P" + randUserId;
randUserName= "O" + randUserName;
randUserId = "2_" + randUserId;
randUserName= "2_" + randUserName;
} else if (GlobalConfig.userRole == ApeConsts.invisible) {
randUserId = "I" + randUserId;
randUserName= "I" + randUserName;
randUserId = "32_" + randUserId;
randUserName= "32_" + randUserName;
} else {
randUserId = "S" + randUserId;
randUserName= "S" + randUserName;
randUserId = "8_" + randUserId;
randUserName= "8_" + randUserName;
}
//如果没有名字,随机起一个名字
... ... @@ -1240,6 +1240,8 @@ export default class MessageEntrance extends Emiter {
joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;
joinClassSuccessCallBackData.password = GlobalConfig.password;
joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired; // 老师的默认是true
joinClassSuccessCallBackData.joinTimestamp = GlobalConfig.joinTimestamp;
//GlobalConfig.passwordRequired 老师的默认是true
//GlobalConfig.portal=_data.portal;
joinClassSuccessCallBackData.role = GlobalConfig.role;
... ...
... ... @@ -36,7 +36,11 @@ class EngineUtils {
static creatRandomNum(_part = 3, splitStr = "") {
let randNumStr = "";
for (let i = 0; i < _part; i++) {
randNumStr += splitStr + parseInt(Math.random() * 1000);
if(i==0){
randNumStr += ""+parseInt(Math.random() * 1000);
}else{
randNumStr +=splitStr+parseInt(Math.random() * 1000);
}
}
return randNumStr;
}
... ...
... ... @@ -177,6 +177,30 @@ class GlobalConfig {
}
/*
* 根据nodeId获取用户的身份
* */
static getUserRoleToString(userRole) {
let userRoleName="学生";
switch (userRole){
case ApeConsts.NR_HOST:
userRoleName="老师";
break;
case ApeConsts.NR_PRESENTER:
userRoleName="助教";
break;
case ApeConsts.NR_INVISIBLE:
userRoleName="监客";
break;
case ApeConsts.NR_NORMAL:
userRoleName="学生";
break;
default :
break;
}
return userRoleName;
}
/*
* 根据nodeId获取用户的信息
* */
static getUserInfoFromeNodeId(_nodeId) {
... ... @@ -585,6 +609,7 @@ GlobalConfig.videoRecords = [];
GlobalConfig.status = 0
GlobalConfig.mobileDirection = 0;
GlobalConfig.joinTimestamp = 0; //加入课堂的时间戳
GlobalConfig.nodeId = 0; //随机生成 mcu中的唯一ID
GlobalConfig.passwordRequired = false;
GlobalConfig.password = "";
... ...
... ... @@ -101,6 +101,7 @@ class ConferApe extends Ape {
getNodeInfo() {
let nodeInfoRecordPdu = new pdu['RCNodeInfoRecordPdu'];
nodeInfoRecordPdu.nodeId = GlobalConfig.nodeId;
nodeInfoRecordPdu.joinTimestamp= GlobalConfig.joinTimestamp||EngineUtils.creatSoleNumberFromTimestamp();
nodeInfoRecordPdu.selfSilence = JSON.stringify(GlobalConfig.selfSilence) || "";
nodeInfoRecordPdu.name = GlobalConfig.userName;
nodeInfoRecordPdu.role = ApeConsts.userTypesToId[GlobalConfig.userRole] || 1; //NR_NORMAL用户的身份,根据用户登录时的身份设置;
... ... @@ -1001,7 +1002,7 @@ class ConferApe extends Ape {
//新加入的人员不是自己
//1.判断进入的用户身份,如果进入的人身份是host,助教,监课,并且和自己的身份冲突,自己会被踢掉
//2.最后进入的人会踢掉之前进入的人,nodeId是按时间戳生成的,最后进入的人nodeId的值比之前进入的人大
if (parseInt(nodeId) > GlobalConfig.nodeId) {
if (parseInt(nodeData.joinTimestamp) > GlobalConfig.joinTimestamp) {
let newUserInfo = {
userId: nodeData.userId,
userName: nodeData.name,
... ... @@ -1010,11 +1011,11 @@ class ConferApe extends Ape {
deviceType: nodeData.deviceType
}
if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) {
loger.warn("相同身份的人进入->自己被踢出->进入的人员信息", "userName:" + nodeData.name, "userId:" + nodeData.userId, "userRole:" + nodeData.userRole, "nodeId:" + nodeData.nodeId, "deviceType:" + nodeData.deviceType);
loger.warn("相同身份的人进入->自己被踢出->进入的人员信息", "userName:" + nodeData.name, "userId:" + nodeData.userId, "userRole:" + nodeData.userRole, "nodeId:" + nodeData.nodeId, "deviceType:" + nodeData.deviceType,"joinTimestamp:"+nodeData.joinTimestamp);
this.kickOutRoster(newUserInfo);
return;
} else if (nodeData.userId == GlobalConfig.userId && GlobalConfig.userId != "0") {
loger.warn("异地登陆->userId->", GlobalConfig.userId);
loger.warn("异地登陆->自己被踢出->进入的人员信息", "userName:" + nodeData.name, "userId:" + nodeData.userId, "userRole:" + nodeData.userRole, "nodeId:" + nodeData.nodeId, "deviceType:" + nodeData.deviceType,"joinTimestamp:"+nodeData.joinTimestamp);
this._emit(MessageTypes.MCU_ERROR, {type: MessageTypes.ERR_CLASS_REMOTE_LANDING, data: newUserInfo});
this._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 1});
}
... ...
... ... @@ -751,6 +751,8 @@ class VideoApe extends Ape {
} else {
GlobalConfig.openCamera = 0;
GlobalConfig.openMicrophones = 0;
GlobalConfig.videoEnabled=true;
GlobalConfig.audioEnabled=true;
}
//更新用户的摄像头和麦克风状态
... ...
... ... @@ -36,7 +36,6 @@ class WebRtcApe extends Emiter {
this.channelId = "";
this.uid = 0;
this.info = ""
this.videAndAudioMutedStatusData={};//记录当前自己的摄像头和麦克风禁用状态
this.reAddRemoteStreamDelay = 0;//重连远程视频的计时器
this.rePublishDelay = 0;//重新推流的间隔
... ... @@ -203,7 +202,14 @@ class WebRtcApe extends Emiter {
});
this.client.on("active-speaker", (evt)=> {
let uid = evt.uid;
loger.log("当前正在讲话的uid:" + uid);
let user=GlobalConfig.getUserInfoFromeNodeId(parseInt(uid));
//console.log("active-speaker",user);
if(user){
let roleRole=GlobalConfig.getUserRoleToString(user.role);
loger.log("当前正在讲话的 ["+roleRole+"] name:"+user.name+" uid:" + uid);
}else{
loger.log("当前正在讲话的uid:" + uid);
}
});
}
... ... @@ -237,25 +243,24 @@ class WebRtcApe extends Emiter {
if(user&&user.audioEnabled==true){
audioMutedDiv = `<div class="audioAndVideMuted microphoneOn " id=${this.audioMutedIdName + uid} title="${this.closeMicrophoneTitle}"></div>`;
}else{
audioMutedDiv = `<div class="audioAndVideMuted microphoneff " id=${this.audioMutedIdName + uid} title="${this.closeMicrophoneTitle}"></div>`;
audioMutedDiv = `<div class="audioAndVideMuted microphoneOff " id=${this.audioMutedIdName + uid} title="${this.closeMicrophoneTitle}"></div>`;
}
videoAndAudioBox=`<div class="audioAndVideBox unOpenVideo">${videoMutedDiv+audioMutedDiv}</div>`;
}
if (userRole == ApeConsts.invisible) {
let nameDiv = `<div style=${this.invisibleVideoWidth}px;height:22px; position: absolute;bottom: 2px; right:4px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; vertical-align: middle;background-color: #2926251a;color: #e7e7e7display:${this.nameDisplay}">${userName}</div>`;
let nameDiv = `<div style="${this.invisibleVideoWidth}px;height:22px; position: absolute;bottom: 2px; right:4px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; vertical-align: middle;color: #e7e7e7display:${this.nameDisplay}">${userName}</div>`;
//把远程视频添加到监课列表
loger.log("获取远程视频流成功->监课:" + userName + "->" + uid, new Date().getTime());
let viewDiv = `<div id="${this.xdyRemote + uid}" class="${this.invisibleWebRtcVideoClass}" style="width:${this.invisibleVideoWidth * this.videoScale}px;height:${this.invisibleVideoHeight * this.videoScale}px;float: left;margin-right: 1px;">${nameDiv + videoAndAudioBox}</div>`;
$(this.invisibleViewId).append(viewDiv);
} else if (userRole == ApeConsts.host || userRole == ApeConsts.assistant || userRole == ApeConsts.presenter) {
let nameDiv = `<div style="width:${this.hostRemoteVideoWidth}px;height:22px; position: absolute;bottom: 2px;right:4px z-index: 1;overflow:hidden;font-size: 14px;text-align: right;vertical-align: middle; background-color: #2926251a;color: #e7e7e7;display:${this.nameDisplay}">${userName }</div>`;
let nameDiv = `<div style="width:${this.hostRemoteVideoWidth}px;height:22px; position: absolute;bottom: 2px;right:4px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right;vertical-align: middle;color: #e7e7e7;display:${this.nameDisplay}">${userName }</div>`;
//把远程视图添加到老师列表
loger.log("获取远程视频流成功->userRole:" + userRole + ":" + userName + "->" + uid, new Date().getTime());
let viewDiv = `<div id="${this.xdyRemote + uid}" class="${this.hostWebRtcVideoClass}" style="width:${this.hostRemoteVideoWidth * this.videoScale}px;height:${this.hostRemoteVideoHeight * this.videoScale}px;float: left;margin-right: 1px;">${nameDiv + videoAndAudioBox}</div>`;
$(this.hostRemoteViewId).prepend(viewDiv);
} else {
let nameDiv = `<div style="width:${this.normalRemoteVideoWidth}px;height:22px; position: absolute;bottom: 2px;right:4px z-index: 1;overflow:hidden;font-size: 14px;text-align: right;vertical-align: middle;background-color: #2926251a;color: #e7e7e7;display:${this.nameDisplay}">${userName}</div>`;
let nameDiv = `<div style="width:${this.normalRemoteVideoWidth}px;height:22px; position: absolute;bottom: 2px;right:4px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right;vertical-align: middle;color: #e7e7e7;display:${this.nameDisplay}">${userName}</div>`;
//把视图添加到学生列表
loger.log("获取远程视频流成功->学生:" + userName + "->" + uid, new Date().getTime());
let viewDiv = `<div id="${this.xdyRemote + uid}" class="${this.normalWebRtcVideoClass}" style="width:${this.normalRemoteVideoWidth * this.videoScale}px;height:${this.normalRemoteVideoHeight * this.videoScale}px;float: left;margin-right: 1px;">${nameDiv + videoAndAudioBox}</div>`;
... ... @@ -279,6 +284,7 @@ class WebRtcApe extends Emiter {
$("#" + this.xdyRemote + uid).remove();
}
}
$("#player_" + uid).css("pointer-events","none");
if (user && (user.deviceType == GlobalConfig.deviceIOS || user.deviceType == GlobalConfig.deviceAndroid)) {
this.remoteVideoList[user.nodeId] = stream;
}
... ... @@ -593,7 +599,7 @@ class WebRtcApe extends Emiter {
videoAndAudioBox=`<div class="audioAndVideBox openVideo">${videoMutedDiv+audioMutedDiv}</div>`;
}
let nameDiv = `<div id="${"videoOwnerName_" + this.uid}" class="localVideoOwnerName" style="width:${this.localVideoWidth}px;height:26px; position: absolute;bottom: 2px;right:4px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; vertical-align:bottom;color: #e7e7e7;display:${this.nameDisplay}">${videoAndAudioBox+userName}</div>`;
let nameDiv = `<div id="${"videoOwnerName_" + this.uid}" class="localVideoOwnerName" style="width:${this.localVideoWidth}px;height:26px; position: absolute;bottom: 2px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; vertical-align:bottom;color: #e7e7e7;display:${this.nameDisplay}">${userName+videoAndAudioBox}</div>`;
$(this.localViewId).prepend(nameDiv);
$("#" + this.videoMutedIdName + this.uid).off("click", this._clickVideoMuted.bind(this));
... ... @@ -864,7 +870,6 @@ class WebRtcApe extends Emiter {
* */
_clickVideoMuted(evt) {
let className = evt.currentTarget.className;
loger.log("点击禁用和开启视频", evt.currentTarget.id);
let idArr = (evt.currentTarget.id).split("_");
let uid = 10000000;//默认设置一个不存在的uid
if (idArr && idArr.length > 1) {
... ... @@ -873,21 +878,9 @@ class WebRtcApe extends Emiter {
if (className.indexOf("cameraOn") > 0) {
loger.log("点击禁用视频->" + uid);
this.sendChangeUserMediaEnabled({nodeId: uid, video: false, audio: true});
/*if (uid != GlobalConfig.nodeId) {
this.sendChangeUserMediaEnabled({nodeId: uid, video: false, audio: true});
this.setUidVideoEnabledStatus(uid,false);
} else {
this.disableVideo(uid);
}*/
} else {
loger.log("点击开启视频");
loger.log("点击解除视频禁用->"+uid);
this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: true});
/* if (uid != GlobalConfig.nodeId) {
this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: true});
this.setUidVideoEnabledStatus(uid,true);
} else {
this.enableVideo(uid);
}*/
}
}
/*
... ... @@ -895,7 +888,6 @@ class WebRtcApe extends Emiter {
* */
_clickAudioMuted(evt) {
let className = evt.currentTarget.className;
loger.log("点击禁音和开启按钮切换", evt.currentTarget.id);
let idArr = (evt.currentTarget.id).split("_");
let uid = 10000000;//默认设置一个不存在的uid
if (idArr && idArr.length > 1) {
... ... @@ -904,21 +896,9 @@ class WebRtcApe extends Emiter {
if (className.indexOf("microphoneOn") > 0) {
loger.log("点击禁音->" + uid);
this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: false});
/*if (uid != GlobalConfig.nodeId) {
this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: false});
this.setUidAudioEnabledStatus(uid,false);
} else {
this.disableAudio(uid);
}*/
} else {
loger.log("点击开启声");
loger.log("点击解除禁音");
this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: true});
/*if (uid != GlobalConfig.nodeId) {
this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: true});
this.setUidAudioEnabledStatus(uid,true);
} else {
this.enableAudio(uid);
}*/
}
}
... ... @@ -938,7 +918,7 @@ class WebRtcApe extends Emiter {
if (!_data) {
return;
}
this.videAndAudioMutedStatusData=_data;
if (_data.nodeId != GlobalConfig.nodeId) {
//不是自己的只设置状态显示即可
//音频
... ... @@ -975,8 +955,9 @@ class WebRtcApe extends Emiter {
this.enableVideo(_data.nodeId);
}
//更新同步用户的媒体禁用状态
if(this.videAndAudioMutedStatusData){
this._emit(WebRtcApe.UPDATE_USER_MEDIA_MUTED_STATUS,this.videAndAudioMutedStatusData);
loger.log("更新同步用户的媒体禁用状态",_data);
if(_data){
this._emit(WebRtcApe.UPDATE_USER_MEDIA_MUTED_STATUS,_data);
}
}
}
... ...
... ... @@ -438,10 +438,10 @@ class WhiteBoardApe extends Ape {
case TYPE_RECT:
break;
case TYPE_CIRCLE:
whiteBoardModelPdu.radius = parseInt(_param.radius);
whiteBoardModelPdu.radius = parseInt(parseFloat(_param.radius)*100);//外部传入的值有可能是小数,放大100倍,收到数据后再转换
break;
case TYPE_TEXT:
whiteBoardModelPdu.fontSize = parseInt(_param.fontSize);
whiteBoardModelPdu.fontSize = parseInt(parseFloat(_param.fontSize)*100);//外部传入的值有可能是小数,放大100倍,收到数据后再转换
whiteBoardModelPdu.fontName = _param.fontName || null;
whiteBoardModelPdu.text = _param.text || null;
break;
... ... @@ -475,6 +475,9 @@ class WhiteBoardApe extends Ape {
//let _pointGroup = EngineUtils.arrayFromJsonString(whiteBoardModelPdu.pointGroup);
let pointGroup=EngineUtils.unPackOptimizePoint(whiteBoardModelPdu.pointGroup);//还原压缩后的数据
whiteBoardModelPdu.pointGroup = pointGroup;
whiteBoardModelPdu.radius =whiteBoardModelPdu.radius*0.01;//发送的时候放大100倍,接收的时候需要除100;
whiteBoardModelPdu.fontSize=whiteBoardModelPdu.fontSize*0.01;//发送的时候放大100倍,接收的时候需要除100;
this.annoInfos[itemIdx] = whiteBoardModelPdu;
return whiteBoardModelPdu;
} catch (err) {
... ...
... ... @@ -232,6 +232,7 @@ class MCU extends Emiter {
randNodeId=parseInt(randNodeId);
this.classInfo.nodeId =randNodeId; //EngineUtils.creatSoleNumberFromTimestamp();
GlobalConfig.joinTimestamp=EngineUtils.creatSoleNumberFromTimestamp();
GlobalConfig.nodeId = this.classInfo.nodeId; //这是标识自己身份的id
console.log("创建nodeId",GlobalConfig.nodeId);
... ... @@ -240,6 +241,7 @@ class MCU extends Emiter {
nodeInfoRecordPdu.nodeId = this.classInfo.nodeId;
nodeInfoRecordPdu.userId = this.classInfo.userId;
nodeInfoRecordPdu.role = ApeConsts.userTypesToId[this.classInfo.userRole] || 1; //NR_NORMAL用户的身份,根据用户登录时的身份设置
nodeInfoRecordPdu.joinTimestamp= GlobalConfig.joinTimestamp||EngineUtils.creatSoleNumberFromTimestamp();
nodeInfoRecordPdu.level = 0;
nodeInfoRecordPdu.handUpTime = 0;
nodeInfoRecordPdu.selfDisEnableDrawTime = 1;
... ...
... ... @@ -938,6 +938,7 @@ message RCNodeInfoRecordPdu {
optional uint32 selfDisEnableDrawTime = 39;
optional bool videoEnabled=40;
optional bool audioEnabled=41;
optional uint32 joinTimestamp=42;
}
message RCVotingPollSettingsPdu {
... ...