From 27da8aa21d1246dce97e8384f0b239d369a8a948 Mon Sep 17 00:00:00 2001 From: liyong <liyong@3mang.com> Date: Thu, 26 Oct 2017 19:00:41 +0800 Subject: [PATCH] 1.新增添加和删除外部流地址的接口;2.新增的外部流地址数据显示和储存按文档数据处理;type类型为video,可以删除;3.文档数据模块增加4个流地址字段; --- src/EngineEntrance.js | 904 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/Sass.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/SystemConfig.js | 2 +- src/apes/ApeConsts.js | 1 + src/apes/DocApe.js | 9 ++++++++- src/apes/ShareApe.js | 18 ++++++++++++++++++ src/apes/VideoApe.js | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ src/pdus/pro.js | 6 +++++- 8 files changed, 694 insertions(+), 387 deletions(-) diff --git a/src/EngineEntrance.js b/src/EngineEntrance.js index 49030e8..b918b90 100644 --- a/src/EngineEntrance.js +++ b/src/EngineEntrance.js @@ -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; } diff --git a/src/Sass.js b/src/Sass.js index c52f254..e5697c2 100644 --- a/src/Sass.js +++ b/src/Sass.js @@ -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'; diff --git a/src/SystemConfig.js b/src/SystemConfig.js index e0baa18..23510b6 100644 --- a/src/SystemConfig.js +++ b/src/SystemConfig.js @@ -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) { diff --git a/src/apes/ApeConsts.js b/src/apes/ApeConsts.js index 1f24497..694f84f 100644 --- a/src/apes/ApeConsts.js +++ b/src/apes/ApeConsts.js @@ -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; //成功 diff --git a/src/apes/DocApe.js b/src/apes/DocApe.js index 461ef42..85a8e82 100644 --- a/src/apes/DocApe.js +++ b/src/apes/DocApe.js @@ -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; } diff --git a/src/apes/ShareApe.js b/src/apes/ShareApe.js index d5fdf83..f24afb5 100644 --- a/src/apes/ShareApe.js +++ b/src/apes/ShareApe.js @@ -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) { diff --git a/src/apes/VideoApe.js b/src/apes/VideoApe.js index 692b972..d292537 100644 --- a/src/apes/VideoApe.js +++ b/src/apes/VideoApe.js @@ -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); diff --git a/src/pdus/pro.js b/src/pdus/pro.js index 40612d4..550f824 100644 --- a/src/pdus/pro.js +++ b/src/pdus/pro.js @@ -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 { -- libgit2 0.24.0