李勇

1.修改课堂录制的逻辑

... ... @@ -58,7 +58,7 @@ export default class MessageEntrance extends Emiter {
constructor() {
super();
//sdk 信息
GlobalConfig.sdkVersion = "v1.81.1.20170824";
GlobalConfig.sdkVersion = "v1.81.19.20170828";
loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
//设置
... ... @@ -399,7 +399,7 @@ export default class MessageEntrance extends Emiter {
//当前的课堂状态信息发生改变,需要保存课堂状态到Sass
_onClassStatusInfoChange(_param) {
//如果MCU连接已经断开,不发送
if (GlobalConfig.getCurrentStatus().code != GlobalConfig.statusCode_2.code) {
if (!_mcu||!_mcu.connected) {
loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
return;
}
... ... @@ -424,14 +424,17 @@ export default class MessageEntrance extends Emiter {
this.classRecordStatusUpdateTimer = setTimeout(function () {
clearTimeout(this.classRecordStatusUpdateTimer);
_this.updaterRecordAllApeStatus(_param);
}, 2000);
}, 1600);
}
//录制状态发送改变,更新所有模块的当前数据发送到MCU
updaterRecordAllApeStatus(_param) {
if(GlobalConfig.isRecordPlayBack){
return;
}
//老师身份和非录制回放的时候执行,录制状态发送改变,需要更新当前的数据,否则已有的消息会录制不上
if (GlobalConfig.isHost && !GlobalConfig.isRecordPlayBack) {
if (GlobalConfig.isHost||GlobalConfig.rosterNumber<=1) {
loger.warn('录制状态发送改变->更新所有模块的当前数据发送到MCU');
//目前录制的模块[文档模块、白板模块、视频模块(包含屏幕共享)、音频模块、媒体共享,聊天模块]
if (_doc_ape) {
... ... @@ -959,7 +962,7 @@ export default class MessageEntrance extends Emiter {
isForce = true;
}
if (GlobalConfig.isHost || isForce) {
/* if (GlobalConfig.isHost || isForce) {
//只有加入课堂之后才能保存数据
if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
//POST 保存数据
... ... @@ -969,7 +972,26 @@ export default class MessageEntrance extends Emiter {
}
} else {
loger.log("没有保存课堂状态信息的权限->身份", GlobalConfig.userRole);
}*/
if (GlobalConfig.isHost || isForce||GlobalConfig.rosterNumber<=1) {
//只有加入课堂之后才能保存数据
/*if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
//POST 保存数据
_sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo}); //保存课堂状态信息
} else {
loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());
}*/
if (_mcu&&_mcu.connected) {
//POST 保存数据
_sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo}); //保存课堂状态信息
} else {
loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());
}
} else {
loger.log("没有保存课堂状态信息的权限->身份", GlobalConfig.userRole);
}
}
//保存会态信息成功
... ... @@ -1355,10 +1377,15 @@ export default class MessageEntrance extends Emiter {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(GlobalConfig.isRecordPlayBack){
return;
}
if (_confer_ape) {
//开始录制
_confer_ape.startRecord();
setTimeout(()=> {
_confer_ape.startRecord();
},2000);
//开始上课
_confer_ape.startClass(_param);
}
... ...
... ... @@ -72,6 +72,7 @@ class RecordPlayBackParse extends Emiter {
let pduMsg = pdu.decode_pdu(data);
let pduType = pduMsg.get("type");
let pduData = pduMsg.get("data");
//*************非常重要******************
//客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端,
//所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的
... ... @@ -121,10 +122,11 @@ class RecordPlayBackParse extends Emiter {
//解析和储存,录制回放EverSocket底层消息处理 data-数据;timestamp-数据对应的时间戳
_parseSaveSocketMsgReceivedHandler(data, timestamp) {
//loger.log('解析和储存录制回放数据-> ');
let pduMsg = pdu.decode_pdu(data);
let pduType = pduMsg.get("type");
let pduData = pduMsg.get("data");
//*************非常重要******************
//客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端,
//所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的
... ... @@ -328,10 +330,17 @@ class RecordPlayBackParse extends Emiter {
}
GlobalConfig.recordPlaybackMaxTime = this._recordPlaybackMaxTime;
console.log('课堂模块',this._conferApeMssages);
console.log('音视频通话模块数据',this.mediaChannleList);
console.log('媒体共享模块数据',this._mediaShareApeMssages);
console.log('媒体共享模块数据',this._mediaShareApeMssages);
console.log('伴音模块数据',this._musicShareApeMssages);
loger.log("录制回放数据解析完成,录制回放的总时间长为->", this._recordPlaybackMaxTime);
console.log('视频数据',this._videoApeMssages);
console.log('音频数据',this._audioApeMssages);
console.log('文档数据',this._docApeMssages);
console.log('白板数据',this._whiteApeMssages);
console.log('聊天数据',this._chatApeMssages);
loger.log("录制回放数据解析完成,录制回放的总时间长为->", this._recordPlaybackMaxTime,"recordTimestamp:"+GlobalConfig.recordTimestamp);
this._emit(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, {"recordPlaybackMaxTime": this._recordPlaybackMaxTime});
}
... ... @@ -342,7 +351,7 @@ class RecordPlayBackParse extends Emiter {
//没有数据,需要查找当前时间点属于哪一个时间戳关键帧
} else {
//把时间点对应的数据发送,同一秒内有存在多个数据的情况
loger.log(_ape,"回放数据->",msgDataArr.length)
loger.log(_ape,"回放数据->length:",msgDataArr.length)
for (let i = 0; i < msgDataArr.length; i++) {
this._everSocketMsgReceivedHandler(msgDataArr[i].byteData, 0);
}
... ... @@ -470,11 +479,12 @@ class RecordPlayBackParse extends Emiter {
messageItem = channelInfos[i];
if (messageItem) {
keyFrameSeekTime = (this._recordPlaybackTimestamp - i);
loger.log("SEEK->查找音视频模块数据->",messageItem,'keyFrameSeekTime->',keyFrameSeekTime)
loger.log("频道:"+k+"->SEEK->查找音视频模块数据->",messageItem,'keyFrameSeekTime->',keyFrameSeekTime)
this._everSocketMsgReceivedHandler(messageItem.byteData, keyFrameSeekTime);
break;
}
}
loger.log("频道:"+k+"—>没有查找到数据")
}
}
}
... ... @@ -677,7 +687,11 @@ class RecordPlayBackParse extends Emiter {
if(!this.mediaChannleList[videoChannelInfo.channelId]){
this.mediaChannleList[videoChannelInfo.channelId]={};
}
this.mediaChannleList[videoChannelInfo.channelId][timestamp]={parseData:videoChannelInfo,byteData:data,timestamp: timestamp };
let statusStr="关";
if(videoChannelInfo&&videoChannelInfo.status==1){
statusStr="开";
}
this.mediaChannleList[videoChannelInfo.channelId][timestamp]={parseData:videoChannelInfo,byteData:data,timestamp: timestamp,status:statusStr};
} catch (err) {
loger.log("RCVideoChannelInfoPdu->unPackPdu->error->" + tableItem.itemIdx + " err:" + err.message);
}
... ... @@ -689,7 +703,11 @@ class RecordPlayBackParse extends Emiter {
if(!this.mediaChannleList[audioChannelInfo.channelId]){
this.mediaChannleList[audioChannelInfo.channelId]={};
}
this.mediaChannleList[audioChannelInfo.channelId][timestamp]={parseData:audioChannelInfo,byteData:data,timestamp: timestamp };
let statusStr="关";
if(audioChannelInfo&&audioChannelInfo.status==1){
statusStr="开";
}
this.mediaChannleList[audioChannelInfo.channelId][timestamp]={parseData:audioChannelInfo,byteData:data,timestamp: timestamp,status:statusStr};
} catch (err) {
loger.log("RCAudioChannelInfoPdu->unPackPdu->error->" + tableItem.itemIdx + " err:" + err.message);
}
... ...
... ... @@ -94,6 +94,7 @@ export default class Ape extends Emiter {
let regPdu = pdu['RCAdapterPdu'].decode(regBuffer);
let regItems = regPdu.item;
let regItemSize = regItems.length;
//console.log("RCAdapterPdu数据同步处理",regPdu);
//loger.log(this._session_name + '数据同步消息');
//loger.log(this._session_name + '数据同步消息.同步条数', regItemSize,"seekTime->",seekTime);
for (var i = 0; i < regItemSize; ++i) {
... ... @@ -332,10 +333,14 @@ export default class Ape extends Emiter {
//loger.log('Ape发送数据NORMAL PDU');
//console.log(appPdu);
//loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
/* if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
}*/
if(!this.mcu||!this.mcu.connected){
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
if(!this._classInfo){
loger.warn('Ape发送数据NORMAL PDU->失败->ape课堂数据无效->', this._classInfo);
return;
... ... @@ -391,7 +396,6 @@ export default class Ape extends Emiter {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return;
}
let uniformPdu = pdu.create_uniform_pdu(
appPdu.type,
this._classInfo.nodeId,
... ...
... ... @@ -470,7 +470,7 @@ class AudioApe extends Ape {
//更新媒体文件模块的录制信息,每次开启录制的时候需要把当前媒体文件的信息更新一次
updaterRecordApeStatus(_param) {
console.warn("录制状态发送改变->更新当前的状态->", this.mediaModule.mediaChannels);
loger.warn("录制状态发送改变->更新当前的状态->", this.mediaModule.mediaChannels);
for (let i in this.mediaModule.mediaChannels) {
let channelInfo = this.mediaModule.mediaChannels[i];
if (channelInfo) {
... ...
... ... @@ -271,10 +271,10 @@ class ConferApe extends Ape {
loger.warn('不能再录制,录制时间已经达到最大限制', GlobalConfig.recordTimestamp);
return;
}
loger.warn('检测是否需要开启录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
//如果是host或者当前课堂只有1个人
if (GlobalConfig.isHost||this.rosterLen<=1) {
if(GlobalConfig.recordStatus){
/* if(GlobalConfig.recordStatus){
loger.warn("课堂已经是录制状态不->不需要再开启,isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
}else{
loger.warn('开启录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
... ... @@ -282,8 +282,12 @@ class ConferApe extends Ape {
this.sendConferRecordMsg({"recordStatus": true});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this._emit(MessageTypes.CLASS_RECORD_START); //课堂开始录制
}
}*/
loger.warn('开启录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
this.sendConferRecordMsg({"recordStatus": true});
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
this._emit(MessageTypes.CLASS_RECORD_START); //课堂开始录制
}
}
... ... @@ -434,7 +438,8 @@ class ConferApe extends Ape {
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE, _param);
//this.sendUpdaterClassStatusInfo({"actionType": 2, isStopAllPublishMedia: true});
this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_PAUSE, isStopAllPublishMedia: false});
this.stopTimerCounter();
//this.stopTimerCounter();//新版的录制规则,尝试暂停不停止计时器
}
//关闭课堂
... ... @@ -605,6 +610,7 @@ class ConferApe extends Ape {
}
loger.log('课堂模块初始完成->当前课堂状态:'+ GlobalConfig.classStatus,"recordStatus:"+GlobalConfig.recordStatus);
this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1);
//2秒后执行开始上课和开始录制的判断逻辑
clearTimeout(this.startClassTimer);
this.startClassTimer=setTimeout(()=>{
... ... @@ -658,9 +664,36 @@ class ConferApe extends Ape {
this.stopTimerCounter();
return;
}
//课堂开始的状态下,课堂进行时间和录制时间都需要更加,录制时间会大于或等于课堂开始的累积时间
//更新课堂进行时间
if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
GlobalConfig.classTimestamp = GlobalConfig.classTimestamp + 1; //计时
//向应用层更新当前课堂进行的时间长度 (秒)
this._emit(MessageTypes.CLASS_UPDATE_TIMER, {"classTimestamp": GlobalConfig.classTimestamp});
//以一定的时间间隔同步课堂内所有人的累积上课时间
if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
//如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
if (GlobalConfig.isHost||this.rosterLen<=1) {
//保存数据到Sass
this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
//同步消息给其他人
this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_STARTED, isStopAllPublishMedia: false});
}
}
//进行MS动态选点,选择最快的MS服务器地址(录制回放不做处理)
if (!GlobalConfig.isRecordPlayBack && GlobalConfig.classTimestamp % GlobalConfig.msDynamicChooseIpDelay == 0) {
//MS推流选点
this._emit(MessageTypes.SWITCH_MS_IP);
//MS拉流选点
this._emit(MessageTypes.SWITCH_RTMP_PULL_IP);
//HLS拉流选点
this._emit(MessageTypes.SWITCH_HLS_IP);
}
}
//更新录制进行时间
/* if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
GlobalConfig.classTimestamp = GlobalConfig.classTimestamp + 1; //计时
//老师身份的时候要记录录制的时间
if (GlobalConfig.isHost||this.rosterLen<=1) {
GlobalConfig.recordTimestamp = GlobalConfig.recordTimestamp + 1;
... ... @@ -700,7 +733,7 @@ class ConferApe extends Ape {
this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_STARTED, isStopAllPublishMedia: false});
}
}
}
}*/
/* //如果还没开始或已经暂停、关闭,不做计时处理
if (GlobalConfig.classStatus != ApeConsts.CLASS_STATUS_STARTED) {
... ... @@ -939,11 +972,11 @@ class ConferApe extends Ape {
// 1.当前课堂只有自己;2.自己的身份不是host;3当前的课堂状态为(CLASS_STATUS_STARTED= 1;//直播中)
this.rosterLen = Object.keys(this.rosters).length;
GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数
if (this.rosterLen <=1 && !GlobalConfig.isHost && GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
/* if (this.rosterLen <=1 && !GlobalConfig.isHost && GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
loger.warn("当前课堂没有老师->暂停课堂");
this.pauseClass({isForce: true});
//this.stopRecord(true);
}
}*/
//处理用户信息
this.unPackRosterInfo(nodeId, nodeData);
return;
... ... @@ -963,7 +996,7 @@ class ConferApe extends Ape {
deviceType: nodeData.deviceType
}
if (nodeData.role == ApeConsts.NR_HOST && GlobalConfig.isHost) {
loger.warn("相同身份的人进入->自己被踢出->进入的人员信息", nodeData);
loger.warn("相同身份的人进入->自己被踢出->进入的人员信息","userName:"+ nodeData.name,"userId:"+ nodeData.userId,"userRole:"+ nodeData.userRole,"nodeId:"+ nodeData.nodeId,"deviceType:"+ nodeData.deviceType);
this.kickOutRoster(newUserInfo);
return;
} else if (nodeData.userId == GlobalConfig.userId && GlobalConfig.userId != "0") {
... ...
... ... @@ -599,7 +599,7 @@ class VideoApe extends Ape {
//更新媒体文件模块的录制信息,每次开启录制的时候需要把当前媒体文件的信息更新一次
updaterRecordApeStatus(_param) {
console.warn("录制状态发送改变->更新当前的状态->", this.mediaModule.mediaChannels);
loger.warn("录制状态发送改变->更新当前的状态->", this.mediaModule.mediaChannels);
for (let i in this.mediaModule.mediaChannels) {
let channelInfo = this.mediaModule.mediaChannels[i];
if (channelInfo) {
... ... @@ -608,6 +608,10 @@ class VideoApe extends Ape {
} else {
channelInfo.owner = channelInfo.fromNodeId;
}
//owner为0就是没有使用
if(channelInfo.owner==0){
channelInfo.status == ApeConsts.CHANNEL_STATUS_RELEASED
}
this.sendTableUpdateHandler(channelInfo);
}
}
... ...