... ... @@ -62,19 +62,19 @@ export default class MessageEntrance extends Emiter {
constructor() {
super();
//sdk 信息
GlobalConfig.sdkVersion = "v2.21.3.20171024";
GlobalConfig.sdkVersion = "v2.22.7.20171026";
loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
console.log("sdkVersion:" + GlobalConfig.sdkVersion);
//设置
let locationProtocol= location.protocol;
if(locationProtocol=="https:"){
GlobalConfig.isHttps=true;
GlobalConfig.locationProtocol="https://";
GlobalConfig.websocketProtocol="wss://";
}else {
GlobalConfig.isHttps=false;
GlobalConfig.locationProtocol="http://";
GlobalConfig.websocketProtocol="ws://";
let locationProtocol = location.protocol;
if (locationProtocol == "https:") {
GlobalConfig.isHttps = true;
GlobalConfig.locationProtocol = "https://";
GlobalConfig.websocketProtocol = "wss://";
} else {
GlobalConfig.isHttps = false;
GlobalConfig.locationProtocol = "http://";
GlobalConfig.websocketProtocol = "ws://";
}
loger.warn("protocol:" + GlobalConfig.locationProtocol);
//获取设备和系统信息
... ... @@ -91,12 +91,12 @@ export default class MessageEntrance extends Emiter {
this.isGetFastestRtmpPullCallback = false; //是否RTMP拉流地址测试结束
this.isGetFastestHlsPullCallback = false; //是否HLS拉流地址测试结束
this.isGetFastestRsCallback = false; //是否录制回放HLS拉流地址测试结束
this.saveClassStatusTimer=0;//保存课堂数据的计时器间隔,防止同一瞬间多次提交
this.joinChannelTimer=0;//加入音视频通道的间隔
this.saveClassStatusTimer = 0;//保存课堂数据的计时器间隔,防止同一瞬间多次提交
this.joinChannelTimer = 0;//加入音视频通道的间隔
//全局的Error处理
this.on(MessageTypes.MCU_ERROR, this._mcuErrorHandler.bind(this));
_webRtc=WebRtcApe;
_webRtc = WebRtcApe;
_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推流状态发生改变
... ... @@ -107,7 +107,7 @@ export default class MessageEntrance extends Emiter {
_sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this)); //通过SASS平台验证(密码和MD5)
_sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this)); //获取课堂初始化信息
//_sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取课堂的基本信息
_sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this)); //获取课堂的最全信息和历史保存的数据
_sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this)); //SAAS获取课堂的最全信息和历史保存的数据
_sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this)); //保存课堂状态信息
_sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this)); //保存课堂录制信息
... ... @@ -117,7 +117,7 @@ export default class MessageEntrance extends Emiter {
//选点模块
_ipManager = new IpManager();
_base64=new Base64Module();
_base64 = new Base64Module();
// 底层MCU消息层
_mcu = Mcu;
... ... @@ -148,7 +148,7 @@ export default class MessageEntrance extends Emiter {
//_confer_ape.on(MessageTypes.SWITCH_RTMP_PULL_IP, this._switchRtmpPullIpHandler.bind(this)); //MS 拉流地址动态选点
//_confer_ape.on(MessageTypes.SWITCH_HLS_IP, this._switchHlsIpHandler.bind(this)); //MS HLS动态选点
_confer_ape.on(MessageTypes.STOP_ALL_MEDIA_PUBLISH, this._stopAllMediaPublishHandler.bind(this)); //课堂状态发生改变,需要停止当前的所有推流
_confer_ape.on(MessageTypes.CLASS_UPDATE_ROSTER,this._onRosterUpdateHandler.bind(this));
_confer_ape.on(MessageTypes.CLASS_UPDATE_ROSTER, this._onRosterUpdateHandler.bind(this));
_chat_ape = new ChatApe();
_chat_ape.on('*', (type, data) => this._emit(type, data));
... ... @@ -222,6 +222,10 @@ export default class MessageEntrance extends Emiter {
this.publishScreenShare = this._publishScreenShare.bind(this);
this.stopPublishScreenShare = this._stopPublishScreenShare.bind(this);
//推送外部流
this.publishExternalLink = this._publishExternalLink.bind(this);
this.stopPublishExternalLink = this._stopPublishExternalLink.bind(this);
//videoApe
this.getVideoPublishPath = this._getVideoPublishPath.bind(this);
this.getVideoAllChannelInfo = this._getVideoAllChannelInfo.bind(this);
... ... @@ -261,7 +265,7 @@ export default class MessageEntrance extends Emiter {
//获取文档图片的完整路径
this.getDocPDFFullPath = this._getDocPDFFullPath.bind(this); //获取文档的完整路径
this.getDocFullAddress = this._getDocFullAddress.bind(this); //获取文档资源地址
this.hideCurrentDocument=this._hideCurrentDocument.bind(this);//隐藏当前显示的文档
this.hideCurrentDocument = this._hideCurrentDocument.bind(this);//隐藏当前显示的文档
this.switchToWhiteboard = this._switchToWhiteboard.bind(this); //切换到白板文档
//媒体共享模块
this.mediaSharedUpload = this._sendMediaSharedUpload.bind(this); //上传
... ... @@ -287,19 +291,19 @@ export default class MessageEntrance extends Emiter {
this.stopQuestion = this._stopQuestion.bind(this);
//webrtc
this.publishMedia=this._publishMedia.bind(this);
this.unpublishMedia=this._unpublishMedia.bind(this);
this.changeDevices=this._changeDevices.bind(this);
this.setConfigPublisher=this._setConfigPublisher.bind(this);
this.setLocalMediaView=this._setLocalMediaView.bind(this);//设置自己的视图
this.setHostRemoteMediaView=this._setHostRemoteMediaView.bind(this);//设置远程老师的视图
this.setNormalRemoteMediaView=this._setNormalRemoteMediaView.bind(this);//设置远程学生的视图
this.setInvisibleMediaView=this._setInvisibleMediaView.bind(this);//设置监课身份的视图
this.publishMedia = this._publishMedia.bind(this);
this.unpublishMedia = this._unpublishMedia.bind(this);
this.changeDevices = this._changeDevices.bind(this);
this.setConfigPublisher = this._setConfigPublisher.bind(this);
this.setLocalMediaView = this._setLocalMediaView.bind(this);//设置自己的视图
this.setHostRemoteMediaView = this._setHostRemoteMediaView.bind(this);//设置远程老师的视图
this.setNormalRemoteMediaView = this._setNormalRemoteMediaView.bind(this);//设置远程学生的视图
this.setInvisibleMediaView = this._setInvisibleMediaView.bind(this);//设置监课身份的视图
this.setAppConfig=this._setAppConfig.bind(this);
this.recordControl=this._mediaRecordControl.bind(this);
this.setAppConfig = this._setAppConfig.bind(this);
this.recordControl = this._mediaRecordControl.bind(this);
this.changeRtcVideoConfig=this._changeRtcVideoConfig.bind(this);//设置webRtc视频视图的缩放
this.changeRtcVideoConfig = this._changeRtcVideoConfig.bind(this);//设置webRtc视频视图的缩放
this.setDeviceInfo = this._setDeviceInfo.bind(this); //设置设备信息(麦克风,摄像头等等.....)
this.setMessageDelay = this._setMessageDelay.bind(this); //设置是否延迟消息
... ... @@ -314,7 +318,12 @@ export default class MessageEntrance extends Emiter {
this.addWarn = this._addWarn.bind(this);
this.addError = this._addError.bind(this);
this.hasFreePublishChannel=this._hasFreePublishChannel.bind(this);//判断是否还有空闲的推流通道
this.hasFreePublishChannel = this._hasFreePublishChannel.bind(this);//判断是否还有空闲的推流通道
//添加外部流数据和删除外部流数据
this.deleteMediaExternalLink=this._deleteMediaExternalLink.bind(this);
this.addMediaExternalLink=this._addMediaExternalLink.bind(this);
}
//设置是否输出日志
... ... @@ -337,21 +346,21 @@ export default class MessageEntrance extends Emiter {
//上传log日志
_addLog(_data) {
if (_data) {
LogManager.addLog(LogManager.LOG, _data.msg||"");
LogManager.addLog(LogManager.LOG, _data.msg || "");
}
}
//上传warn日志
_addWarn(_data) {
if (_data) {
LogManager.addLog(LogManager.WARN, _data.msg||"");
LogManager.addLog(LogManager.WARN, _data.msg || "");
}
}
//上传error日志
_addError(_data) {
if (_data) {
LogManager.addLog(LogManager.ERROR, _data.msg||"");
LogManager.addLog(LogManager.ERROR, _data.msg || "");
}
}
... ... @@ -434,7 +443,7 @@ export default class MessageEntrance extends Emiter {
//当前的课堂状态信息发生改变,需要保存课堂状态到Sass
_onClassStatusInfoChange(_param) {
//如果MCU连接已经断开,不发送
if (!_mcu||!_mcu.connected) {
if (!_mcu || !_mcu.connected) {
loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
return;
}
... ... @@ -443,7 +452,7 @@ export default class MessageEntrance extends Emiter {
//如果是第一次点击开始上课,需要创建录制时的文件名
_onClassRecordStart(_param) {
if (!_mcu||!_mcu.connected) {
if (!_mcu || !_mcu.connected) {
loger.warn("不能保存课堂状态", GlobalConfig.getCurrentStatus());
return;
}
... ... @@ -463,7 +472,7 @@ export default class MessageEntrance extends Emiter {
//录制状态发送改变,更新所有模块的当前数据发送到MCU
updaterRecordAllApeStatus(_param) {
if(GlobalConfig.isRecordPlayBack||!_confer_ape){
if (GlobalConfig.isRecordPlayBack || !_confer_ape) {
return;
}
//老师身份和非录制回放的时候执行,录制状态发送改变,需要更新当前的数据,否则已有的消息会录制不上
... ... @@ -496,17 +505,18 @@ export default class MessageEntrance extends Emiter {
_onClassDeleteRoster(_data) {
}
//人员更新
_onClassUpdateRoster(_data){
if(!_data){
_onClassUpdateRoster(_data) {
if (!_data) {
return;
}
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2||GlobalConfig.deviceType==3||_data.nodeId==GlobalConfig.nodeId){
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2 || GlobalConfig.deviceType == 3 || _data.nodeId == GlobalConfig.nodeId) {
return;
}
if(_webRtc){
let user=GlobalConfig.rosters[_data.nodeId];
if(user&&user.openCamera==0){
if (_webRtc) {
let user = GlobalConfig.rosters[_data.nodeId];
if (user && user.openCamera == 0) {
_webRtc.closeRemoteVideoView(_data);
}
}
... ... @@ -559,14 +569,14 @@ export default class MessageEntrance extends Emiter {
//保存参数
GlobalConfig.isRecordPlayBack = false; //设置为非录制回放状态
GlobalConfig.classId = parseInt(_param.classId);
GlobalConfig.portal = _param.portal||"";
GlobalConfig.openFlash=Boolean(_param.openFlash);
if(GlobalConfig.isHttps==true){
GlobalConfig.portal = _param.portal || "";
GlobalConfig.openFlash = Boolean(_param.openFlash);
if (GlobalConfig.isHttps == true) {
//https的时候替换所有80端口
GlobalConfig.portal= GlobalConfig.replacePort(GlobalConfig.portal,":80","");
GlobalConfig.portal = GlobalConfig.replacePort(GlobalConfig.portal, ":80", "");
}
GlobalConfig.userId = ""+_param.userId || "0";
GlobalConfig.userId = "" + _param.userId || "0";
//H5处理
GlobalConfig.isH5 = _param.isH5 || false;//外部传入的参数,是否是H5
if (GlobalConfig.isH5 == true) {
... ... @@ -591,21 +601,21 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.userRole = ApeConsts.normal;
}
//如果没有名字或没有userId的时候,需要随机生成
let timestampStr=new Date().getTime().toString();
timestampStr=timestampStr.substr(timestampStr.length-4);
if(GlobalConfig.userRole==ApeConsts.host){
timestampStr="T"+timestampStr;
}else if(GlobalConfig.userRole==ApeConsts.assistant) {
let timestampStr = new Date().getTime().toString();
timestampStr = timestampStr.substr(timestampStr.length - 4);
if (GlobalConfig.userRole == ApeConsts.host) {
timestampStr = "T" + timestampStr;
} else if (GlobalConfig.userRole == ApeConsts.assistant) {
timestampStr = "A" + timestampStr;
}else if(GlobalConfig.userRole==ApeConsts.presenter){
timestampStr="P"+timestampStr;
}else {
timestampStr="S"+timestampStr;
} else if (GlobalConfig.userRole == ApeConsts.presenter) {
timestampStr = "P" + timestampStr;
} else {
timestampStr = "S" + timestampStr;
}
//如果没有名字,随机起一个名字
GlobalConfig.userName = _param.userName ||timestampStr;
GlobalConfig.userName = _param.userName || timestampStr;
//如果没有userId或者为"0",随机生成
if (!GlobalConfig.userId||GlobalConfig.userId == "0") {
if (!GlobalConfig.userId || GlobalConfig.userId == "0") {
GlobalConfig.userId = timestampStr;
}
... ... @@ -646,10 +656,10 @@ export default class MessageEntrance extends Emiter {
//loger.log("autoLoginMd5", GlobalConfig.classId, GlobalConfig.userId, GlobalConfig.userRole);
let autoLoginMd5 = MD5("" + GlobalConfig.classId + GlobalConfig.userId + GlobalConfig.userRole);
//loger.log("joinClass-GlobalConfig.autoLogin", GlobalConfig.autoLogin, "autoLoginMd5-", autoLoginMd5);
if (GlobalConfig.autoLogin && autoLoginMd5 == GlobalConfig.autoLogin||GlobalConfig.isInvisible) {
if (GlobalConfig.autoLogin && autoLoginMd5 == GlobalConfig.autoLogin || GlobalConfig.isInvisible) {
// MD5(classId+userId+userRole)==m
//自动登录,跳过验证流程
loger.log("自动登录->"+GlobalConfig.userRole);
loger.log("自动登录->" + GlobalConfig.userRole);
this._sassJoinSuccessHandler();
} else {
//不能自动登录,开始校验
... ... @@ -695,7 +705,7 @@ export default class MessageEntrance extends Emiter {
// 通过SASS平台验证(密码和MD5)
_sassJoinSuccessHandler(_data) {
//获取课堂最完整的数据
//SAAS获取课堂最完整的数据
if (_sass) {
_sass.getClassParam();
}
... ... @@ -896,15 +906,15 @@ export default class MessageEntrance extends Emiter {
loger.warn(" HLS-List", GlobalConfig.hlsPullListFinal);
loger.warn(" RS-List", GlobalConfig.rsPullListFinal);
/* //使用webRtc不需要再使用MS列表中的数据---------
GlobalConfig.msListFinal=[];//清空数据
GlobalConfig.rtmpPullListFinal=[];
//不是录制回放的时候hls的也清空
if(!GlobalConfig.isRecordPlayBack){
GlobalConfig.hlsPullListFinal=[];
GlobalConfig.rsPullListFinal=[]
}
//-------------------------------------------*/
/* //使用webRtc不需要再使用MS列表中的数据---------
GlobalConfig.msListFinal=[];//清空数据
GlobalConfig.rtmpPullListFinal=[];
//不是录制回放的时候hls的也清空
if(!GlobalConfig.isRecordPlayBack){
GlobalConfig.hlsPullListFinal=[];
GlobalConfig.rsPullListFinal=[]
}
//-------------------------------------------*/
}
... ... @@ -970,16 +980,16 @@ export default class MessageEntrance extends Emiter {
loger.warn(" HLS-List", GlobalConfig.hlsPullListFinal);
loger.warn(" RS-List", GlobalConfig.rsPullListFinal);
/*
//使用webRtc不需要再使用MS列表中的数据---------
GlobalConfig.msListFinal=[];//清空数据
GlobalConfig.rtmpPullListFinal=[];
//不是录制回放的时候hls的也清空
if(!GlobalConfig.isRecordPlayBack){
GlobalConfig.hlsPullListFinal=[];
GlobalConfig.rsPullListFinal=[]
}
//-------------------------------------------*/
/*
//使用webRtc不需要再使用MS列表中的数据---------
GlobalConfig.msListFinal=[];//清空数据
GlobalConfig.rtmpPullListFinal=[];
//不是录制回放的时候hls的也清空
if(!GlobalConfig.isRecordPlayBack){
GlobalConfig.hlsPullListFinal=[];
GlobalConfig.rsPullListFinal=[]
}
//-------------------------------------------*/
}
... ... @@ -1041,11 +1051,11 @@ export default class MessageEntrance extends Emiter {
//保存课堂状态信息
_sassSaveClassStatusInfo(_param) {
if (!_mcu||!_mcu.connected) {
if (!_mcu || !_mcu.connected) {
loger.warn("不能保存课堂数据->MCU已经断开");
return ;
return;
}
if(!_confer_ape){
if (!_confer_ape) {
return;
}
//{isForce:true} isForce->是否强制提交(true为是)
... ... @@ -1054,14 +1064,14 @@ export default class MessageEntrance extends Emiter {
if (_param && _param.isForce == true) {
isForce = true;
}
if (_confer_ape.checkHasRecordControl()||isForce) {
//POST 保存数据
clearTimeout(this.saveClassStatusTimer);
this.saveClassStatusTimer=setTimeout(()=>{
_sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo}); //保存课堂状态信息
},1000);
if (_confer_ape.checkHasRecordControl() || isForce) {
//POST 保存数据
clearTimeout(this.saveClassStatusTimer);
this.saveClassStatusTimer = setTimeout(()=> {
_sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo}); //保存课堂状态信息
}, 1000);
} else {
loger.log("没有保存课堂状态信息的权限->当前身份->"+GlobalConfig.userRole);
loger.log("没有保存课堂状态信息的权限->当前身份->" + GlobalConfig.userRole);
}
}
... ... @@ -1123,29 +1133,30 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.screenWidth = window.screen.width;
GlobalConfig.screenHeight = window.screen.height;
GlobalConfig.channelId = ""+GlobalConfig.siteId+"_"+GlobalConfig.classId;
GlobalConfig.channelId = "" + GlobalConfig.siteId + "_" + GlobalConfig.classId;
GlobalConfig.userUid = GlobalConfig.nodeId;
GlobalConfig.channelKey="";
GlobalConfig.rosters={};//情况人员数据列表
GlobalConfig.channelKey = "";
GlobalConfig.rosters = {};//情况人员数据列表
//判断是否需要获取加入音视频通话频道的channelKey
if(GlobalConfig.appCertificate){
if (GlobalConfig.appCertificate) {
loger.log("加入视频通话模块->需要先获取channelKey")
//获取channelKey
_sass.getChannelKeyToken((_data)=>{
_sass.getChannelKeyToken((_data)=> {
//{"code":200,"channelKey":"005AQAoAEQzQUQxNzFDOEQwOEU3OTVGMjlCMzZDRUZENTNGOTU0RDY4N0ZGMUEQANylukzO70ocgrNX9hlkNNWvpLBZ9buDAy/fuVkAAA==","uid":"751373669"}
if(_data&&_data.channelKey){
GlobalConfig.channelKey=_data.channelKey||"";
if (_data && _data.channelKey) {
GlobalConfig.channelKey = _data.channelKey || "";
}
this._joinClassSuccessSeting();
})
}else {
} else {
loger.log("加入视频通话模块->不需要获取channelKey")
this._joinClassSuccessSeting();
}
}
//加入课堂成功之后设置本地数据和返回数据给客户端
_joinClassSuccessSeting(){
_joinClassSuccessSeting() {
//返回给客户端初始化成功的数据
let joinClassSuccessCallBackData = {};
joinClassSuccessCallBackData.isRecordPlayBack = GlobalConfig.isRecordPlayBack;
... ... @@ -1205,8 +1216,8 @@ export default class MessageEntrance extends Emiter {
joinClassSuccessCallBackData.explorerVersion = GlobalConfig.explorerVersion;
joinClassSuccessCallBackData.os = GlobalConfig.os;
joinClassSuccessCallBackData.channelId =GlobalConfig.channelId ;
joinClassSuccessCallBackData.channelKey =GlobalConfig.channelKey ;
joinClassSuccessCallBackData.channelId = GlobalConfig.channelId;
joinClassSuccessCallBackData.channelKey = GlobalConfig.channelKey;
joinClassSuccessCallBackData.userUid = GlobalConfig.userUid;
joinClassSuccessCallBackData.appId = GlobalConfig.appId;
joinClassSuccessCallBackData.appCertificate = GlobalConfig.appCertificate;
... ... @@ -1220,7 +1231,7 @@ export default class MessageEntrance extends Emiter {
LogManager.userRole = GlobalConfig.userRole;//userRole
LogManager.userName = GlobalConfig.userName;//用户名称
LogManager.logUrl = GlobalConfig.logUrl;//日志服务器地址 //http://log.3mang.com
LogManager.platform=GlobalConfig.platform;
LogManager.platform = GlobalConfig.platform;
loger.log('加入课堂成功->');
loger.log(joinClassSuccessCallBackData);
... ... @@ -1228,25 +1239,30 @@ export default class MessageEntrance extends Emiter {
this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);
//主讲人和老师可以设置旁录
if(GlobalConfig.appId&&!GlobalConfig.openFlash){
if (GlobalConfig.appId && !GlobalConfig.openFlash) {
//加入之前先设置旁录地址,只有直播支持旁路(1路流)
if(_webRtc&&GlobalConfig.isTeachOrAssistant&&GlobalConfig.maxMediaChannels==1){
if (_webRtc && GlobalConfig.isTeachOrAssistant && GlobalConfig.maxMediaChannels == 1) {
let curTimestamp = new Date().getTime();
let streamId=GlobalConfig.siteId+"_"+GlobalConfig.classId+"_"+GlobalConfig.userId+"_"+curTimestamp;
let streamId = GlobalConfig.siteId + "_" + GlobalConfig.classId + "_" + GlobalConfig.userId + "_" + curTimestamp;
//传入固定的流Id
let publishData=this._getVideoPublishPath({streamId:streamId});
loger.log("加入之前先设置旁录地址",publishData);
if(publishData&&publishData.code==0){
let publishData = this._getVideoPublishPath({streamId: streamId});
loger.log("加入之前先设置旁录地址", publishData);
if (publishData && publishData.code == 0) {
_webRtc.setConfigPublisherUrl(publishData.publishUrl);
let m3u8Stream = _video_ape.getPlayVideoPath({"type": "m3u8", "streamId":streamId});
let rtmpStream = _video_ape.getPlayVideoPath({"type": "rtmp", "streamId":streamId});
_webRtc.setRtmpM3u8Path({m3u8Url:m3u8Stream.playUrl,rtmpUrl:rtmpStream.playUrl});
let m3u8Stream = _video_ape.getPlayVideoPath({"type": "m3u8", "streamId": streamId});
let rtmpStream = _video_ape.getPlayVideoPath({"type": "rtmp", "streamId": streamId});
_webRtc.setRtmpM3u8Path({m3u8Url: m3u8Stream.playUrl, rtmpUrl: rtmpStream.playUrl});
}
}
setTimeout(()=>{
setTimeout(()=> {
//加入音视频通话模块,延迟一秒处理,因为视频需要根据用户列表信息来判断放的位置,太早的话用户列表没有数据
this._joinChannel({channelId:GlobalConfig.channelId,channelKey:GlobalConfig.channelKey ,uid:GlobalConfig.userUid,info:""+GlobalConfig.userRole});
},1600);
this._joinChannel({
channelId: GlobalConfig.channelId,
channelKey: GlobalConfig.channelKey,
uid: GlobalConfig.userUid,
info: "" + GlobalConfig.userRole
});
}, 1600);
}
}
... ... @@ -1269,21 +1285,21 @@ export default class MessageEntrance extends Emiter {
} else {
if (GlobalConfig.mcuListFinal && GlobalConfig.mcuListFinal.length > 0) {
//如果当前没有设置过mcu的ip和端口随机选择一个
if(!GlobalConfig.MCUServerIP||GlobalConfig.mcuListFinal.length==1){
if (!GlobalConfig.MCUServerIP || GlobalConfig.mcuListFinal.length == 1) {
let index = parseInt(Math.random() * GlobalConfig.mcuListFinal.length);
GlobalConfig.MCUServerIP = GlobalConfig.mcuListFinal[index].ip || "";
GlobalConfig.MCUServerPort = GlobalConfig.mcuListFinal[index].port || "";
}else {
} else {
//当前mcu已经有值,需要选择一个新的
for(let i=0;i<GlobalConfig.mcuListFinal.length;i++){
if(GlobalConfig.MCUServerIP == GlobalConfig.mcuListFinal[i].ip){
for (let i = 0; i < GlobalConfig.mcuListFinal.length; i++) {
if (GlobalConfig.MCUServerIP == GlobalConfig.mcuListFinal[i].ip) {
//获取下一个MCU
let nextMcu= GlobalConfig.mcuListFinal[i+1];
if(!nextMcu){
let nextMcu = GlobalConfig.mcuListFinal[i + 1];
if (!nextMcu) {
//如果下一个mcu不存在就使用第一个
nextMcu=GlobalConfig.mcuListFinal[0];
nextMcu = GlobalConfig.mcuListFinal[0];
}
if(nextMcu){
if (nextMcu) {
GlobalConfig.MCUServerIP = nextMcu.ip || "";
GlobalConfig.MCUServerPort = nextMcu.port || "";
}
... ... @@ -1315,20 +1331,21 @@ export default class MessageEntrance extends Emiter {
loger.log('课堂状态发生改变,需要停止当前的所有推流');
this._emit(MessageTypes.MEDIA_STOP_PUBLISH);
}
//用更状态数据发送变更
_onRosterUpdateHandler(_data){
_onRosterUpdateHandler(_data) {
//数据无效/ios/android 不处理数据
if(!_data||GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
if (!_data || GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
return;
}
let nodeData=_data.nodeData;
let nodeData = _data.nodeData;
//数据用户是pc或H5不处理
if(!nodeData||nodeData.deviceType==0||nodeData.deviceType==3){
if (!nodeData || nodeData.deviceType == 0 || nodeData.deviceType == 3) {
return;
}
if(nodeData.openCamera>0&&_webRtc){
loger.log("收到移动端用户数据更新,当前是开启摄像头状态,需要尝试添加一个远程视频");
_webRtc.tryAddMobileStream(_data.nodeId);
if (nodeData.openCamera > 0 && _webRtc) {
loger.log("收到移动端用户数据更新,当前是开启摄像头状态,需要尝试添加一个远程视频");
_webRtc.tryAddMobileStream(_data.nodeId);
}
}
... ... @@ -1344,7 +1361,7 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.MS_PUBLISH_PORT = _param.port || "";
}
GlobalConfig.MS_PLAY_RTMP_IP = GlobalConfig.MS_PUBLISH_IP;
GlobalConfig.MS_PLAY_RTMP_PORT =GlobalConfig.MS_PUBLISH_PORT;
GlobalConfig.MS_PLAY_RTMP_PORT = GlobalConfig.MS_PUBLISH_PORT;
loger.warn('手动切换MS->', GlobalConfig.MS_PUBLISH_IP + ":" + GlobalConfig.MS_PUBLISH_PORT);
loger.warn('手动切换RTMP->', GlobalConfig.MS_PLAY_RTMP_IP + ":" + GlobalConfig.MS_PLAY_RTMP_PORT);
//更换完用户当前的MS地址,需要更新用户数据
... ... @@ -1353,10 +1370,10 @@ export default class MessageEntrance extends Emiter {
}
//音视频模块对当前正在播放的流进行更换MS
if(_video_ape){
if (_video_ape) {
_video_ape.changeMediaMs();
}
if(_audio_ape){
if (_audio_ape) {
_audio_ape.changeMediaMs();
}
}
... ... @@ -1523,14 +1540,14 @@ export default class MessageEntrance extends Emiter {
loger.warn(GlobalConfig.getCurrentStatus());
return;
}
if(GlobalConfig.isRecordPlayBack){
if (GlobalConfig.isRecordPlayBack) {
return;
}
if (_confer_ape) {
//开始上课
_confer_ape.startClass(_param);
////开始录制
//_confer_ape.startRecord();
////开始录制
//_confer_ape.startRecord();
}
}
... ... @@ -1548,7 +1565,7 @@ export default class MessageEntrance extends Emiter {
}
//控制课堂全局是否可绘制的状态
_changeDrawStatus(_param){
_changeDrawStatus(_param) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return;
... ... @@ -1558,6 +1575,7 @@ export default class MessageEntrance extends Emiter {
_confer_ape.changeDrawStatus(_param);
}
}
//暂停上课
_sendPauseClass(_param) {
if (!_mcu.connected) {
... ... @@ -1648,10 +1666,11 @@ export default class MessageEntrance extends Emiter {
_confer_ape.changeHandUpStatus(_param);
}
}
/*
* 控制画笔使用状态
* */
_controlDrawStatus(_param){
* 控制画笔使用状态
* */
_controlDrawStatus(_param) {
//{nodeId:333333,isDisEnableDraw:true}
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
... ... @@ -1661,9 +1680,10 @@ export default class MessageEntrance extends Emiter {
_confer_ape.controlDrawStatus(_param);
}
}
//停止上课
_sendCloseClass(_param) {
if (!_mcu||!_mcu.connected) {
if (!_mcu || !_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": ""};
}
... ... @@ -1680,11 +1700,11 @@ export default class MessageEntrance extends Emiter {
}
//离开视频通话频道
/* if(GlobalConfig.deviceType==0||GlobalConfig.deviceType==3){
if(_webRtc){
_webRtc.leaveChannel();
}
}*/
/* if(GlobalConfig.deviceType==0||GlobalConfig.deviceType==3){
if(_webRtc){
_webRtc.leaveChannel();
}
}*/
//停止推流
if (_video_ape) {
... ... @@ -1721,28 +1741,28 @@ export default class MessageEntrance extends Emiter {
//获取课堂所有参数(20170727新规则) api/meeting/detail.do? flash中的接口文件是 getClassParam.do
_sassGetClassParamSuccessHandler(_data) {
loger.log('获取课堂课堂信息完成.',_data.appConfig);
loger.log('获取课堂课堂信息完成.', _data.appConfig);
//包含整个课堂最全的信息,储存数据
if (_data) {
//老师\助教默认启用画笔功能,其他身份默认禁用画笔功能
if(GlobalConfig.userRole==ApeConsts.host||
GlobalConfig.userRole==ApeConsts.assistant||
GlobalConfig.userRole==ApeConsts.presenter){
GlobalConfig.selfDisEnableDrawTime=0;
if (GlobalConfig.userRole == ApeConsts.host ||
GlobalConfig.userRole == ApeConsts.assistant ||
GlobalConfig.userRole == ApeConsts.presenter) {
GlobalConfig.selfDisEnableDrawTime = 0;
}
GlobalConfig.mcuDelay = _data.h5Delay || 0; //mcu消息延迟的时间间隔,单位(秒),结合客户端传的messageDelay的值使用
GlobalConfig.className = _data.meetingName || "";
GlobalConfig.classBeginTime = _data.beginTime || "";
GlobalConfig.classEndTime = _data.endTime || "";
GlobalConfig.siteId=_data.siteID||"";//这个字段ID是大写的
GlobalConfig.channelId = ""+GlobalConfig.siteId+"_"+GlobalConfig.classId;
GlobalConfig.siteId = _data.siteID || "";//这个字段ID是大写的
GlobalConfig.channelId = "" + GlobalConfig.siteId + "_" + GlobalConfig.classId;
//sdk获取ip失败就使用saas返回的
if(!GlobalConfig.userIp){
if (!GlobalConfig.userIp) {
GlobalConfig.userIp = _data.userIp || "";
loger.warn("使用从Sass返回的userIp",GlobalConfig.userIp);
}else {
loger.warn("使用SDK获取的userIp",GlobalConfig.userIp);
loger.warn("使用从Sass返回的userIp", GlobalConfig.userIp);
} else {
loger.warn("使用SDK获取的userIp", GlobalConfig.userIp);
}
... ... @@ -1762,9 +1782,9 @@ export default class MessageEntrance extends Emiter {
//是否自动开始(身份是host的时候才用到的)
GlobalConfig.isAutoStartClass = _data.autoRecord || 0;
GlobalConfig.logUrl = _data.logUrl || "";
GlobalConfig.logUrl=GlobalConfig.logUrl.replace("https://","");
GlobalConfig.logUrl=GlobalConfig.logUrl.replace("http://","");
GlobalConfig.logUrl=GlobalConfig.locationProtocol+GlobalConfig.logUrl;
GlobalConfig.logUrl = GlobalConfig.logUrl.replace("https://", "");
GlobalConfig.logUrl = GlobalConfig.logUrl.replace("http://", "");
GlobalConfig.logUrl = GlobalConfig.locationProtocol + GlobalConfig.logUrl;
GlobalConfig.serverTime = _data.serverTime || new Date().getTime(); //获取服务器时间戳
GlobalConfig.serverAndLoacTimeDistanc = (new Date().getTime() - GlobalConfig.serverTime) / 1000; //当前系统时间和服务器时间的差值 (秒)
... ... @@ -1779,29 +1799,29 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.setMediaShareList(_data.sharedMediaList); //提前上传的媒体共享文件列表
//设置白板文档,固定ID
let whiteBoradData={
itemIdx:GlobalConfig.whiteboardId,//指定的白板文档ID
let whiteBoradData = {
itemIdx: GlobalConfig.whiteboardId,//指定的白板文档ID
name: "白板.pdf",
creatUserId: 0,
md5:"b153313f6f390328a30db5389b6cee53",
md5: "b153313f6f390328a30db5389b6cee53",
pageNum: 30,
docId: "b153313f6f390328a30db5389b6cee53",
url:"http://pclive.xuedianyun.com/DocSharing/data/whiteboard/default/whiteboard.pdf",
url: "http://pclive.xuedianyun.com/DocSharing/data/whiteboard/default/whiteboard.pdf",
dynamicTransferStatic: "0",
relativeUrl: "/DocSharing/data/whiteboard/default/whiteboard.pdf",
fileType: "pdf"
}
GlobalConfig.docListPrepare.push(whiteBoradData);
let appConfigStr=_data.appConfig;
appConfigStr=_base64.decode(appConfigStr);
let appConfig={};
try{
appConfig=JSON.parse(appConfigStr);
let appConfigStr = _data.appConfig;
appConfigStr = _base64.decode(appConfigStr);
let appConfig = {};
try {
appConfig = JSON.parse(appConfigStr);
//储存app相关信息
this._setAppConfig(appConfig);
}catch (err){
loger.warn("appConfig->解析失败",appConfigStr);
} catch (err) {
loger.warn("appConfig->解析失败", appConfigStr);
}
... ... @@ -1812,9 +1832,9 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.DOCServerIP = GlobalConfig.docList[index].ip || "";
GlobalConfig.DOCServerPort = GlobalConfig.docList[index].port || "";
if(GlobalConfig.isHttps){
if (GlobalConfig.isHttps) {
//https的时候替换所有80端口
GlobalConfig.DOCServerPort= GlobalConfig.replacePort(GlobalConfig.DOCServerPort,"80","");
GlobalConfig.DOCServerPort = GlobalConfig.replacePort(GlobalConfig.DOCServerPort, "80", "");
}
}
... ... @@ -1824,9 +1844,9 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.RecordServerIP = GlobalConfig.recordList[index].ip || "";
GlobalConfig.RecordServerPort = GlobalConfig.recordList[index].port || "";
if(GlobalConfig.isHttps){
if (GlobalConfig.isHttps) {
//https的时候替换所有80端口
GlobalConfig.RecordServerPort= GlobalConfig.replacePort(GlobalConfig.RecordServerPort,"80","");
GlobalConfig.RecordServerPort = GlobalConfig.replacePort(GlobalConfig.RecordServerPort, "80", "");
}
}
loger.warn('默认->文档服务器地址->.', GlobalConfig.DOCServerIP, GlobalConfig.DOCServerPort);
... ... @@ -1842,26 +1862,107 @@ export default class MessageEntrance extends Emiter {
}
}
//课堂获取Sass数据完成
this._emit(MessageTypes.CLASS_GET_INFO_SUCCESS, GlobalConfig.getClassInfo());
//存储Sass数据到本地
if (_data.currentInfo) {
//根据从Sass获取的数据信息,同步最后一次保存的课堂状态信息
loger.log("从Saas返回的课堂状态信息数据",_data.currentInfo);
loger.log("从Saas返回的课堂状态信息数据", _data.currentInfo);
try {
let dataObj=JSON.parse(_data.currentInfo);
dataObj.recordStatus=false;
let dataObj = JSON.parse(_data.currentInfo);
dataObj.recordStatus = false;
GlobalConfig.setClassStatusInfo(dataObj);
} catch (err) {
loger.warn("从Sass获取的课堂数据JSON转换失败->");
GlobalConfig.setClassStatusInfo(_data.currentInfo);
}
loger.log(GlobalConfig.classStatusInfo);
//课堂获取Sass数据完成
this._emit(MessageTypes.CLASS_GET_INFO_SUCCESS, GlobalConfig.getClassInfo());
//课堂数据获取完成->进入课堂或进入录制回放
//录制回放不需要获取ip信息和选点
if (GlobalConfig.isRecordPlayBack) {
if (_recordPlayback) {
//开启录制回放流程
loger.warn("开启录制回放流程");
//根据用户的userIp信息从sever.json和Sass中选择最终mcu和推流拉流数据列表
ServerConfig.serverList = ServerConfig.sassServerJson;
this._choiceMcuAndMsListFromSass();
//获取MCU和MS 推流拉流、录制回放的默认地址
this.getMcuAndMsDefaultServerIp();
_recordPlayback.readyLoadRecordPlayData();
} else {
loger.warn("开启录制回放流程失败->还未创建模块");
}
} else {
//初始化音视频通话sdk
if (GlobalConfig.appId && !GlobalConfig.openFlash) {
loger.log("使用webRtc通话模式");
//加入webRtc
this._initWebRtcSdk({
appId: GlobalConfig.appId
}, ()=> {
//音视频通话SDK初始化完成之后,根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
this.loadServerJsonAndgetUserIpInfo();
});
} else {
//加入flash
loger.log("使用flash通话模式");
this.loadServerJsonAndgetUserIpInfo();
}
}
} else {
loger.log("还没有保存过课堂状信息");
loger.warn("从Sass获取的课堂数据currentInfo无效->再次获取");
//如果获取的数据中没有课堂保存的状态数据,需要单独的接口获取一次
_sass.getClassRecordInfo((_currentInfo)=> {
if(_currentInfo){
try {
let dataObj = JSON.parse(_currentInfo);
dataObj.recordStatus = false;
GlobalConfig.setClassStatusInfo(dataObj);
} catch (err) {
loger.warn("getClassRecordInfo获取的课堂数据JSON转换失败->");
}
}
//课堂获取Sass数据完成
this._emit(MessageTypes.CLASS_GET_INFO_SUCCESS, GlobalConfig.getClassInfo());
//课堂数据获取完成->进入课堂或进入录制回放
//录制回放不需要获取ip信息和选点
if (GlobalConfig.isRecordPlayBack) {
if (_recordPlayback) {
//开启录制回放流程
loger.warn("开启录制回放流程");
//根据用户的userIp信息从sever.json和Sass中选择最终mcu和推流拉流数据列表
ServerConfig.serverList = ServerConfig.sassServerJson;
this._choiceMcuAndMsListFromSass();
//获取MCU和MS 推流拉流、录制回放的默认地址
this.getMcuAndMsDefaultServerIp();
_recordPlayback.readyLoadRecordPlayData();
} else {
loger.warn("开启录制回放流程失败->还未创建模块");
}
} else {
//初始化音视频通话sdk
if (GlobalConfig.appId && !GlobalConfig.openFlash) {
loger.log("使用webRtc通话模式");
//加入webRtc
this._initWebRtcSdk({
appId: GlobalConfig.appId
}, ()=> {
//音视频通话SDK初始化完成之后,根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
this.loadServerJsonAndgetUserIpInfo();
});
} else {
//加入flash
loger.log("使用flash通话模式");
this.loadServerJsonAndgetUserIpInfo();
}
}
})
}
/* //课堂获取Sass数据完成
this._emit(MessageTypes.CLASS_GET_INFO_SUCCESS, GlobalConfig.getClassInfo());
//课堂数据获取完成->进入课堂或进入录制回放
//录制回放不需要获取ip信息和选点
if (GlobalConfig.isRecordPlayBack) {
... ... @@ -1879,26 +1980,21 @@ export default class MessageEntrance extends Emiter {
}
} else {
//初始化音视频通话sdk
if(GlobalConfig.appId&&!GlobalConfig.openFlash){
if (GlobalConfig.appId && !GlobalConfig.openFlash) {
loger.log("使用webRtc通话模式");
//加入webRtc
this._initWebRtcSdk({
appId:GlobalConfig.appId
},()=>{
appId: GlobalConfig.appId
}, ()=> {
//音视频通话SDK初始化完成之后,根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
this.loadServerJsonAndgetUserIpInfo();
});
}else {
} else {
//加入flash
loger.log("使用flash通话模式");
this.loadServerJsonAndgetUserIpInfo();
}
/*
//根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
this.loadServerJsonAndgetUserIpInfo();
*/
}
}*/
}
//获取各个服务的默认ip,之后会进行测速选择更快的ip
... ... @@ -1907,8 +2003,8 @@ export default class MessageEntrance extends Emiter {
if (GlobalConfig.mcuListFinal && GlobalConfig.mcuListFinal.length > 0) {
//还未开始选点之前随机选择一个
let index = parseInt(Math.random() * GlobalConfig.mcuListFinal.length);
if(!GlobalConfig.MCUServerIP){
index=0;
if (!GlobalConfig.MCUServerIP) {
index = 0;
}
GlobalConfig.MCUServerIP = GlobalConfig.mcuListFinal[index].ip || "";
GlobalConfig.MCUServerPort = GlobalConfig.mcuListFinal[index].port || "";
... ... @@ -1918,8 +2014,8 @@ export default class MessageEntrance extends Emiter {
if (GlobalConfig.rsPullListFinal && GlobalConfig.rsPullListFinal.length > 0) {
//还未开始选点之前随机选择一个
let index = parseInt(Math.random() * GlobalConfig.rsPullListFinal.length);
if(!GlobalConfig.RS_RECORD_PLAY_IP){
index=0;
if (!GlobalConfig.RS_RECORD_PLAY_IP) {
index = 0;
}
GlobalConfig.RS_RECORD_PLAY_IP = GlobalConfig.rsPullListFinal[index].ip || "";
GlobalConfig.RS_RECORD_PLAY_PORT = GlobalConfig.rsPullListFinal[index].port || "";
... ... @@ -1929,8 +2025,8 @@ export default class MessageEntrance extends Emiter {
if (GlobalConfig.msListFinal && GlobalConfig.msListFinal.length > 0) {
//还未开始选点之前随机选择一个
let index = parseInt(Math.random() * GlobalConfig.msListFinal.length);
if(!GlobalConfig.MS_PUBLISH_IP){
index=0;
if (!GlobalConfig.MS_PUBLISH_IP) {
index = 0;
}
GlobalConfig.MS_PUBLISH_IP = GlobalConfig.msListFinal[index].ip || "";
GlobalConfig.MS_PUBLISH_PORT = GlobalConfig.msListFinal[index].port || "";
... ... @@ -1940,8 +2036,8 @@ export default class MessageEntrance extends Emiter {
if (GlobalConfig.rtmpPullListFinal && GlobalConfig.rtmpPullListFinal.length > 0) {
// //还未开始选点之前随机选择一个
let index = parseInt(Math.random() * GlobalConfig.rtmpPullListFinal.length);
if(!GlobalConfig.MS_PLAY_RTMP_IP){
index=0;
if (!GlobalConfig.MS_PLAY_RTMP_IP) {
index = 0;
}
GlobalConfig.MS_PLAY_RTMP_IP = GlobalConfig.rtmpPullListFinal[index].ip || "";
GlobalConfig.MS_PLAY_RTMP_PORT = GlobalConfig.rtmpPullListFinal[index].port || "";
... ... @@ -1955,8 +2051,8 @@ export default class MessageEntrance extends Emiter {
if (GlobalConfig.hlsPullListFinal && GlobalConfig.hlsPullListFinal.length > 0) {
//有单独的hls拉流地址
let index = parseInt(Math.random() * GlobalConfig.hlsPullListFinal.length);
if(!GlobalConfig.MS_PLAY_HLS_IP){
index=0;
if (!GlobalConfig.MS_PLAY_HLS_IP) {
index = 0;
}
GlobalConfig.MS_PLAY_HLS_IP = GlobalConfig.hlsPullListFinal[index].ip || "";
GlobalConfig.MS_PLAY_HLS_PORT = GlobalConfig.hlsPullListFinal[index].port || "";
... ... @@ -2007,25 +2103,27 @@ export default class MessageEntrance extends Emiter {
_confer_ape.updaterUserDeviecStatusChange(_data);
}
}
//webRtc推流状态发生改变
mediaPublishStatusChange(_data){
mediaPublishStatusChange(_data) {
if (!_mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": ""};
}
if (_video_ape) {
//if(_data.status==WebRtcApe.RECORD_STATUS_1&&!_data.publishUrl){
loger.log("webRtc推流状态发生改变->发送同步消息",_data);
if(_data.status==WebRtcApe.RECORD_STATUS_1){
let publishData=this._getVideoPublishPath();
let publishUrl="";
if(publishData&&publishData.code==0){
_data.publishUrl=publishData.publishUrl||"";
loger.log("webRtc推流状态发生改变->发送同步消息", _data);
if (_data.status == WebRtcApe.RECORD_STATUS_1) {
let publishData = this._getVideoPublishPath();
let publishUrl = "";
if (publishData && publishData.code == 0) {
_data.publishUrl = publishData.publishUrl || "";
}
}
_video_ape.mediaPublishStatusChange(_data);
}
}
//屏幕共享
//开始屏幕共享
_publishScreenShare(_param) {
... ... @@ -2041,6 +2139,54 @@ export default class MessageEntrance extends Emiter {
}
}
//添加外部流
_addMediaExternalLink(_params){
if(!_params||!_params.rtmpUrl){
return;
}
let fileInfo = {};
fileInfo.pageNum =1;// 文档的总页数
fileInfo.fileName = _params.fileName||"视频"+EngineUtils.creatTimestamp()+".video";//文档名字
fileInfo.fileType ="video";
fileInfo.relativeUrl =""; //文档相对地址
fileInfo.url = _params.rtmpUrl||"unkown"; //文档绝对地址 默认值: null
fileInfo.docId =""+EngineUtils.creatTimestamp(); //文档在数据库中的唯一id标识 默认值: null
fileInfo.visible = false; // 是否显示 默认值: false
fileInfo.publishUrl = _params.rtmpUrl||"";
fileInfo.rtmpUrl = _params.rtmpUrl||"";
fileInfo.m3u8Url = _params.m3u8Url||"";
fileInfo.replay = _params.replay||"";
loger.log("添加外部流", fileInfo);
this._sendDocumentUpload(fileInfo);
}
//删除外部流
_deleteMediaExternalLink(_param){
this._sendDocumentDelete(_param);
}
//推送外部流地址
_publishExternalLink(_param) {
if (!_mcu.connected) {
loger.warn("推送外部流地址失败,mcu连接已经断开");
return {"code": ApeConsts.RETURN_FAILED, "data": ""};
}
loger.log("推送外部流地址", _param);
if (_video_ape) {
_video_ape.publishExternalLink(_param);
}
}
//停止推送外部流地址
_stopPublishExternalLink(_param) {
if (!_mcu.connected) {
loger.warn("停止推送外部流地址失败,mcu连接已经断开");
return {"code": ApeConsts.RETURN_FAILED, "data": ""};
}
loger.log("停止推送外部流地址", _param);
if (_video_ape) {
_video_ape.stopPublishExternalLink(_param);
}
}
//VidoeApe
videoUpdate(_data) {
//视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
... ... @@ -2257,22 +2403,24 @@ export default class MessageEntrance extends Emiter {
_doc_ape.documentSwitchDoc(_param);
}
}
//切换到白板文档
_switchToWhiteboard(_param){
_switchToWhiteboard(_param) {
if (!_mcu.connected) {
loger.warn("连接已经断开->不能切换到白板文档");
return;
}
//白板文档的数据
let data={
itemIdx:GlobalConfig.whiteboardId,
visible:true
let data = {
itemIdx: GlobalConfig.whiteboardId,
visible: true
}
if (_doc_ape) {
loger.log("切换到白板文档");
_doc_ape.documentSwitchDoc(data);
}
}
//操作文档(翻页)
_sendDocumentSwitchPage(_param) {
if (!_mcu.connected) {
... ... @@ -2349,11 +2497,12 @@ export default class MessageEntrance extends Emiter {
}
//隐藏当前显示的文档
_hideCurrentDocument(_params){
_hideCurrentDocument(_params) {
if (_doc_ape) {
_doc_ape.hideCurrentDocument(_params);
}
}
//文档加入频道成功,同步到MCU服务器上的数据
docJoinChannelSuccess() {
loger.log("文档加入频道成功->isHost=", GlobalConfig.isHost, "当前总人数:", GlobalConfig.rosterNumber, "sassDoclength=", GlobalConfig.docListPrepare.length);
... ... @@ -2366,16 +2515,16 @@ export default class MessageEntrance extends Emiter {
if (value) {
//loger.log("判断是否需要把提前上传的文档上传到mcu", value);
let paramInfo = {
"pageNum": value.pdfSize||value.pageNum,
"pageNum": value.pdfSize || value.pageNum,
"fileName": value.name,
"fileType": value.type,
"relativeUrl": value.relativeLocation||value.relativeUrl,
"url": value.absoluteLocation||value.url,
"creatUserId": value.createUserID||0,
"docId": value.id||value.docId,
"md5": value.MD5||"",
"relativeUrl": value.relativeLocation || value.relativeUrl,
"url": value.absoluteLocation || value.url,
"creatUserId": value.createUserID || 0,
"docId": value.id || value.docId,
"md5": value.MD5 || "",
"visible": false,
"itemIdx":value.itemIdx||0
"itemIdx": value.itemIdx || 0
};
this._sendDocumentUpload(paramInfo);
}
... ... @@ -2621,10 +2770,10 @@ export default class MessageEntrance extends Emiter {
//保存参数
GlobalConfig.isRecordPlayBack = true; //设置为录制回放状态
GlobalConfig.classId = parseInt(_param.classId);
GlobalConfig.portal = _param.portal||"";
if(GlobalConfig.isHttps==true){
GlobalConfig.portal = _param.portal || "";
if (GlobalConfig.isHttps == true) {
//https的时候替换所有80端口
GlobalConfig.portal= GlobalConfig.replacePort(GlobalConfig.portal,":80","");
GlobalConfig.portal = GlobalConfig.replacePort(GlobalConfig.portal, ":80", "");
}
GlobalConfig.userRole = ApeConsts.normal; //*************很重要,录制回放的时候,身份模式是普通人********
... ... @@ -2688,7 +2837,7 @@ export default class MessageEntrance extends Emiter {
//录制回放加入 课堂成功
_joinRecordPlaybackSuccessHandler(_data) {
loger.log('加入录制回放成功.');
LogManager.IS_OPEN_SEND_LOG=false;//录制回放不需要上报日志
LogManager.IS_OPEN_SEND_LOG = false;//录制回放不需要上报日志
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
//返回给客户端初始化成功的数据
... ... @@ -2811,104 +2960,112 @@ export default class MessageEntrance extends Emiter {
//WEB RTC-------------------------------------------------------------------------------------------
/*
* 初始化webRtc
* */
_initWebRtcSdk(_params,_callback){
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
* 初始化webRtc
* */
_initWebRtcSdk(_params, _callback) {
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
loger.warn("移动端不需要处理初始化webRtc");
if(_callback){
if (_callback) {
_callback();
}
return ;
return;
}
if(_webRtc){
_webRtc.initApp(_params,(_callbackData)=>{
if (_webRtc) {
_webRtc.initApp(_params, (_callbackData)=> {
//_callback({isSuccess:false,error:err});
if(_callbackData&&_callbackData.isSuccess==true){
this._emit(MessageTypes.WEB_RTC_INIT_SUCCESS,_callbackData);
}else {
this._emit(MessageTypes.WEB_RTC_INIT_FAILED,_callbackData);
if (_callbackData && _callbackData.isSuccess == true) {
this._emit(MessageTypes.WEB_RTC_INIT_SUCCESS, _callbackData);
} else {
this._emit(MessageTypes.WEB_RTC_INIT_FAILED, _callbackData);
}
if(_callback){
if (_callback) {
_callback();
}
});
}
}
/*
* 重新加入频道
* */
_reJoinChannel(_params){
if(GlobalConfig.appId&&!GlobalConfig.openFlash){
//先离开频道
this._leaveChannel();
* 重新加入频道
* */
_reJoinChannel(_params) {
if (GlobalConfig.appId && !GlobalConfig.openFlash) {
//先离开频道
this._leaveChannel();
//主讲人和老师可以设置旁录
//加入之前先设置旁录地址,只有直播支持旁路(1路流)
if(_webRtc&&GlobalConfig.isTeachOrAssistant&&GlobalConfig.maxMediaChannels==1){
if (_webRtc && GlobalConfig.isTeachOrAssistant && GlobalConfig.maxMediaChannels == 1) {
let curTimestamp = new Date().getTime();
let streamId=GlobalConfig.siteId+"_"+GlobalConfig.classId+"_"+GlobalConfig.userId+"_"+curTimestamp;
let streamId = GlobalConfig.siteId + "_" + GlobalConfig.classId + "_" + GlobalConfig.userId + "_" + curTimestamp;
//传入固定的流Id
let publishData=this._getVideoPublishPath({streamId:streamId});
loger.log("加入之前先设置旁录地址",publishData);
if(publishData&&publishData.code==0){
let publishData = this._getVideoPublishPath({streamId: streamId});
loger.log("加入之前先设置旁录地址", publishData);
if (publishData && publishData.code == 0) {
_webRtc.setConfigPublisherUrl(publishData.publishUrl);
let m3u8Stream = _video_ape.getPlayVideoPath({"type": "m3u8", "streamId":streamId});
let rtmpStream = _video_ape.getPlayVideoPath({"type": "rtmp", "streamId":streamId});
_webRtc.setRtmpM3u8Path({m3u8Url:m3u8Stream.playUrl,rtmpUrl:rtmpStream.playUrl});
let m3u8Stream = _video_ape.getPlayVideoPath({"type": "m3u8", "streamId": streamId});
let rtmpStream = _video_ape.getPlayVideoPath({"type": "rtmp", "streamId": streamId});
_webRtc.setRtmpM3u8Path({m3u8Url: m3u8Stream.playUrl, rtmpUrl: rtmpStream.playUrl});
}
}
clearTimeout(this.joinChannelTimer);
this.joinChannelTimer=setTimeout(()=>{
this.joinChannelTimer = setTimeout(()=> {
//加入音视频通话模块,延迟一秒处理,因为视频需要根据用户列表信息来判断放的位置,太早的话用户列表没有数据
this._joinChannel({channelId:GlobalConfig.channelId,channelKey:GlobalConfig.channelKey ,uid:GlobalConfig.userUid,info:""+GlobalConfig.userRole});
},1600);
this._joinChannel({
channelId: GlobalConfig.channelId,
channelKey: GlobalConfig.channelKey,
uid: GlobalConfig.userUid,
info: "" + GlobalConfig.userRole
});
}, 1600);
}
}
/*
* 加入视频通话
* */
_joinChannel(_params){
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
* 加入视频通话
* */
_joinChannel(_params) {
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
loger.warn("移动端不需要处理加入视频房间");
return ;
return;
}
if(_webRtc){
if (_webRtc) {
_webRtc.joinChannel(_params);
}
}
/*
* 离开视频通话频道
* */
_leaveChannel(_params){
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
return ;
* 离开视频通话频道
* */
_leaveChannel(_params) {
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
return;
}
if(_webRtc){
if (_webRtc) {
_webRtc.leaveChannel(_params);
}
}
/*
* 发布流
* */
_publishMedia(_params){
* 发布流
* */
_publishMedia(_params) {
//判断是否能推流,当前课堂推流人数是有限制的
let premission=GlobalConfig.getPublishPermission();
loger.log("判断是否能推流->",premission);
if(!premission&&GlobalConfig.userRole!=ApeConsts.invisible){
let premission = GlobalConfig.getPublishPermission();
loger.log("判断是否能推流->", premission);
if (!premission && GlobalConfig.userRole != ApeConsts.invisible) {
loger.warn("不能再打开更多设备");
console.log("当前用户列表",GlobalConfig.rosters);
console.log("当前用户列表", GlobalConfig.rosters);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_WEBRTC_PUBLISH_FULL);
return ;
return;
}
//ios和安卓的只需要更新数据即可
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
loger.log("调用webRtc推流");
GlobalConfig.openCamera = EngineUtils.creatTimestamp();
GlobalConfig.openMicrophones = GlobalConfig.openCamera;
this.userDeviecStatusChange({
this.userDeviecStatusChange({
nodeId: GlobalConfig.nodeId,
userRole: GlobalConfig.userRole,
userName: GlobalConfig.userName,
... ... @@ -2916,25 +3073,25 @@ export default class MessageEntrance extends Emiter {
openCamera: GlobalConfig.openCamera,
openMicrophones: GlobalConfig.openMicrophones
});
this._mediaRecordControl({"status":WebRtcApe.RECORD_STATUS_1});
return ;
this._mediaRecordControl({"status": WebRtcApe.RECORD_STATUS_1});
return;
}
//PC端的先推流再同步数据
if(_webRtc){
if (_webRtc) {
_webRtc.publish(_params);
}
}
/*
* 停止发布流
* */
_unpublishMedia(_params){
* 停止发布流
* */
_unpublishMedia(_params) {
//ios和安卓的只需要更新数据即可
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
loger.log("调用webRtc停止推流");
GlobalConfig.openCamera =0;
GlobalConfig.openMicrophones =0;
GlobalConfig.openCamera = 0;
GlobalConfig.openMicrophones = 0;
this.userDeviecStatusChange({
nodeId: GlobalConfig.nodeId,
userRole: GlobalConfig.userRole,
... ... @@ -2943,12 +3100,12 @@ export default class MessageEntrance extends Emiter {
openCamera: GlobalConfig.openCamera,
openMicrophones: GlobalConfig.openMicrophones
});
this._mediaRecordControl({"status":WebRtcApe.RECORD_STATUS_0});
return ;
this._mediaRecordControl({"status": WebRtcApe.RECORD_STATUS_0});
return;
}
if(_webRtc){
this._mediaRecordControl({"status":WebRtcApe.RECORD_STATUS_0});
if (_webRtc) {
this._mediaRecordControl({"status": WebRtcApe.RECORD_STATUS_0});
_webRtc.unpublish(_params);
}
}
... ... @@ -2956,45 +3113,47 @@ export default class MessageEntrance extends Emiter {
/*
* 切换摄像头和麦克风设备
* */
_changeDevices(_params){
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
_changeDevices(_params) {
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
return;
}
if(_webRtc){
if (_webRtc) {
_webRtc.changeDevices(_params);
}
}
/*
* 设置旁路推流
* */
_setConfigPublisher(_params){
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
_setConfigPublisher(_params) {
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
return;
}
if(_webRtc){
if (_webRtc) {
_webRtc.setConfigPublisher(_params);
}
}
/*
* 设置本地video视图
* */
_setLocalMediaView(_params){
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
* 设置本地video视图
* */
_setLocalMediaView(_params) {
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
return;
}
if(_webRtc){
if (_webRtc) {
_webRtc.setLoaclView(_params);
}
}
/*
* 设置房间内老师身份的视图
* */
_setHostRemoteMediaView(_params){
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
* 设置房间内老师身份的视图
* */
_setHostRemoteMediaView(_params) {
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
return;
}
if(_webRtc){
if (_webRtc) {
_webRtc.setHostRemoteMediaView(_params);
}
}
... ... @@ -3002,117 +3161,119 @@ export default class MessageEntrance extends Emiter {
/*
* 设置房间内普通身份的视图
* */
_setNormalRemoteMediaView(_params){
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
_setNormalRemoteMediaView(_params) {
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
return;
}
if(_webRtc){
if (_webRtc) {
_webRtc.setNormalRemoteMediaView(_params);
}
}
/*
* 设置RTC视频属性
* */
_changeRtcVideoConfig(_params){
loger.log("设置RTC视频属性",_params);
if(!_params){
* 设置RTC视频属性
* */
_changeRtcVideoConfig(_params) {
loger.log("设置RTC视频属性", _params);
if (!_params) {
return;
}
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
return;
}
if(_webRtc){
if (_webRtc) {
_webRtc.changeRtcVideoConfig(_params);
//如果是老师和主讲人操作,需要同步给所有人
if(GlobalConfig.isTeachOrAssistant){
if(_confer_ape){
let newVideoScale=_params.videoScale||1;
if(GlobalConfig.videoScale==newVideoScale){
loger.log("不需要设置视频视图大小,没有发生改变",newVideoScale);
if (GlobalConfig.isTeachOrAssistant) {
if (_confer_ape) {
let newVideoScale = _params.videoScale || 1;
if (GlobalConfig.videoScale == newVideoScale) {
loger.log("不需要设置视频视图大小,没有发生改变", newVideoScale);
return;
}
loger.log("设置视频视图大小->",newVideoScale);
GlobalConfig.videoScale=newVideoScale;
_confer_ape.sendUpdaterClassStatusInfo({videoScale:_params.videoScale});
loger.log("设置视频视图大小->", newVideoScale);
GlobalConfig.videoScale = newVideoScale;
_confer_ape.sendUpdaterClassStatusInfo({videoScale: _params.videoScale});
}
}
}
}
/*
* 设置监课和需要隐藏显示的用户视图
* */
_setInvisibleMediaView(_params){
if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
* 设置监课和需要隐藏显示的用户视图
* */
_setInvisibleMediaView(_params) {
if (GlobalConfig.deviceType == 1 || GlobalConfig.deviceType == 2) {
return;
}
if(_webRtc){
if (_webRtc) {
_webRtc.setInvisibleMediaView(_params);
}
}
//设置app相关数据
_setAppConfig(_params){
if(!_params){
_setAppConfig(_params) {
if (!_params) {
return;
}
loger.log("设置appConfig",_params);
if(GlobalConfig.appId){
loger.log("设置appConfig", _params);
if (GlobalConfig.appId) {
loger.log("本地已经设置appConfig,不需要再设置");
return;
}
GlobalConfig.appId=_params.appId||"";
GlobalConfig.appCertificate=_params.appCertificate||"";
GlobalConfig.appRecordingKey=_params.appRecordingKey||"";
GlobalConfig.recordInterfaces=_params.recordInterfaces||"";
GlobalConfig.getChannelToken=_params.getChannelToken||""
GlobalConfig.getRecordInfoInterfaces=_params.getRecordInfoInterfaces||"";
GlobalConfig.stopRecordingInterfaces=_params.stopRecordingInterfaces||"";
GlobalConfig.getTxRecordInfoInterfaces=_params.getTxRecordInfoInterfaces||"";
GlobalConfig.getRecordFileURLAgoInterfaces=_params.getRecordFileURLAgoInterfaces||"";
GlobalConfig.appId = _params.appId || "";
GlobalConfig.appCertificate = _params.appCertificate || "";
GlobalConfig.appRecordingKey = _params.appRecordingKey || "";
GlobalConfig.recordInterfaces = _params.recordInterfaces || "";
GlobalConfig.getChannelToken = _params.getChannelToken || ""
GlobalConfig.getRecordInfoInterfaces = _params.getRecordInfoInterfaces || "";
GlobalConfig.stopRecordingInterfaces = _params.stopRecordingInterfaces || "";
GlobalConfig.getTxRecordInfoInterfaces = _params.getTxRecordInfoInterfaces || "";
GlobalConfig.getRecordFileURLAgoInterfaces = _params.getRecordFileURLAgoInterfaces || "";
//去掉协议头
try{
if(GlobalConfig.recordInterfaces){
GlobalConfig.recordInterfaces=GlobalConfig.recordInterfaces.replace('http://',"");
GlobalConfig.recordInterfaces=GlobalConfig.recordInterfaces.replace('https://',"");
try {
if (GlobalConfig.recordInterfaces) {
GlobalConfig.recordInterfaces = GlobalConfig.recordInterfaces.replace('http://', "");
GlobalConfig.recordInterfaces = GlobalConfig.recordInterfaces.replace('https://', "");
}
if(GlobalConfig.getRecordInfoInterfaces){
GlobalConfig.getRecordInfoInterfaces=GlobalConfig.getRecordInfoInterfaces.replace('http://',"");
GlobalConfig.getRecordInfoInterfaces=GlobalConfig.getRecordInfoInterfaces.replace('https://',"");
if (GlobalConfig.getRecordInfoInterfaces) {
GlobalConfig.getRecordInfoInterfaces = GlobalConfig.getRecordInfoInterfaces.replace('http://', "");
GlobalConfig.getRecordInfoInterfaces = GlobalConfig.getRecordInfoInterfaces.replace('https://', "");
}
if(GlobalConfig.getTxRecordInfoInterfaces){
GlobalConfig.getTxRecordInfoInterfaces=GlobalConfig.getTxRecordInfoInterfaces.replace('http://',"");
GlobalConfig.getTxRecordInfoInterfaces=GlobalConfig.getTxRecordInfoInterfaces.replace('https://',"");
if (GlobalConfig.getTxRecordInfoInterfaces) {
GlobalConfig.getTxRecordInfoInterfaces = GlobalConfig.getTxRecordInfoInterfaces.replace('http://', "");
GlobalConfig.getTxRecordInfoInterfaces = GlobalConfig.getTxRecordInfoInterfaces.replace('https://', "");
}
if(GlobalConfig.getRecordFileURLAgoInterfaces){
GlobalConfig.getRecordFileURLAgoInterfaces=GlobalConfig.getRecordFileURLAgoInterfaces.replace('http://',"");
GlobalConfig.getRecordFileURLAgoInterfaces=GlobalConfig.getRecordFileURLAgoInterfaces.replace('https://',"");
if (GlobalConfig.getRecordFileURLAgoInterfaces) {
GlobalConfig.getRecordFileURLAgoInterfaces = GlobalConfig.getRecordFileURLAgoInterfaces.replace('http://', "");
GlobalConfig.getRecordFileURLAgoInterfaces = GlobalConfig.getRecordFileURLAgoInterfaces.replace('https://', "");
}
if(GlobalConfig.stopRecordingInterfaces){
GlobalConfig.stopRecordingInterfaces=GlobalConfig.stopRecordingInterfaces.replace('http://',"");
GlobalConfig.stopRecordingInterfaces=GlobalConfig.stopRecordingInterfaces.replace('https://',"");
if (GlobalConfig.stopRecordingInterfaces) {
GlobalConfig.stopRecordingInterfaces = GlobalConfig.stopRecordingInterfaces.replace('http://', "");
GlobalConfig.stopRecordingInterfaces = GlobalConfig.stopRecordingInterfaces.replace('https://', "");
}
if(GlobalConfig.getChannelToken){
GlobalConfig.getChannelToken=GlobalConfig.getChannelToken.replace('http://',"");
GlobalConfig.getChannelToken=GlobalConfig.getChannelToken.replace('https://',"");
if (GlobalConfig.getChannelToken) {
GlobalConfig.getChannelToken = GlobalConfig.getChannelToken.replace('http://', "");
GlobalConfig.getChannelToken = GlobalConfig.getChannelToken.replace('https://', "");
}
}catch (err){
} catch (err) {
}
}
//录制状态控制和推流状态控制
_mediaRecordControl(_params){
if(!GlobalConfig.recordInterfaces||!_params){
loger.log("录制控制->失败->接口地址无效",_params);
return ;
_mediaRecordControl(_params) {
if (!GlobalConfig.recordInterfaces || !_params) {
loger.log("录制控制->失败->接口地址无效", _params);
return;
}
if(_webRtc){
switch (_params.status){
if (_webRtc) {
switch (_params.status) {
case WebRtcApe.RECORD_STATUS_0:
case WebRtcApe.RECORD_STATUS_1:
//推流/停止推流/开启录制 统一使用一个接口
... ... @@ -3127,14 +3288,15 @@ export default class MessageEntrance extends Emiter {
}
}
}
//webRtc-----------------end --------------------------------
//判断是否能推流,当前课堂推流人数是有限制的
_hasFreePublishChannel(){
let premission=GlobalConfig.getPublishPermission();
loger.log("判断是否能推流->",premission);
if(!premission&&GlobalConfig.userRole!=ApeConsts.invisible){
_hasFreePublishChannel() {
let premission = GlobalConfig.getPublishPermission();
loger.log("判断是否能推流->", premission);
if (!premission && GlobalConfig.userRole != ApeConsts.invisible) {
loger.warn("不能再打开更多设备");
console.log("当前用户列表",GlobalConfig.rosters);
console.log("当前用户列表", GlobalConfig.rosters);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_WEBRTC_PUBLISH_FULL);
return premission;
}
... ...
... ... @@ -862,8 +862,74 @@ class Sass extends Emiter {
this._emit(Sass.SASS_GET_QUESTION_RESULT_FAILED);
});
}
//点名---------------------------------------------------------
//获取课堂保存的信息
getClassRecordInfo(_callback){
//http://networkschool.xuedianyun.com/server/recordInfo/getOldRecordInfo
let path="networkschool.xuedianyun.com/server/recordInfo/getOldRecordInfo";
let url = `${GlobalConfig.locationProtocol+path}`;
loger.log('获取课堂保存的状态信息', url);
//接口中用的是GET
fetch(encodeURI(url), {
method: 'POST',
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"
},
body: `meetingNumber=${ GlobalConfig.classId}`,
timeout: 5000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`获取课堂保存的状态信息-网络异常.状态码:${ret}`);
if(_callback){
_callback();
}
throw '';
}
})
.then(ret => {
loger.log('获取课堂保存的状态信息-完成');
/* {
"code": 200,
"returnData": {
"data": {
"id": 28,
"meeting_number": "1170105412",
"info": "{\"siteId\":\"h5dev\",\"classId\":1170105412,\"className\":\"mcuClientSdk20170318\",\"classType\":1,\"classStatus\":2,\"classStartTime\":\"2017-3-24-20-9-56\",\"classStopTime\":\"2017-3-28-22-20-56\",\"classTimestamp\":25402,\"recordPlaybackMaxTime\":0,\"classBeginTime\":\"2017-03-18 19:00:00\",\"classEndTime\":\"2017-03-29 21:00:00\",\"recordStatus\":false,\"recordTimestamp\":0,\"recordFileName\":\"h5dev/20170318/1170105412_20170318.rec\",\"recordDownloadUrl\":\"\",\"serverTimestamp\":1490710856,\"activeDocId\":666519474,\"activeDocCurPage\":1}",
"create_time": "2017-03-18T21:12:19.000Z"
}
}
}*/
if(ret&&ret.code==200){
try{
if(ret.returnData&&ret.returnData.data){
if(_callback) {
_callback(ret.returnData.data.info);
}
}
}catch (err){
if(_callback){
_callback();
}
}
}else {
if(_callback){
_callback();
}
}
})
.catch(err => {
loger.error(`AGOR-获取媒体录制信息-异常.状态码:${err}`);
if(_callback){
_callback();
}
});
}
}
Sass.prototype.SUCCESS = Sass.SUCCESS = 'Sass_success';
... ...
... ... @@ -180,7 +180,7 @@ class SystemConfig {
if (window.clientInformation.languages.length > 2) {
Sys.explorer = "chrome";
loger.log("chrome", Sys);
} else if (window.clientInformation.languages.length == 2&&versionNum<60) {
} else if (window.clientInformation.languages.length == 2&&versionNum<55) {
var _track = 'track' in document.createElement('track');
var webstoreKeysLength = window.chrome && window.chrome.webstore ? Object.keys(window.chrome.webstore).length : 0;
if (_track) {
... ...
... ... @@ -110,6 +110,7 @@ ApeConsts.MEDIA_TYPE_DEFAULT = 0; //没有类型
ApeConsts.MEDIA_TYPE_VIDEO = 1; //视频流(包含音频)
ApeConsts.MEDIA_TYPE_AUDIO = 2; //音频流
ApeConsts.MEDIA_TYPE_SHARE = 3; //屏幕共享
ApeConsts.MEDIA_TYPE_EXTERNAL_LINK = 4; //外部推流地址
//return返回值状态
ApeConsts.RETURN_SUCCESS = 0; //成功
... ...
... ... @@ -684,7 +684,7 @@ class DocApe extends Ape {
let tempDocItemIdx;//临时记录文档数据,用于显示默认文档
for (let key in this.docList) {
tempDocItemIdx = this.docList[key];
if (tempDocItemIdx) {
if (tempDocItemIdx&&tempDocItemIdx.fileType!="video") {
loger.log("选择一个文档作为默认文档显示->", tempDocItemIdx);
let paramInfo = {
"itemIdx": tempDocItemIdx.itemIdx,
... ... @@ -763,6 +763,13 @@ class DocApe extends Ape {
docModelPdu.showType = _param.showType || 0;//文档显示模式
docModelPdu.animationStep = _param.animationStep || 1;//当前页面上的动画步数(动态ppt时有这个字段)
//loger.log(docModelPdu);
//新增的外部流数据,
docModelPdu.publishUrl = _param.rtmpUrl||"";
docModelPdu.rtmpUrl = _param.rtmpUrl||"";
docModelPdu.m3u8Url = _param.m3u8Url||"";
docModelPdu.replay = _param.replay||"";
return docModelPdu;
}
... ...
... ... @@ -138,6 +138,24 @@ class ShareApe extends Emiter {
this.shareScreen.startConnect(this.fullIpPort);
}
}
/*
* 推送外部流地址
* */
publishExternalLink(_result) {
/* return {"code": ApeConsts.RETURN_SUCCESS,
"data":"",
"mediaId":shareChannel,
"publishUrl": publishUrl,
"streamId":streamId,
"port":""
};*/
clearTimeout(this.reConnectTimer);
//if (_result) {
// this.publishUrl = _result.publishUrl || '';
// this.streamId = _result.streamId || '';
//}
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_SUCCESS,_result);
}
//屏幕共享推流,如果没有连接需要先建立连接
publish(_result) {
... ...
... ... @@ -254,7 +254,7 @@ class VideoApe extends Ape {
this.stopPublishVideo(_data)
}
}
//==========================屏幕共享=========================================================================
//-----------------------屏幕共享-----------------------
//屏幕共享连接打开
onPublishScreenShareFaile() {
... ... @@ -291,8 +291,8 @@ class VideoApe extends Ape {
}
//监听屏幕共享发布成功
onPublishScreenShareSuccess() {
loger.log('屏幕共享推流成功之后才能更新同步消息->');
onPublishScreenShareSuccess(data) {
loger.log('屏幕共享推流成功之后才能更新同步消息->',data);
//屏幕共享推流成功之后才能更新同步消息
let channelInfo = this.shareApe.getPublishChannelInfo();
this.sendTableUpdateHandler(channelInfo);
... ... @@ -337,14 +337,48 @@ class VideoApe extends Ape {
let channelInfo = this.shareApe.getDefaultChannelInfo();
channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
this.sendTableUpdateHandler(channelInfo);
this.shareApe.stopPublish();
}
}
//-----------------------屏幕共享 end-----------------------
//-----------------------推送和停止外部流地址----------------
//推送外部流地址
publishExternalLink(_param) {
loger.log('推送外部流地址->',_param);
//屏幕共享推流成功之后才能更新同步消息
let channelInfo = this.shareApe.getPublishChannelInfo();
channelInfo.mediaType = ApeConsts.MEDIA_TYPE_EXTERNAL_LINK;//外部推流地址
//如果
if(_param){
channelInfo.publishUrl=_param.rtmpUrl||"";//推流拉流地址一样
channelInfo.m3u8Url=_param.m3u8Url||"";
channelInfo.rtmpUrl=_param.rtmpUrl||"";
channelInfo.replay=_param.replay||"";
}
this.sendTableUpdateHandler(channelInfo);
}
//=============================屏幕共享 end=================================================
//停止推送外部流地址
stopPublishExternalLink(_param) {
loger.log('停止推送外部流地址->', _param);
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//只有老师能停止屏幕共享
if (GlobalConfig.isHost||GlobalConfig.isAssistant||GlobalConfig.isPresenter) {
let channelInfo = this.shareApe.getDefaultChannelInfo();
channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.mediaType=ApeConsts.MEDIA_TYPE_EXTERNAL_LINK;
this.sendTableUpdateHandler(channelInfo);
//调用停止的时候自己的也要停止,同步的消息不会再发给自己
this._emit(MessageTypes.SCREEN_SHARE_STOP, channelInfo);
}
}
//-----------------------推送和停止外部流地址END-------------
//释放nodeId占用的指定的channelId频道
_releaseChannelForNodeId(nodeId, channelId) {
loger.log(nodeId, "停止-->channelId", channelId);
... ... @@ -609,11 +643,14 @@ class VideoApe extends Ape {
unpackChannelInfo.streamId = "";
}
//屏幕共享的流不保存
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE && unpackChannelInfo.channelId > 0) {
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE &&
unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_EXTERNAL_LINK &&
unpackChannelInfo.channelId > 0) {
this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
}
if (unpackChannelInfo && unpackChannelInfo.fromNodeId != GlobalConfig.nodeId) {
//数据存在并且不是自己发送的消息,或者是外部设置的播放地址
if (unpackChannelInfo && (unpackChannelInfo.fromNodeId != GlobalConfig.nodeId||unpackChannelInfo.mediaType== ApeConsts.MEDIA_TYPE_EXTERNAL_LINK)) {
let receiveChannelInfo = {};
receiveChannelInfo.mediaId = unpackChannelInfo.channelId;
receiveChannelInfo.fromNodeId = unpackChannelInfo.fromNodeId;
... ... @@ -639,6 +676,7 @@ class VideoApe extends Ape {
"type": "m3u8",
"streamId": unpackChannelInfo.streamId
});
//如果接收的消息中已经有拉流地址,优先使用
if(unpackChannelInfo.m3u8Url){
m3u8Stream.playUrl=unpackChannelInfo.m3u8Url;
... ... @@ -646,6 +684,9 @@ class VideoApe extends Ape {
if(unpackChannelInfo.rtmpUrl){
rtmpStream.playUrl=unpackChannelInfo.rtmpUrl;
}
if(unpackChannelInfo.replay){
replay.playUrl=unpackChannelInfo.replay;
}
if (m3u8Stream.code == 0) {
... ... @@ -658,7 +699,9 @@ class VideoApe extends Ape {
receiveChannelInfo.replay = replay.playUrl;
}
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE) {
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE&&
unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_EXTERNAL_LINK
) {
//广播播放视频的消息
loger.log("VIDEO_PLAY", receiveChannelInfo);
this._emit(MessageTypes.VIDEO_PLAY, receiveChannelInfo);
... ... @@ -669,7 +712,9 @@ class VideoApe extends Ape {
}
} else {
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE) {
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE&&
unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_EXTERNAL_LINK
) {
//停止播放视频
loger.log("VIDEO_STOP", receiveChannelInfo);
this._emit(MessageTypes.VIDEO_STOP, receiveChannelInfo);
... ... @@ -679,7 +724,6 @@ class VideoApe extends Ape {
loger.log("SCREEN_SHARE_STOP", receiveChannelInfo);
this._emit(MessageTypes.SCREEN_SHARE_STOP, receiveChannelInfo);
} else {
loger.log("停止播放视频->channelId=0->不合法的id", receiveChannelInfo);
}
}
... ... @@ -697,7 +741,9 @@ class VideoApe extends Ape {
}
//更新用户的摄像头和麦克风状态
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE) {
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE&&
unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_EXTERNAL_LINK
) {
//非屏幕共享的情况下才更新状态
this._emit(MessageTypes.USER_DEVICE_STATUS_CHAANGE, {
nodeId: GlobalConfig.nodeId,
... ... @@ -709,7 +755,9 @@ class VideoApe extends Ape {
});
}
}
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE) {
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE&&
unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_EXTERNAL_LINK
) {
//非屏幕共享情况的处理
MediaModule.allMediaChannelsList[itemIdx] = unpackChannelInfo;
console.log('MediaModule.allMediaChannelsList', MediaModule.allMediaChannelsList);
... ... @@ -798,6 +846,7 @@ class VideoApe extends Ape {
packPduModel.streamId = _param.streamId || "";
packPduModel.m3u8Url=_param.m3u8Url || "";
packPduModel.rtmpUrl=_param.rtmpUrl || "";
packPduModel.replay=_param.replay || "";
packPduModel.siteId = _param.siteId || GlobalConfig.siteId;//GlobalConfig.siteId;
packPduModel.classId = parseInt(_param.classId) || parseInt(GlobalConfig.classId);
... ...
... ... @@ -743,7 +743,10 @@ message RCDocSendDataModelPdu {
optional uint32 show_type=19;//文档显示模式
optional uint32 animation_step=20 [default =1];//当前页码的动画步数
optional bool isFullScreen=21 ;//是否全屏显示
optional string publishUrl=22;
optional string rtmpUrl=23;
optional string m3u8Url=24;
optional string replay=25;
}
message RCMediaSharedSendDataModelPdu {
... ... @@ -855,6 +858,7 @@ message RCVideoChannelInfoPdu {
optional string optionJsonData =16;//其他参数的json对象
optional string m3u8Url =17;//m3u8拉流地址
optional string rtmpUrl =18;//rtmp拉流地址
optional string replay =19;//回放的拉流地址
}
message RCVideoChannelInfoRecordPdu {
... ...