diff --git a/src/EngineEntrance.js b/src/EngineEntrance.js index 048d473..d5d5830 100644 --- a/src/EngineEntrance.js +++ b/src/EngineEntrance.js @@ -62,7 +62,7 @@ export default class MessageEntrance extends Emiter { constructor() { super(); //sdk 信息 - GlobalConfig.sdkVersion = "v2.9.3.20170919"; + GlobalConfig.sdkVersion = "v2.10.4.20170920"; loger.warn("sdkVersion:" + GlobalConfig.sdkVersion); //设置 @@ -147,6 +147,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)); _chat_ape = new ChatApe(); _chat_ape.on('*', (type, data) => this._emit(type, data)); @@ -1359,6 +1360,22 @@ export default class MessageEntrance extends Emiter { loger.log('课堂状态发生改变,需要停止当前的所有推流'); this._emit(MessageTypes.MEDIA_STOP_PUBLISH); } + //用更状态数据发送变更 + _onRosterUpdateHandler(_data){ + //数据无效/ios/android 不处理数据 + if(!_data||GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){ + return; + } + let nodeData=_data.nodeData; + //数据用户是pc或H5不处理 + if(!nodeData||nodeData.deviceType==0||nodeData.deviceType==3){ + return; + } + if(nodeData.openCamera>0&&_webRtc){ + loger.log("收到移动端用户数据更新,当前是开启摄像头状态,需要尝试添加一个远程视频"); + _webRtc.tryAddMobileStream(_data.nodeId); + } + } //手动切换MS -> {ip;"xxx.xx.xx","port":"xxxx"} _switchMediaServer(_param) { @@ -1742,7 +1759,7 @@ export default class MessageEntrance extends Emiter { GlobalConfig.className = _data.meetingName || ""; GlobalConfig.classBeginTime = _data.beginTime || ""; GlobalConfig.classEndTime = _data.endTime || ""; - + GlobalConfig.channelId = ""+GlobalConfig.siteId+"_"+GlobalConfig.classId; //sdk获取ip失败就使用saas返回的 if(!GlobalConfig.userIp){ GlobalConfig.userIp = _data.userIp || ""; diff --git a/src/RecordPlayBackParse.js b/src/RecordPlayBackParse.js index 1019afa..e5a7e5c 100644 --- a/src/RecordPlayBackParse.js +++ b/src/RecordPlayBackParse.js @@ -33,6 +33,7 @@ class RecordPlayBackParse extends Emiter { this._recordPlaybackMaxTime = 0;//录制回放的总时间 this._isReady = false;//录制回放是否已经准备完成 this._apes = {}; + this._videoApeBroadcastMssages={};//视频模块的广播消息 this.mediaChannleList={}; this._conferApeMssages = {};//会议数据 this._chatApeMssages = {};//聊天数据 @@ -134,7 +135,7 @@ class RecordPlayBackParse extends Emiter { pduMsg.type = PduType.RCPDU_SEND_DATA_REQUEST; pduType = PduType.RCPDU_SEND_DATA_REQUEST; } - //loger.log('pduType', pduType); + loger.log('解析和储存->pduType', pduType); switch (pduType) { case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE: //加入课堂请求返回数据处理 @@ -160,7 +161,7 @@ class RecordPlayBackParse extends Emiter { let ape = this._apes[pduMsg.sessionId]; let sessionLabel = ApeConsts(pduMsg.sessionId); //只做解析存储,不对外发送 - //loger.log('解析数据-timestamp->', timestamp, 'sessionId->', pduMsg.sessionId, 'sessionLabel->', sessionLabel); + loger.log('解析数据-timestamp->', timestamp, 'sessionId->', pduMsg.sessionId, 'sessionLabel->', sessionLabel,"subType:"+pduMsg.subType); switch (pduMsg.sessionId) { case ApeConsts.CONFERENCE_SESSION_ID: this.saveParseData(data, timestamp, this._conferApeMssages); @@ -375,7 +376,7 @@ class RecordPlayBackParse extends Emiter { console.log('文档数据',this._docApeMssages); console.log('白板数据',this._whiteApeMssages); console.log('聊天数据',this._chatApeMssages); - + console.log('视频模块广播消息',this._videoApeBroadcastMssages); loger.log("录制回放数据解析完成,录制回放的总时间长为->", this._recordPlaybackMaxTime,"recordTimestamp:"+GlobalConfig.recordTimestamp); this._emit(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, {"recordPlaybackMaxTime": this._recordPlaybackMaxTime}); } @@ -638,9 +639,16 @@ class RecordPlayBackParse extends Emiter { regItemSize = regItems.length; }catch (err){ - console.warn('RCAdapterPdu->unpack-error->type类型不对') + console.warn('RCAdapterPdu->unpack-error->type类型不对'); + try { + let sendDataPdu = pdu['RCVideoSendDataRequestPdu'].decode(regBuffer); + console.log("RCVideoSendDataRequestPdu",sendDataPdu); + }catch (err){ + + } return; } + for (var i = 0; i < regItemSize; ++i) { let regItem = regItems[i]; let regItemType = regItem.type; @@ -707,6 +715,28 @@ class RecordPlayBackParse extends Emiter { let tableDeleteData = pdu['RCRegistryTableDeleteItemPdu'].decode(user_data); //console.log("tableDeleteData",object_id,tableDeleteData); break; + case pdu.RCPDU_SEND_VIDEO_DATA_REQUEST: + //视频模块的控制消息 + try{ + let videoReceivePdu = pdu['RCVideoSendDataRequestPdu'].decode(user_data); + if (videoReceivePdu == null) { + loger.warn("视频控制消息处理,收到的消息为null,不做处理"); + return; + } + videoReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(videoReceivePdu.data, 2);//开头两个字会乱码 + let dataObj = {}; + try { + dataObj = JSON.parse(videoReceivePdu.data); + } catch (err) { + loger.warn('控制消息->JSON转换失败'); + dataObj = videoReceivePdu.data; + } + videoReceivePdu.data = dataObj; + this._videoApeBroadcastMssages[timestamp]={parseData:videoReceivePdu,byteData:data,timestamp: timestamp}; + }catch (err){ + loger.warn("RCPDU_SEND_VIDEO_DATA_REQUEST->err",err); + } + break; case pdu.RCPDU_REG_TABLE_UPDATE_PDU: let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data); let tableUpdateItems = tableUpdateData.items; diff --git a/src/SystemConfig.js b/src/SystemConfig.js index 2f69a91..ecc3035 100644 --- a/src/SystemConfig.js +++ b/src/SystemConfig.js @@ -30,7 +30,7 @@ class SystemConfig { } if (mdetect.isAndroid()) { GlobalConfig.platform = "android"; //"android"; - GlobalConfig.deviceType = 2; //"ios"; + GlobalConfig.deviceType = 2; //"android"; } //语言 diff --git a/src/apes/WebRtcApe.js b/src/apes/WebRtcApe.js index cd8b1f6..1f54c3d 100644 --- a/src/apes/WebRtcApe.js +++ b/src/apes/WebRtcApe.js @@ -35,6 +35,8 @@ class WebRtcApe extends Emiter { this.curCameraId = ""; this.curMicrophoneId = ""; + this.remoteVideoList={};//记录远程视频流 + this.videoResolution = "240P"; this.isOpenVideo = true; @@ -138,6 +140,10 @@ class WebRtcApe extends Emiter { }); this.client.on('stream-subscribed', (evt)=> { let stream = evt.stream; + this.addRemoetStreamView(stream); + }); + /* this.client.on('stream-subscribed', (evt)=> { + let stream = evt.stream; if(stream){ //let viewDiv=`<div id="${this.xdyRemote + stream.getId()}" style="width:${this.hostRemoteVideoWidth}px;height:${this.hostRemoteVideoHeight}px;"></div>`; let uid=stream.getId(); @@ -148,6 +154,7 @@ class WebRtcApe extends Emiter { userName=user.name||""; userRole=user.userRole; } + let nameDiv=`<div style="width:98%;height:20px; position: absolute; z-index: 1;left: 4px;overflow:hidden;font-size: 14px; color: #cccccc;display:${this.nameDisplay}">${userName}</div>`; if(userRole==ApeConsts.invisible){ @@ -172,14 +179,21 @@ class WebRtcApe extends Emiter { stream.play(this.xdyRemote + stream.getId()); }catch (err){ } + if(user.deviceType==1||user.deviceType==2){ + this.remoteVideoList[user.nodeId]=stream; + } + console.log("移动端远程视频流集合->",this.remoteVideoList); } - }); + });*/ this.client.on('stream-removed', (evt)=> { let stream = evt.stream; - stream.stop(); - $('#' + this.xdyRemote + stream.getId()).remove(); - loger.log("远程视频流已经断开:" + stream.getId()); + if(stream){ + stream.stop(); + $('#' + this.xdyRemote + stream.getId()).remove(); + loger.log("远程视频流已经断开:" + stream.getId()); + } + }); this.client.on('peer-leave', (evt)=> { @@ -196,6 +210,48 @@ class WebRtcApe extends Emiter { }); } + addRemoetStreamView(stream){ + if(stream){ + //let viewDiv=`<div id="${this.xdyRemote + stream.getId()}" style="width:${this.hostRemoteVideoWidth}px;height:${this.hostRemoteVideoHeight}px;"></div>`; + let uid=stream.getId(); + let user=GlobalConfig.getUserInfoFromeNodeId(uid); + let userName=""; + let userRole="" + if(user){ + userName=user.name||""; + userRole=user.userRole; + } + let nameDiv=`<div style="width:98%;height:20px; position: absolute; z-index: 1;left: 4px;overflow:hidden;font-size: 14px; color: #cccccc;display:${this.nameDisplay}">${userName}</div>`; + + if(userRole==ApeConsts.invisible){ + //把远程视频添加到监课列表 + loger.log("获取远程视频流成功->监课:"+userName+"->" + uid,new Date().getTime()); + let viewDiv=`<div id="${this.xdyRemote + uid}" style="width:${this.invisibleVideoWidth}px;height:${this.invisibleVideoHeight}px;float: left;margin-right: 1px;pointer-events: none;">${nameDiv}</div>`; + $(this.invisibleViewId).append(viewDiv); + }else if(userRole==ApeConsts.host){ + //把远程视图添加到老师列表 + loger.log("获取远程视频流成功->老师:"+userName+"->" + uid,new Date().getTime()); + let viewDiv=`<div id="${this.xdyRemote + uid}" style="width:${this.hostRemoteVideoWidth}px;height:${this.hostRemoteVideoHeight}px;float: left;margin-right: 1px;pointer-events: none;">${nameDiv}</div>`; + $(this.hostRemoteViewId).append(viewDiv); + }else { + //把视图添加到学生列表 + loger.log("获取远程视频流成功->学生:"+userName+"->" +uid,new Date().getTime()); + let viewDiv=`<div id="${this.xdyRemote + uid}" style="width:${this.normalRemoteVideoWidth}px;height:${this.normalRemoteVideoHeight}px;float: left;margin-right: 1px;pointer-events: none;">${nameDiv}</div>`; + $(this.normalRemoteViewId).append(viewDiv); + } + //播放视频,隐藏控制条 + try{ + $("bar_"+stream.getId()).hide(); + stream.play(this.xdyRemote + stream.getId()); + }catch (err){ + } + if(user.deviceType==1||user.deviceType==2){ + this.remoteVideoList[user.nodeId]=stream; + } + console.log("移动端远程视频流集合->",this.remoteVideoList); + } + } + //重新添加远程视频 reAddRemoteStream(_stream){ if(!_stream){ @@ -215,7 +271,6 @@ class WebRtcApe extends Emiter { return; } if(err=="PEERCONNECTION_FAILED"){ - //this.reAddRemoteStreamDelay=setTimeout(()=>{ setTimeout(()=>{ loger.warn("连接远程的流失败->尝试重新连接",err); this.reAddRemoteStream(_stream); @@ -224,6 +279,23 @@ class WebRtcApe extends Emiter { loger.warn("添加一个远程视频流->失败", err); } }); } + //尝试添加远程的移动设备视频流 + tryAddMobileStream(nodeId){ + let stream=this.remoteVideoList[nodeId]; + if(!stream){ + return; + } + let remoteView=document.getElementById(this.xdyRemote +nodeId) + console.log("remoteView->",remoteView) + if(remoteView){ + loger.log(nodeId+" 流已经添加显示,不需要再处理"); + return; + } + if(stream) { + loger.log("收到移动端推流的消息,主动添加一个远程视频流"); + this.addRemoetStreamView(stream); + } + } joinChannel(_params) { this.channelId = _params.channelId||"";