李勇

1.增加控制礼物发送的功能;2.修复录制回放rec文件中消息时间戳重复叠加的问题;修复课堂中音视频频道被占用导致无法推流回放时缺少视频的问题

此 diff 太大无法显示。
@@ -63,7 +63,7 @@ export default class MessageEntrance extends Emiter { @@ -63,7 +63,7 @@ export default class MessageEntrance extends Emiter {
63 super(); 63 super();
64 this.lastClassActiveTime=0;//最后一次课堂激活的时间戳 64 this.lastClassActiveTime=0;//最后一次课堂激活的时间戳
65 //sdk 信息 65 //sdk 信息
66 - GlobalConfig.sdkVersion = "v2.36.11.20171204"; 66 + GlobalConfig.sdkVersion = "v2.36.8.20171206";
67 loger.warn("sdkVersion:" + GlobalConfig.sdkVersion); 67 loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
68 console.log("sdkVersion:" + GlobalConfig.sdkVersion); 68 console.log("sdkVersion:" + GlobalConfig.sdkVersion);
69 //设置 69 //设置
@@ -213,6 +213,8 @@ export default class MessageEntrance extends Emiter { @@ -213,6 +213,8 @@ export default class MessageEntrance extends Emiter {
213 this.kickOutRosterFormNodeId = this._kickOutRosterFormNodeId.bind(this); //把指定nodeId的人踢出课堂 213 this.kickOutRosterFormNodeId = this._kickOutRosterFormNodeId.bind(this); //把指定nodeId的人踢出课堂
214 this.sendThridChannelMessage = this._sendThridChannelMessage.bind(this);//通道第三方消息通道发送消息 214 this.sendThridChannelMessage = this._sendThridChannelMessage.bind(this);//通道第三方消息通道发送消息
215 this.changeDrawStatus = this._changeDrawStatus.bind(this);//切换绘制状态 215 this.changeDrawStatus = this._changeDrawStatus.bind(this);//切换绘制状态
  216 + this.changeGiftStatus = this._changeGiftStatus.bind(this);//切换送礼物状态
  217 +
216 218
217 //录制回放 219 //录制回放
218 this.initRecordPlayback = this._initRecordPlayback.bind(this); 220 this.initRecordPlayback = this._initRecordPlayback.bind(this);
@@ -735,7 +737,7 @@ export default class MessageEntrance extends Emiter { @@ -735,7 +737,7 @@ export default class MessageEntrance extends Emiter {
735 GlobalConfig.md5 = _data.md5 || ""; //这个暂时用假数据,后台接口写完就有数据了 737 GlobalConfig.md5 = _data.md5 || ""; //这个暂时用假数据,后台接口写完就有数据了
736 GlobalConfig.msType = _data.msType || 1; 738 GlobalConfig.msType = _data.msType || 1;
737 GlobalConfig.siteId = _data.siteId || ""; 739 GlobalConfig.siteId = _data.siteId || "";
738 - GlobalConfig.classType = _data.meetingType || ApeConsts.CLASS_TYPE_1v1; 740 + GlobalConfig.classType = _data.meetingType|| ApeConsts.CLASS_TYPE_1v1;
739 741
740 //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的 742 //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
741 GlobalConfig.passwordRequired = _data.passwordRequired || false; //md5验证的时候需要Sass返回的值,不能更改 743 GlobalConfig.passwordRequired = _data.passwordRequired || false; //md5验证的时候需要Sass返回的值,不能更改
@@ -1654,12 +1656,22 @@ export default class MessageEntrance extends Emiter { @@ -1654,12 +1656,22 @@ export default class MessageEntrance extends Emiter {
1654 loger.warn(GlobalConfig.getCurrentStatus()); 1656 loger.warn(GlobalConfig.getCurrentStatus());
1655 return; 1657 return;
1656 } 1658 }
1657 -  
1658 if (_confer_ape) { 1659 if (_confer_ape) {
1659 _confer_ape.changeDrawStatus(_param); 1660 _confer_ape.changeDrawStatus(_param);
1660 } 1661 }
1661 } 1662 }
1662 1663
  1664 + //控制课堂全局是否可送礼物的状态
  1665 + _changeGiftStatus(_param) {
  1666 + if (!_mcu.connected) {
  1667 + loger.warn(GlobalConfig.getCurrentStatus());
  1668 + return;
  1669 + }
  1670 + if (_confer_ape) {
  1671 + _confer_ape.changeGiftStatus(_param);
  1672 + }
  1673 + }
  1674 +
1663 //暂停上课 1675 //暂停上课
1664 _sendPauseClass(_param) { 1676 _sendPauseClass(_param) {
1665 if (!_mcu.connected) { 1677 if (!_mcu.connected) {
@@ -91,6 +91,7 @@ class GlobalConfig { @@ -91,6 +91,7 @@ class GlobalConfig {
91 classStatusInfo.classBeginTime = this.classBeginTime; //课堂创建的时间,这个是Sass返回的 91 classStatusInfo.classBeginTime = this.classBeginTime; //课堂创建的时间,这个是Sass返回的
92 classStatusInfo.classEndTime = this.classEndTime; //课堂结束的时间,这个是Sass返回的 92 classStatusInfo.classEndTime = this.classEndTime; //课堂结束的时间,这个是Sass返回的
93 93
  94 + classStatusInfo.isEnableGift = this.isEnableGift;
94 classStatusInfo.isEnableDraw = this.isEnableDraw; //当前是否开启绘制权限 95 classStatusInfo.isEnableDraw = this.isEnableDraw; //当前是否开启绘制权限
95 classStatusInfo.recordStatus = this.recordStatus; //当前录制状态 96 classStatusInfo.recordStatus = this.recordStatus; //当前录制状态
96 classStatusInfo.silence = this.silence; //当前课堂禁言状态 97 classStatusInfo.silence = this.silence; //当前课堂禁言状态
@@ -130,8 +131,8 @@ class GlobalConfig { @@ -130,8 +131,8 @@ class GlobalConfig {
130 this.className = data.className; 131 this.className = data.className;
131 } 132 }
132 133
133 - if (!this.classType) {  
134 - this.classType = data.classType; 134 + if (data.classType) {
  135 + this.classType = parseInt(data.classType);
135 } 136 }
136 if (!this.classBeginTime) { 137 if (!this.classBeginTime) {
137 this.classBeginTime = data.classBeginTime; //课堂创建的时间,这个是Sass返回的 138 this.classBeginTime = data.classBeginTime; //课堂创建的时间,这个是Sass返回的
@@ -155,6 +156,7 @@ class GlobalConfig { @@ -155,6 +156,7 @@ class GlobalConfig {
155 this.currentSceneTableId = data.currentSceneTableId || 0; //文档区域的模块显示 156 this.currentSceneTableId = data.currentSceneTableId || 0; //文档区域的模块显示
156 157
157 this.isEnableDraw = data.isEnableDraw || false;//是否开启所有人的绘制权限 158 this.isEnableDraw = data.isEnableDraw || false;//是否开启所有人的绘制权限
  159 + this.isEnableGift = data.isEnableGift || false;
158 this.videoScale = parseInt(data.videoScale) || 1; 160 this.videoScale = parseInt(data.videoScale) || 1;
159 // 全局禁言状态 161 // 全局禁言状态
160 this.silence = data.silence || false; 162 this.silence = data.silence || false;
@@ -634,6 +636,7 @@ GlobalConfig.classJoinSuccess = false; //是否已经加入课堂 @@ -634,6 +636,7 @@ GlobalConfig.classJoinSuccess = false; //是否已经加入课堂
634 GlobalConfig.recordPlaybackMaxTime = 0; //录制回放的总时间 636 GlobalConfig.recordPlaybackMaxTime = 0; //录制回放的总时间
635 GlobalConfig.recordStatus = false; //当前录制状态 637 GlobalConfig.recordStatus = false; //当前录制状态
636 GlobalConfig.isEnableDraw = false; //当前所有人是否开启绘制状态(老师除外) 638 GlobalConfig.isEnableDraw = false; //当前所有人是否开启绘制状态(老师除外)
  639 +GlobalConfig.isEnableGift = false; //当前所有人是否开启送礼物状态
637 GlobalConfig.silence = false; //当前课堂禁言状态 640 GlobalConfig.silence = false; //当前课堂禁言状态
638 GlobalConfig.silenceUsers = {}; //当前课堂用户禁言状态 641 GlobalConfig.silenceUsers = {}; //当前课堂用户禁言状态
639 GlobalConfig.selfSilence = {}; //当前课堂禁言状态 642 GlobalConfig.selfSilence = {}; //当前课堂禁言状态
@@ -108,12 +108,14 @@ MessageTypes.WEB_RTC_INIT_SUCCESS = "web_rtc_init_success"; @@ -108,12 +108,14 @@ MessageTypes.WEB_RTC_INIT_SUCCESS = "web_rtc_init_success";
108 MessageTypes.WEB_RTC_INIT_FAILED = "web_rtc_init_failed"; 108 MessageTypes.WEB_RTC_INIT_FAILED = "web_rtc_init_failed";
109 MessageTypes.WEB_RTC_JOIN_SUCCESS = "web_rtc_join_success"; 109 MessageTypes.WEB_RTC_JOIN_SUCCESS = "web_rtc_join_success";
110 MessageTypes.WEB_RTC_JOIN_FAILED = "web_rtc_join_failed"; 110 MessageTypes.WEB_RTC_JOIN_FAILED = "web_rtc_join_failed";
  111 +MessageTypes.WEB_RTC_LEAVE_CHANNEL = "web_rtc_leave_channel";//离开频道
111 MessageTypes.WEB_RTC_PUBLISH_FAILED = "web_rtc_publish_failed"; 112 MessageTypes.WEB_RTC_PUBLISH_FAILED = "web_rtc_publish_failed";
112 MessageTypes.GET_DEVICES_SUCCESS = "get_devices_success"; 113 MessageTypes.GET_DEVICES_SUCCESS = "get_devices_success";
113 MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE = "media_publish_status_change";//音视频推流的状态发生改变 114 MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE = "media_publish_status_change";//音视频推流的状态发生改变
114 MessageTypes.MEDIA_ENABLED_CHANGE = "media_enabled_change";//媒体禁用或开启状态改变 115 MessageTypes.MEDIA_ENABLED_CHANGE = "media_enabled_change";//媒体禁用或开启状态改变
115 MessageTypes.RECEIVE_MEDIA_ENABLED_CHANGE = "receive_media_enabled_change";//收到媒体禁用状态控制的消息 116 MessageTypes.RECEIVE_MEDIA_ENABLED_CHANGE = "receive_media_enabled_change";//收到媒体禁用状态控制的消息
116 117
  118 +
117 //MCU MS 119 //MCU MS
118 MessageTypes.SWITCH_MCU_IP = "switch_mcu_ip"; //切换mcu 重新选点 120 MessageTypes.SWITCH_MCU_IP = "switch_mcu_ip"; //切换mcu 重新选点
119 MessageTypes.SWITCH_MS_IP = "switch_ms_ip"; //切换ms 重新选点 121 MessageTypes.SWITCH_MS_IP = "switch_ms_ip"; //切换ms 重新选点
@@ -25,22 +25,22 @@ class RecordInfoMatch extends Emiter { @@ -25,22 +25,22 @@ class RecordInfoMatch extends Emiter {
25 } 25 }
26 26
27 start(_recordMessagesList) { 27 start(_recordMessagesList) {
28 - this.recordMessagesList=_recordMessagesList; 28 + this.recordMessagesList = _recordMessagesList;
29 let serverIp = GlobalConfig.recordFileSever || "playbak.xuedianyun.com:8080"; 29 let serverIp = GlobalConfig.recordFileSever || "playbak.xuedianyun.com:8080";
30 this.filePath = `${GlobalConfig.locationProtocol + serverIp}`; 30 this.filePath = `${GlobalConfig.locationProtocol + serverIp}`;
31 31
32 - if(GlobalConfig.locationProtocol=="https://"){  
33 - this.filePath=this.filePath.replace(":8080",""); 32 + if (GlobalConfig.locationProtocol == "https://") {
  33 + this.filePath = this.filePath.replace(":8080", "");
34 } 34 }
35 35
36 - if (!_recordMessagesList||_recordMessagesList.length<1) { 36 + if (!_recordMessagesList || _recordMessagesList.length < 1) {
37 console.log("没有视频消息", _recordMessagesList); 37 console.log("没有视频消息", _recordMessagesList);
38 this.matchRecordFile(this.recordMessages, this.m3u8jsonDataList); 38 this.matchRecordFile(this.recordMessages, this.m3u8jsonDataList);
39 } 39 }
40 40
41 //this.getRecordInfo(()=> { 41 //this.getRecordInfo(()=> {
42 - this.parseRecordMessage(_recordMessagesList,()=> {  
43 - console.log("JSON数据列表",this.jsonPathList); 42 + this.parseRecordMessage(_recordMessagesList, ()=> {
  43 + console.log("JSON数据列表", this.jsonPathList);
44 let requestLen = Object.keys(this.jsonPathList).length; 44 let requestLen = Object.keys(this.jsonPathList).length;
45 let currentLen = 0; 45 let currentLen = 0;
46 let fileNameArr; 46 let fileNameArr;
@@ -115,7 +115,7 @@ class RecordInfoMatch extends Emiter { @@ -115,7 +115,7 @@ class RecordInfoMatch extends Emiter {
115 }) 115 })
116 .then(ret => { 116 .then(ret => {
117 loger.log('AG-获取媒体录制信息-完成'); 117 loger.log('AG-获取媒体录制信息-完成');
118 - this.parseRecordMessage(ret.returnData.data,_callback); 118 + this.parseRecordMessage(ret.returnData.data, _callback);
119 /* for (let i = 0; i < ret.returnData.data.length; i++) { 119 /* for (let i = 0; i < ret.returnData.data.length; i++) {
120 let item = ret.returnData.data[i]; 120 let item = ret.returnData.data[i];
121 if (item.status == 1) { 121 if (item.status == 1) {
@@ -150,13 +150,13 @@ class RecordInfoMatch extends Emiter { @@ -150,13 +150,13 @@ class RecordInfoMatch extends Emiter {
150 }); 150 });
151 } 151 }
152 152
153 - parseRecordMessage(_data,_callback){  
154 - if(!_data||_data.length<1){  
155 - console.log("录制消息数据无效",_data) 153 + parseRecordMessage(_data, _callback) {
  154 + if (!_data || _data.length < 1) {
  155 + console.log("录制消息数据无效", _data)
156 return; 156 return;
157 } 157 }
158 - for (let i = 0; i <_data.length; i++) {  
159 - let item =_data[i]; 158 + for (let i = 0; i < _data.length; i++) {
  159 + let item = _data[i];
160 if (item.status == 1) { 160 if (item.status == 1) {
161 this.streamInfoLen++; 161 this.streamInfoLen++;
162 //console.log(JSON.stringify(item)); 162 //console.log(JSON.stringify(item));
@@ -250,7 +250,7 @@ class RecordInfoMatch extends Emiter { @@ -250,7 +250,7 @@ class RecordInfoMatch extends Emiter {
250 console.log("_recordMessages", _recordMessages); 250 console.log("_recordMessages", _recordMessages);
251 console.log("_m3u8jsonDataList", _m3u8jsonDataList); 251 console.log("_m3u8jsonDataList", _m3u8jsonDataList);
252 console.log("最终匹配完成的数量为->" + Object.keys(this.matchStreams).length); 252 console.log("最终匹配完成的数量为->" + Object.keys(this.matchStreams).length);
253 - console.log("没有录制文件的用户", this.unMatchUid); 253 + console.error("没有录制文件的用户", this.unMatchUid);
254 this._emit(RecordInfoMatch.RECORD_INFO_MATCH_COMPLETE, this.matchStreams); 254 this._emit(RecordInfoMatch.RECORD_INFO_MATCH_COMPLETE, this.matchStreams);
255 } 255 }
256 256
@@ -271,6 +271,7 @@ class RecordInfoMatch extends Emiter { @@ -271,6 +271,7 @@ class RecordInfoMatch extends Emiter {
271 return parseInt(a.creatTimeUTC) - parseInt(b.creatTimeUTC); 271 return parseInt(a.creatTimeUTC) - parseInt(b.creatTimeUTC);
272 }); 272 });
273 273
  274 +
274 if (uidRecordInfoArr.length == uidRecordFileArr.length && uidRecordFileArr.length > 0) { 275 if (uidRecordInfoArr.length == uidRecordFileArr.length && uidRecordFileArr.length > 0) {
275 //1.如果文件数量和消息数量相等,直接关联即可 276 //1.如果文件数量和消息数量相等,直接关联即可
276 console.log(k + "->数量相同->直接匹配", uidRecordInfoArr.length); 277 console.log(k + "->数量相同->直接匹配", uidRecordInfoArr.length);
@@ -285,11 +286,12 @@ class RecordInfoMatch extends Emiter { @@ -285,11 +286,12 @@ class RecordInfoMatch extends Emiter {
285 for (let f in uidRecordInfo) { 286 for (let f in uidRecordInfo) {
286 let time = parseInt(uidRecordInfo[f].creatTimeUTC); 287 let time = parseInt(uidRecordInfo[f].creatTimeUTC);
287 let video_url = ""; 288 let video_url = "";
  289 + //A.精确匹配
288 let video_urlObj = uidRecordFile[k + "_" + time]; 290 let video_urlObj = uidRecordFile[k + "_" + time];
289 if (video_urlObj && video_urlObj.video_url) { 291 if (video_urlObj && video_urlObj.video_url) {
290 video_url = video_urlObj.video_url; 292 video_url = video_urlObj.video_url;
291 } 293 }
292 - //模糊 294 + //B.模糊匹配-前后相差10秒左右
293 if (!video_url) { 295 if (!video_url) {
294 video_urlObj = uidRecordFile[k + "_" + (time + 1)]; 296 video_urlObj = uidRecordFile[k + "_" + (time + 1)];
295 if (video_urlObj && video_urlObj.video_url) { 297 if (video_urlObj && video_urlObj.video_url) {
@@ -302,7 +304,6 @@ class RecordInfoMatch extends Emiter { @@ -302,7 +304,6 @@ class RecordInfoMatch extends Emiter {
302 video_url = video_urlObj.video_url; 304 video_url = video_urlObj.video_url;
303 } 305 }
304 } 306 }
305 -  
306 //通过时间戳匹配 结束 307 //通过时间戳匹配 结束
307 if (video_url) { 308 if (video_url) {
308 let item = uidRecordInfo[f]; 309 let item = uidRecordInfo[f];
@@ -318,12 +319,34 @@ class RecordInfoMatch extends Emiter { @@ -318,12 +319,34 @@ class RecordInfoMatch extends Emiter {
318 console.log(k + "->数量不同 消息数量:" + uidRecordInfoArr.length, "视频数量:" + uidRecordFileArr.length); 319 console.log(k + "->数量不同 消息数量:" + uidRecordInfoArr.length, "视频数量:" + uidRecordFileArr.length);
319 //按消息的数量大于视频数量处理 320 //按消息的数量大于视频数量处理
320 let lastVideoFileItem;//记录最后一个 321 let lastVideoFileItem;//记录最后一个
321 - for (let h = 0; h < uidRecordInfoArr.length; h++) {  
322 - let infoItem = uidRecordInfoArr[h]; 322 + for (let s = 0; s < uidRecordInfoArr.length; s++) {
  323 + if(s==0){
  324 + let infoItem = uidRecordInfoArr[s];
  325 + let videoFileItem = uidRecordFileArr[s];
  326 + infoItem.video_url = videoFileItem.video_url;
  327 + //如果之前没有匹配到才设置
  328 + if (!this.matchStreams[infoItem.stream_id]) {
  329 + this.matchStreams[infoItem.stream_id] = infoItem;
  330 + }
  331 + }else {
  332 + let infoItem = JSON.stringify(uidRecordInfoArr[s]);
  333 + infoItem=JSON.parse(infoItem);
  334 + console.log("查找->",s,uidRecordInfoArr);
  335 + let videoFileItem=this.getNearestTimeData(infoItem.creatTimeUTC,uidRecordFileArr);
  336 + if(videoFileItem){
  337 + infoItem.video_url = videoFileItem.video_url;
  338 + infoItem.seek=videoFileItem.seek;
  339 + //如果之前没有匹配到才设置
  340 + if (!this.matchStreams[infoItem.stream_id]) {
  341 + this.matchStreams[infoItem.stream_id] = infoItem;
  342 + }
  343 + }
  344 +
  345 + }
  346 + /*let infoItem = uidRecordInfoArr[h];
323 let videoFileItem = uidRecordFileArr[h]; 347 let videoFileItem = uidRecordFileArr[h];
324 if (videoFileItem) { 348 if (videoFileItem) {
325 infoItem.video_url = videoFileItem.video_url; 349 infoItem.video_url = videoFileItem.video_url;
326 -  
327 //如果之前没有匹配到才设置 350 //如果之前没有匹配到才设置
328 if (!this.matchStreams[infoItem.stream_id]) { 351 if (!this.matchStreams[infoItem.stream_id]) {
329 this.matchStreams[infoItem.stream_id] = infoItem; 352 this.matchStreams[infoItem.stream_id] = infoItem;
@@ -337,48 +360,44 @@ class RecordInfoMatch extends Emiter { @@ -337,48 +360,44 @@ class RecordInfoMatch extends Emiter {
337 this.matchStreams[infoItem.stream_id] = infoItem; 360 this.matchStreams[infoItem.stream_id] = infoItem;
338 } 361 }
339 } 362 }
  363 + }*/
340 } 364 }
341 -  
342 } 365 }
343 } 366 }
344 -  
345 - /*  
346 - //没有查找到之后,如果两次推流的消息时间过短,只会有一个视频,需要再次匹配  
347 - console.log("uidRecordInfoUnsearch", uidRecordInfoUnsearch, uidRecordInfo);  
348 - if (Object.keys(uidRecordInfoUnsearch).length > 0) {  
349 - let item;  
350 - let item2;  
351 - let minInterval = 10000;  
352 - let nearItem = null;  
353 - for (let s in uidRecordInfoUnsearch) {  
354 - item = uidRecordInfoUnsearch[s];  
355 - for (let h in uidRecordInfo) {  
356 - item2 = uidRecordInfo[h];  
357 - if (item2 && item2.video_url) {  
358 - let interval = parseInt((item.creatTime) * 0.001 - parseInt(item2.creatTime) * 0.001);  
359 - if (minInterval > interval) {  
360 - nearItem = item2;  
361 - minInterval = interval;  
362 - }  
363 - minInterval = Math.min(minInterval, interval);  
364 - //console.log("两次推流消息的间隔",interval);  
365 - }  
366 - }  
367 - }  
368 - if (item && nearItem) {  
369 - console.log("查找到最接近的消息", nearItem, "seek", minInterval);  
370 - item.video_url = nearItem.video_url;  
371 - item.seek = minInterval;  
372 - matchStreams[item.stream_id] = item;  
373 - }  
374 -  
375 - }*/  
376 } 367 }
377 } 368 }
378 369
  370 + /*
  371 + * 根据时间获取间隔最短的的数据
  372 + * */
  373 + getNearestTimeData(time,videoArr){
  374 + let _time=parseInt(time);
  375 + let _nearstTimeDistance=100000;//默认设置为一个超长的值
  376 + let nearstTimeItem=null;
  377 + for(let k=0;k<videoArr.length;k++){
  378 + //计算最近时间
  379 + let interval=_time-parseInt(videoArr[k].creatTimeUTC);
  380 + console.log("getNearestTimeData",interval,_time,k,videoArr[k].creatTimeUTC);
  381 + if(interval>-12&&interval<_nearstTimeDistance){
  382 + //记录时间点最接近
  383 + nearstTimeItem=videoArr[k];
  384 + nearstTimeItem.seek=interval;
  385 + _nearstTimeDistance=Math.abs(_nearstTimeDistance);
  386 + }
  387 + }
  388 +
  389 + let itemJson="";
  390 + if(nearstTimeItem){
  391 + itemJson=JSON.stringify(nearstTimeItem);
  392 + let finelItem=JSON.parse(itemJson);
  393 + finelItem.seek=_time-parseInt(finelItem.creatTimeUTC);
  394 + console.log("nearstTimeItem->",finelItem);
  395 + return finelItem;
  396 + }
  397 + console.log("nearstTimeItem->没有找到数据");
  398 + return null
379 } 399 }
380 400
381 -  
382 timestampToUTCTime(_timestamp) { 401 timestampToUTCTime(_timestamp) {
383 let date = new Date(_timestamp - 8 * 60 * 60 * 1000);//GMT 转UTC 减8 402 let date = new Date(_timestamp - 8 * 60 * 60 * 1000);//GMT 转UTC 减8
384 let y = "" + date.getFullYear(); 403 let y = "" + date.getFullYear();
@@ -32,6 +32,7 @@ class RecordPlayBackParse extends Emiter { @@ -32,6 +32,7 @@ class RecordPlayBackParse extends Emiter {
32 parseBuffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); 32 parseBuffer = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
33 parseBuffer.clear(); 33 parseBuffer.clear();
34 this._recordPlaybackTimestamp = 0;//回放的时间 34 this._recordPlaybackTimestamp = 0;//回放的时间
  35 + this.lastParseTime=0;
35 this._recordPlaybackMaxTime = 0;//录制回放的总时间 36 this._recordPlaybackMaxTime = 0;//录制回放的总时间
36 this._isReady = false;//录制回放是否已经准备完成 37 this._isReady = false;//录制回放是否已经准备完成
37 this.isLoadTxRecordInfo = false;//是否已经加载TXY的录制数据 38 this.isLoadTxRecordInfo = false;//是否已经加载TXY的录制数据
@@ -42,6 +43,9 @@ class RecordPlayBackParse extends Emiter { @@ -42,6 +43,9 @@ class RecordPlayBackParse extends Emiter {
42 this.videoPublishMessages=[];//记录推流控制的消息 43 this.videoPublishMessages=[];//记录推流控制的消息
43 this._videoApeBroadcastMssages = {};//视频模块的广播消息 44 this._videoApeBroadcastMssages = {};//视频模块的广播消息
44 this.mediaChannleList = {}; 45 this.mediaChannleList = {};
  46 + this.conferApeUnPackMssages = {};//人员数据按时间戳记录数据
  47 + this.allRosterList = {};//记录所有人员数据
  48 +
45 this._conferApeMssages = {};//会议数据 49 this._conferApeMssages = {};//会议数据
46 this._chatApeMssages = {};//聊天数据 50 this._chatApeMssages = {};//聊天数据
47 this._videoApeMssages = {};//视频数据 51 this._videoApeMssages = {};//视频数据
@@ -140,7 +144,7 @@ class RecordPlayBackParse extends Emiter { @@ -140,7 +144,7 @@ class RecordPlayBackParse extends Emiter {
140 let pduMsg = pdu.decode_pdu(data); 144 let pduMsg = pdu.decode_pdu(data);
141 let pduType = pduMsg.get("type"); 145 let pduType = pduMsg.get("type");
142 let pduData = pduMsg.get("data"); 146 let pduData = pduMsg.get("data");
143 - 147 + //console.log("REC->timestamp:"+timestamp,"pduType:"+pduType);
144 //*************非常重要****************** 148 //*************非常重要******************
145 //客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端, 149 //客户端发送的所有125消息,MCU收到之后会痛120把消息返回给客户端,
146 //所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的 150 //所以需要把125消息type转换为120,因为MCU在录制的时候是直接录制客户端发送的消息而不是MCU转换之后的
@@ -178,6 +182,11 @@ class RecordPlayBackParse extends Emiter { @@ -178,6 +182,11 @@ class RecordPlayBackParse extends Emiter {
178 switch (pduMsg.sessionId) { 182 switch (pduMsg.sessionId) {
179 case ApeConsts.CONFERENCE_SESSION_ID: 183 case ApeConsts.CONFERENCE_SESSION_ID:
180 this.saveParseData(data, timestamp, this._conferApeMssages); 184 this.saveParseData(data, timestamp, this._conferApeMssages);
  185 +
  186 + //不处理广播消息,只处理同步消息
  187 + if(pduMsg.subType!=ApeConsts.RCPDU_SEND_CONFERENCE_DATA_REQUEST){
  188 + this.unPackpduRegAdapterHandler(pduMsg.data, timestamp, data, ApeConsts.CONFERENCE_SESSION_ID, pduMsg.subType);
  189 + }
181 break; 190 break;
182 case ApeConsts.CHAT_SESSION_ID: 191 case ApeConsts.CHAT_SESSION_ID:
183 this.saveParseData(data, timestamp, this._chatApeMssages); 192 this.saveParseData(data, timestamp, this._chatApeMssages);
@@ -197,7 +206,7 @@ class RecordPlayBackParse extends Emiter { @@ -197,7 +206,7 @@ class RecordPlayBackParse extends Emiter {
197 case ApeConsts.VIDEO_SESSION_ID: 206 case ApeConsts.VIDEO_SESSION_ID:
198 this.saveParseData(data, timestamp, this._videoApeMssages); 207 this.saveParseData(data, timestamp, this._videoApeMssages);
199 this.unpackVideoBroadcastMessage(pduMsg, timestamp, data); 208 this.unpackVideoBroadcastMessage(pduMsg, timestamp, data);
200 - this.unPackpduRegAdapterHandler(pduMsg.data, timestamp, data, ApeConsts.VIDEO_SESSION_ID, pduMsg.subType) 209 + this.unPackpduRegAdapterHandler(pduMsg.data, timestamp, data, ApeConsts.VIDEO_SESSION_ID, pduMsg.subType);
201 break; 210 break;
202 case ApeConsts.AUDIO_SESSION_ID: 211 case ApeConsts.AUDIO_SESSION_ID:
203 this.saveParseData(data, timestamp, this._audioApeMssages); 212 this.saveParseData(data, timestamp, this._audioApeMssages);
@@ -280,9 +289,9 @@ class RecordPlayBackParse extends Emiter { @@ -280,9 +289,9 @@ class RecordPlayBackParse extends Emiter {
280 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._mediaShareApeMssages, "mediaShareApe"); 289 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._mediaShareApeMssages, "mediaShareApe");
281 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._musicShareApeMssages, "musicShareApe"); 290 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._musicShareApeMssages, "musicShareApe");
282 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._whiteApeMssages, "whiteApe"); 291 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._whiteApeMssages, "whiteApe");
  292 + this._searchMessageFromTime(this._recordPlaybackTimestamp, this._videoApeBroadcastMssages, "videoApBroadcast");
283 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._videoApeMssages, "videoAp"); 293 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._videoApeMssages, "videoAp");
284 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._audioApeMssages, "audioApe"); 294 this._searchMessageFromTime(this._recordPlaybackTimestamp, this._audioApeMssages, "audioApe");
285 - this._searchMessageFromTime(this._recordPlaybackTimestamp, this._videoApeBroadcastMssages, "videoApBroadcast");  
286 } 295 }
287 296
288 //加载录制文件rec 297 //加载录制文件rec
@@ -745,11 +754,19 @@ class RecordPlayBackParse extends Emiter { @@ -745,11 +754,19 @@ class RecordPlayBackParse extends Emiter {
745 let byteData = parseBuffer.buffer.slice(position, (position + byteLen)); 754 let byteData = parseBuffer.buffer.slice(position, (position + byteLen));
746 position += byteLen; 755 position += byteLen;
747 756
  757 + if(this._recordPlaybackMaxTime>timestamp){
  758 + loger.warn("脚本录制文件中的数据时间戳重叠了!!!!",this._recordPlaybackMaxTime,timestamp,"相差:"+this._recordPlaybackMaxTime-timestamp);
  759 + if( this.lastParseTime==0){
  760 + this.lastParseTime=this._recordPlaybackMaxTime;
  761 + this.lastParseTimeDistance=(this._recordPlaybackMaxTime-timestamp)*2;
  762 + }
  763 + timestamp= this.lastParseTime+timestamp;
  764 + }
  765 + //记录最后一个数据的时间戳作为整个录制回放的总时间戳
  766 + this._recordPlaybackMaxTime = Math.max(this._recordPlaybackMaxTime,timestamp);
  767 +
748 //按时间戳解保存数据 768 //按时间戳解保存数据
749 this._parseSaveSocketMsgReceivedHandler(byteData, timestamp); 769 this._parseSaveSocketMsgReceivedHandler(byteData, timestamp);
750 -  
751 - //记录最后一个数据的时间戳作为整个录制回放的总时间戳  
752 - this._recordPlaybackMaxTime = timestamp;  
753 } 770 }
754 this._recordPlaybackTimestamp = 0; 771 this._recordPlaybackTimestamp = 0;
755 this._isReady = true; 772 this._isReady = true;
@@ -776,6 +793,8 @@ class RecordPlayBackParse extends Emiter { @@ -776,6 +793,8 @@ class RecordPlayBackParse extends Emiter {
776 console.log('视频模块广播消息', this._videoApeBroadcastMssages); 793 console.log('视频模块广播消息', this._videoApeBroadcastMssages);
777 loger.log("录制回放数据解析完成,录制回放的总时间长为->", this._recordPlaybackMaxTime, "recordTimestamp:" + GlobalConfig.recordTimestamp); 794 loger.log("录制回放数据解析完成,录制回放的总时间长为->", this._recordPlaybackMaxTime, "recordTimestamp:" + GlobalConfig.recordTimestamp);
778 console.log('videoPublishMessages', this.videoPublishMessages); 795 console.log('videoPublishMessages', this.videoPublishMessages);
  796 + console.log('conferApeUnPackMssages', this.conferApeUnPackMssages);
  797 + console.log('allRosterList', this.allRosterList);
779 798
780 //AGO启动录制消息和文件匹配 799 //AGO启动录制消息和文件匹配
781 this.recordInfoMatch.start(this.videoPublishMessages); 800 this.recordInfoMatch.start(this.videoPublishMessages);
@@ -805,12 +824,12 @@ class RecordPlayBackParse extends Emiter { @@ -805,12 +824,12 @@ class RecordPlayBackParse extends Emiter {
805 return {"code": ApeConsts.RETURN_FAILED, "data": "录制回放还未准备完成"}; 824 return {"code": ApeConsts.RETURN_FAILED, "data": "录制回放还未准备完成"};
806 } 825 }
807 loger.log("classStatusInfo", GlobalConfig.classStatusInfo); 826 loger.log("classStatusInfo", GlobalConfig.classStatusInfo);
808 - console.log("所有流ID", this.allStreams);  
809 - for (let i in this.allStreams) {  
810 - if (MediaModule.streams[i]) {  
811 - console.log("匹配成功的流:" + i, MediaModule.streams[i]); 827 + console.log("所有流ID-videoPublishMessages", this.videoPublishMessages);
  828 + for (let i of this.videoPublishMessages) {
  829 + if (MediaModule.streams[i.streamId]) {
  830 + //console.log("匹配成功的流:" + i, MediaModule.streams[i.streamId]);
812 } else { 831 } else {
813 - console.warn("未匹配成功的流:" + i); 832 + //console.warn("未匹配成功的流:" + i.streamId);
814 } 833 }
815 } 834 }
816 this._startTimerCounter(); 835 this._startTimerCounter();
@@ -866,10 +885,11 @@ class RecordPlayBackParse extends Emiter { @@ -866,10 +885,11 @@ class RecordPlayBackParse extends Emiter {
866 */ 885 */
867 886
868 //先查广播消息再查频道消息,频道消息在广播消息之后 887 //先查广播消息再查频道消息,频道消息在广播消息之后
  888 + //音视频模块的查找规则和其他模块不一样,音视频按频道查找,如果课堂内存在多个频道,都要查
  889 + this.searchMediaApeMessageKeyfram(this.mediaChannleList);
  890 +
869 //视频广播消息 891 //视频广播消息
870 this.searchVideoBroadcastMessageKeyfram(this._videoApeBroadcastMssages); 892 this.searchVideoBroadcastMessageKeyfram(this._videoApeBroadcastMssages);
871 - //音视频模块的查找规则和其他模块不一样,音视频按频道查找,如果课堂内存在多个频道,都要查  
872 - //this.searchMediaApeMessageKeyfram(this.mediaChannleList);  
873 893
874 894
875 //媒体共享模块 895 //媒体共享模块
@@ -930,7 +950,7 @@ class RecordPlayBackParse extends Emiter { @@ -930,7 +950,7 @@ class RecordPlayBackParse extends Emiter {
930 messageItem = channelInfos[i]; 950 messageItem = channelInfos[i];
931 if (messageItem) { 951 if (messageItem) {
932 keyFrameSeekTime = (this._recordPlaybackTimestamp - i); 952 keyFrameSeekTime = (this._recordPlaybackTimestamp - i);
933 - loger.log("频道:" + k + "->SEEK->查找音视频模块数据->", messageItem, 'keyFrameSeekTime->', keyFrameSeekTime) 953 + loger.log("频道:" + k + "->SEEK->查找音视频模块数据->", messageItem, 'keyFrameSeekTime->')
934 this._everSocketMsgReceivedHandler(messageItem.byteData, keyFrameSeekTime); 954 this._everSocketMsgReceivedHandler(messageItem.byteData, keyFrameSeekTime);
935 break; 955 break;
936 } 956 }
@@ -954,9 +974,12 @@ class RecordPlayBackParse extends Emiter { @@ -954,9 +974,12 @@ class RecordPlayBackParse extends Emiter {
954 for (let i = this._recordPlaybackTimestamp; i > 0; i--) { 974 for (let i = this._recordPlaybackTimestamp; i > 0; i--) {
955 messageItem = nodeIdVideoBrodcast[i]; 975 messageItem = nodeIdVideoBrodcast[i];
956 if (messageItem) { 976 if (messageItem) {
  977 + //根据时间戳查找到音视频广播消息,需要判断当前是否有频道消息,不能重复
  978 + if(!this.hasVideoChannelMessage(i)){
957 keyFrameSeekTime = (this._recordPlaybackTimestamp - i); 979 keyFrameSeekTime = (this._recordPlaybackTimestamp - i);
958 loger.log("nodeId:" + k + "->SEEK->查找音视频模块广播数据->", messageItem, 'keyFrameSeekTime->', keyFrameSeekTime) 980 loger.log("nodeId:" + k + "->SEEK->查找音视频模块广播数据->", messageItem, 'keyFrameSeekTime->', keyFrameSeekTime)
959 this._everSocketMsgReceivedHandler(messageItem.byteData, keyFrameSeekTime); 981 this._everSocketMsgReceivedHandler(messageItem.byteData, keyFrameSeekTime);
  982 + }
960 break; 983 break;
961 } 984 }
962 } 985 }
@@ -964,7 +987,16 @@ class RecordPlayBackParse extends Emiter { @@ -964,7 +987,16 @@ class RecordPlayBackParse extends Emiter {
964 } 987 }
965 } 988 }
966 } 989 }
967 - 990 + hasVideoChannelMessage(_time){
  991 + for (let k in this.mediaChannleList) {
  992 + let channelInfos = this.mediaChannleList[k];
  993 + let messageItem = channelInfos[_time];
  994 + if(messageItem){
  995 + return true;
  996 + }
  997 + }
  998 + return false;
  999 + }
968 //媒体共享模块查找关键帧时间戳的消息 1000 //媒体共享模块查找关键帧时间戳的消息
969 searchMediaShareApeMessageKeyfram(_apeMessages) { 1001 searchMediaShareApeMessageKeyfram(_apeMessages) {
970 if (!_apeMessages) { 1002 if (!_apeMessages) {
@@ -1132,7 +1164,46 @@ class RecordPlayBackParse extends Emiter { @@ -1132,7 +1164,46 @@ class RecordPlayBackParse extends Emiter {
1132 console.log("视频模块广播消息->解析失败", err.message); 1164 console.log("视频模块广播消息->解析失败", err.message);
1133 } 1165 }
1134 } 1166 }
  1167 + /*
  1168 + * 根据用户的userId userName userRole 获取nodeId
  1169 + * */
  1170 + getNodeIdFromUserInfo(userInfo){
  1171 + return userInfo.nodeId||userInfo.fromNodeId;
  1172 + if(!userInfo) {
  1173 + console.error("根据用户的userId userName userRole 获取nodeId 失败->传入的参数无效",userInfo);
  1174 + return 0;
  1175 + }
  1176 + let user=null;
  1177 + //全匹配 nodeId+userName+userId
  1178 + for (let k in this.allRosterList){
  1179 + user= this.allRosterList[k];
  1180 + if(user){
  1181 + if(user.userId==userInfo.userId&&
  1182 + user.name==userInfo.userName&&
  1183 + user.nodeId==userInfo.nodeId
  1184 + ){
  1185 + //名字和userId相同就可以返回,角色身份暂时不用(XXXXXXXXXXXXXXXX 老师的需要做处理,有一种情况就是userId和userName相同,nodeId不一样
  1186 + return user.nodeId;
  1187 + }
  1188 + }
  1189 + }
1135 1190
  1191 + //模糊匹配 nodeId+userName+userId
  1192 + for (let k in this.allRosterList){
  1193 + user= this.allRosterList[k];
  1194 + if(user){
  1195 + if(user.userId==userInfo.userId&&
  1196 + user.name==userInfo.userName
  1197 + ){
  1198 + //名字和userId相同就可以返回,角色身份暂时不用(XXXXXXXXXXXXXXXX 老师的需要做处理,有一种情况就是userId和userName相同,nodeId不一样
  1199 + return user.nodeId;
  1200 + }
  1201 + }
  1202 + }
  1203 +
  1204 + console.warn("根据用户的userId userName userRole 获取nodeId 失败->用户列表中找不到用户",userInfo);
  1205 + return userInfo.nodeId||userInfo.fromNodeId;
  1206 + }
1136 //音视频的数据需要解析,然后按频道储存数据 1207 //音视频的数据需要解析,然后按频道储存数据
1137 // 解析pdu RCAdapterPdu的数据: regBuffer(RCAdapterPdu数据),timestamp(时间戳), data(mcu的原始数据) sessionId(类型) 1208 // 解析pdu RCAdapterPdu的数据: regBuffer(RCAdapterPdu数据),timestamp(时间戳), data(mcu的原始数据) sessionId(类型)
1138 unPackpduRegAdapterHandler(regBuffer, timestamp, data, sessionId, subType) { 1209 unPackpduRegAdapterHandler(regBuffer, timestamp, data, sessionId, subType) {
@@ -1188,7 +1259,12 @@ class RecordPlayBackParse extends Emiter { @@ -1188,7 +1259,12 @@ class RecordPlayBackParse extends Emiter {
1188 break; 1259 break;
1189 case pdu.RCPDU_REG_ROSTER_DELETE_PDU: 1260 case pdu.RCPDU_REG_ROSTER_DELETE_PDU:
1190 let rosterDelData = pdu['RCRegistryRosterDeleteItemPdu'].decode(user_data); 1261 let rosterDelData = pdu['RCRegistryRosterDeleteItemPdu'].decode(user_data);
1191 - // console.log('RCRegistryRosterDeleteItemPdu',rosterDelData) 1262 + console.log('RCRegistryRosterDeleteItemPdu',rosterDelData);
  1263 +
  1264 + if(!this.conferApeUnPackMssages[rosterDelData.nodeId]){
  1265 + this.conferApeUnPackMssages[rosterDelData.nodeId]={};
  1266 + }
  1267 + this.conferApeUnPackMssages[rosterDelData.nodeId][timestamp]=rosterDelData;
1192 break; 1268 break;
1193 case pdu.RCPDU_REG_ROSTER_UPDATE_PDU: 1269 case pdu.RCPDU_REG_ROSTER_UPDATE_PDU:
1194 let rosterUpdateData = pdu['RCRegistryRosterUpdateItemPdu'].decode(user_data); 1270 let rosterUpdateData = pdu['RCRegistryRosterUpdateItemPdu'].decode(user_data);
@@ -1199,7 +1275,13 @@ class RecordPlayBackParse extends Emiter { @@ -1199,7 +1275,13 @@ class RecordPlayBackParse extends Emiter {
1199 let node = rosterUpdateItems[i]; 1275 let node = rosterUpdateItems[i];
1200 let nodeId = node.nodeId; 1276 let nodeId = node.nodeId;
1201 let nodeData = pdu['RCNodeInfoRecordPdu'].decode(node.nodeData); 1277 let nodeData = pdu['RCNodeInfoRecordPdu'].decode(node.nodeData);
1202 - // console.log('RCNodeInfoRecordPdu',nodeData) 1278 + //console.log('RCNodeInfoRecordPdu',nodeData);
  1279 + if(!this.conferApeUnPackMssages[nodeId]){
  1280 + this.conferApeUnPackMssages[nodeId]={};
  1281 + }
  1282 + this.conferApeUnPackMssages[nodeId][timestamp]=nodeData;
  1283 +
  1284 + this.allRosterList[nodeId]=nodeData;
1203 } 1285 }
1204 break; 1286 break;
1205 case pdu.RCPDU_REG_TABLE_INSERT_PDU: 1287 case pdu.RCPDU_REG_TABLE_INSERT_PDU:
@@ -1266,7 +1348,17 @@ class RecordPlayBackParse extends Emiter { @@ -1266,7 +1348,17 @@ class RecordPlayBackParse extends Emiter {
1266 //console.log("视频流" + videoChannelInfo.streamId); 1348 //console.log("视频流" + videoChannelInfo.streamId);
1267 if(videoChannelInfo){ 1349 if(videoChannelInfo){
1268 videoChannelInfo.channel=videoChannelInfo.siteId+"_"+videoChannelInfo.classId; 1350 videoChannelInfo.channel=videoChannelInfo.siteId+"_"+videoChannelInfo.classId;
  1351 +
  1352 + //音视频频道在课堂中会出现fromNodeId和推流者nodeId不一样的问题,需要检查和修复
  1353 + let matchNodeIdFromUserInfo=this.getNodeIdFromUserInfo(videoChannelInfo);
  1354 + if(videoChannelInfo.fromNodeId==matchNodeIdFromUserInfo){
1269 videoChannelInfo.uid=videoChannelInfo.fromNodeId; 1355 videoChannelInfo.uid=videoChannelInfo.fromNodeId;
  1356 + }else {
  1357 + console.error("推流者的nodeId和消息中的nodeId不一致,需要替换",videoChannelInfo.fromNodeId,"真实nodeId:"+matchNodeIdFromUserInfo);
  1358 + videoChannelInfo.fromNodeId=matchNodeIdFromUserInfo;
  1359 + videoChannelInfo.uid=matchNodeIdFromUserInfo;
  1360 + }
  1361 +
1270 let streamInfo=videoChannelInfo.streamId.split("_"); 1362 let streamInfo=videoChannelInfo.streamId.split("_");
1271 //kaifangwebrtc_1092942818_S8908_1510741823354 1363 //kaifangwebrtc_1092942818_S8908_1510741823354
1272 if(streamInfo&&streamInfo.length>1){ 1364 if(streamInfo&&streamInfo.length>1){
@@ -1274,9 +1366,8 @@ class RecordPlayBackParse extends Emiter { @@ -1274,9 +1366,8 @@ class RecordPlayBackParse extends Emiter {
1274 }else { 1366 }else {
1275 videoChannelInfo.creatTime=parseInt(videoChannelInfo.timestamp)*1000;//秒转换为毫秒 1367 videoChannelInfo.creatTime=parseInt(videoChannelInfo.timestamp)*1000;//秒转换为毫秒
1276 } 1368 }
1277 -  
1278 } 1369 }
1279 - //****1310721是屏幕共享和外部流 不需要匹配***** 1370 + //!****1310721是屏幕共享和外部流 不需要匹配*****
1280 if(parseInt(videoChannelInfo.channelId)<1310721){ 1371 if(parseInt(videoChannelInfo.channelId)<1310721){
1281 this.videoPublishMessages.push(videoChannelInfo); 1372 this.videoPublishMessages.push(videoChannelInfo);
1282 } 1373 }
@@ -431,6 +431,21 @@ class ConferApe extends Ape { @@ -431,6 +431,21 @@ class ConferApe extends Ape {
431 } 431 }
432 } 432 }
433 433
  434 + //全局送礼物权限控制
  435 + changeGiftStatus(params) {
  436 + loger.log("全局送礼物权限控制",params);
  437 + if (!GlobalConfig.isNormal) {
  438 + if (params && params.isEnableGift == true) {
  439 + GlobalConfig.isEnableGift = true;
  440 + } else {
  441 + GlobalConfig.isEnableGift = false;
  442 + }
  443 + this.sendUpdaterClassStatusInfo(params);
  444 + } else {
  445 + loger.warn('学生没有开启送礼物的权限');
  446 + }
  447 + }
  448 +
434 //控制指定用户的画笔状态 449 //控制指定用户的画笔状态
435 changeUserDrawStatus(_param) { 450 changeUserDrawStatus(_param) {
436 loger.log('控制指定用户的画笔状态->', _param); 451 loger.log('控制指定用户的画笔状态->', _param);
@@ -1251,6 +1266,7 @@ class ConferApe extends Ape { @@ -1251,6 +1266,7 @@ class ConferApe extends Ape {
1251 classStatusInfo.silence = GlobalConfig.silence; 1266 classStatusInfo.silence = GlobalConfig.silence;
1252 classStatusInfo.silenceUsers = JSON.stringify(GlobalConfig.silenceUsers); 1267 classStatusInfo.silenceUsers = JSON.stringify(GlobalConfig.silenceUsers);
1253 classStatusInfo.isEnableDraw = GlobalConfig.isEnableDraw; 1268 classStatusInfo.isEnableDraw = GlobalConfig.isEnableDraw;
  1269 + classStatusInfo.isEnableGift = GlobalConfig.isEnableGift;
1254 classStatusInfo.videoScale=GlobalConfig.videoScale||1; 1270 classStatusInfo.videoScale=GlobalConfig.videoScale||1;
1255 //loger.log("classStatusInfo--->", classStatusInfo); 1271 //loger.log("classStatusInfo--->", classStatusInfo);
1256 1272
@@ -599,9 +599,9 @@ class VideoApe extends Ape { @@ -599,9 +599,9 @@ class VideoApe extends Ape {
599 videoInfo=this.packVideoInfoAndSendToClient(videoData,seek); 599 videoInfo=this.packVideoInfoAndSendToClient(videoData,seek);
600 this._emit(MessageTypes.VIDEO_PLAY, videoInfo); 600 this._emit(MessageTypes.VIDEO_PLAY, videoInfo);
601 }else if(data.status==0){ 601 }else if(data.status==0){
602 - loger.log("停止播放文件->", videoData);  
603 - videoInfo=this.packVideoInfoAndSendToClient(videoData,seek);  
604 - this._emit(MessageTypes.VIDEO_STOP, videoInfo); 602 + // loger.log("停止播放文件->", videoData);
  603 + // videoInfo=this.packVideoInfoAndSendToClient(videoData,seek);
  604 + // this._emit(MessageTypes.VIDEO_STOP, videoInfo);
605 } 605 }
606 break; 606 break;
607 default: 607 default:
@@ -796,7 +796,7 @@ class VideoApe extends Ape { @@ -796,7 +796,7 @@ class VideoApe extends Ape {
796 packVideoInfoAndSendToClient(_param,seek){ 796 packVideoInfoAndSendToClient(_param,seek){
797 let mediaChannelInfo = {}; 797 let mediaChannelInfo = {};
798 mediaChannelInfo.mediaId = _param.channelId; 798 mediaChannelInfo.mediaId = _param.channelId;
799 - mediaChannelInfo.fromNodeId = _param.fromNodeId; 799 + mediaChannelInfo.fromNodeId = _param.fromNodeId||_param.nodeId||_param.uid;
800 mediaChannelInfo.userName = _param.userName || ""; 800 mediaChannelInfo.userName = _param.userName || "";
801 mediaChannelInfo.userRole = _param.userRole || ApeConsts.normal; 801 mediaChannelInfo.userRole = _param.userRole || ApeConsts.normal;
802 mediaChannelInfo.mediaType = _param.mediaType || ApeConsts.MEDIA_TYPE_DEFAULT; 802 mediaChannelInfo.mediaType = _param.mediaType || ApeConsts.MEDIA_TYPE_DEFAULT;
@@ -206,17 +206,17 @@ class WebRtcApe extends Emiter { @@ -206,17 +206,17 @@ class WebRtcApe extends Emiter {
206 let uid = evt.uid; 206 let uid = evt.uid;
207 let user = GlobalConfig.getUserInfoFromeNodeId(parseInt(uid)); 207 let user = GlobalConfig.getUserInfoFromeNodeId(parseInt(uid));
208 //console.log("active-speaker",user); 208 //console.log("active-speaker",user);
209 - if (user) { 209 + /* if (user) {
210 let roleRole = GlobalConfig.getUserRoleToString(user.role); 210 let roleRole = GlobalConfig.getUserRoleToString(user.role);
211 this.speakerList.push("当前正在讲话的 [" + roleRole + "] name:" + user.name + " uid:" + uid); 211 this.speakerList.push("当前正在讲话的 [" + roleRole + "] name:" + user.name + " uid:" + uid);
212 } else { 212 } else {
213 this.speakerList.push("当前正在讲话的uid:" + uid); 213 this.speakerList.push("当前正在讲话的uid:" + uid);
214 - }  
215 - //记录正在讲话的数据,大于50条上报一次 214 + }*/
  215 + /* //记录正在讲话的数据,大于50条上报一次
216 if(this.speakerList.length>20){ 216 if(this.speakerList.length>20){
217 loger.log(this.speakerList); 217 loger.log(this.speakerList);
218 this.speakerList=[]; 218 this.speakerList=[];
219 - } 219 + }*/
220 }); 220 });
221 221
222 } 222 }
@@ -454,7 +454,7 @@ class WebRtcApe extends Emiter { @@ -454,7 +454,7 @@ class WebRtcApe extends Emiter {
454 clearTimeout(this.rePublishDelay); 454 clearTimeout(this.rePublishDelay);
455 this.rePublishDelay = setTimeout(()=> { 455 this.rePublishDelay = setTimeout(()=> {
456 this.publish(); 456 this.publish();
457 - }, 200); 457 + }, 400);
458 } 458 }
459 }, (err)=> { 459 }, (err)=> {
460 loger.error("加入视频通话频道->失败->", err); 460 loger.error("加入视频通话频道->失败->", err);
@@ -484,6 +484,7 @@ class WebRtcApe extends Emiter { @@ -484,6 +484,7 @@ class WebRtcApe extends Emiter {
484 this.localStream.close(); 484 this.localStream.close();
485 this.localStream=null; 485 this.localStream=null;
486 }*/ 486 }*/
  487 + loger.log("获取本地视频流");
487 this.localStream = AgoraRTC.createStream({ 488 this.localStream = AgoraRTC.createStream({
488 streamID: this.uid, 489 streamID: this.uid,
489 audio: true, 490 audio: true,
@@ -507,6 +508,7 @@ class WebRtcApe extends Emiter { @@ -507,6 +508,7 @@ class WebRtcApe extends Emiter {
507 508
508 leaveChannel() { 509 leaveChannel() {
509 loger.log("调用离开视频通话频道->isPublish" + this.isPublish); 510 loger.log("调用离开视频通话频道->isPublish" + this.isPublish);
  511 + this._emit(MessageTypes.WEB_RTC_LEAVE_CHANNEL);
510 if (!this.client) { 512 if (!this.client) {
511 return; 513 return;
512 } 514 }
@@ -568,7 +570,7 @@ class WebRtcApe extends Emiter { @@ -568,7 +570,7 @@ class WebRtcApe extends Emiter {
568 } 570 }
569 571
570 publish(_params) { 572 publish(_params) {
571 - if (!this.client || !this.localStream) { 573 + if (!this.client) {
572 loger.warn("推流失败->未加入频道!"); 574 loger.warn("推流失败->未加入频道!");
573 return; 575 return;
574 } 576 }
@@ -677,10 +679,15 @@ class WebRtcApe extends Emiter { @@ -677,10 +679,15 @@ class WebRtcApe extends Emiter {
677 679
678 unpublish() { 680 unpublish() {
679 clearTimeout(this.rePublishDelay); 681 clearTimeout(this.rePublishDelay);
680 - loger.log("webRtc->停止推流 ", new Date().getTime());  
681 - if (!this.client || !this.localStream) { 682 + if (!this.client) {
  683 + loger.log("webRtc->停止推流失败->没有加入频道", new Date().getTime());
  684 + return;
  685 + }
  686 + if (!this.localStream) {
  687 + loger.log("webRtc->停止推流失败->没有本地视频流", new Date().getTime());
682 return; 688 return;
683 } 689 }
  690 + loger.log("webRtc->停止推流 ", new Date().getTime());
684 this.client.unpublish(this.localStream, (err)=> { 691 this.client.unpublish(this.localStream, (err)=> {
685 loger.log("webRtc->停止推流->失败" + err); 692 loger.log("webRtc->停止推流->失败" + err);
686 }); 693 });
@@ -31,6 +31,7 @@ const TYPE_LINE = 1;//直线 @@ -31,6 +31,7 @@ const TYPE_LINE = 1;//直线
31 const TYPE_RECT = 2;//矩形 31 const TYPE_RECT = 2;//矩形
32 const TYPE_CIRCLE = 3;//圆形 32 const TYPE_CIRCLE = 3;//圆形
33 const TYPE_TEXT = 4;//文本 33 const TYPE_TEXT = 4;//文本
  34 +const TYPE_ELLIPSE = 5;//椭圆
34 35
35 class WhiteBoardApe extends Ape { 36 class WhiteBoardApe extends Ape {
36 constructor() { 37 constructor() {
@@ -440,6 +441,9 @@ class WhiteBoardApe extends Ape { @@ -440,6 +441,9 @@ class WhiteBoardApe extends Ape {
440 case TYPE_CIRCLE: 441 case TYPE_CIRCLE:
441 whiteBoardModelPdu.radius = parseInt(parseFloat(_param.radius)*100);//外部传入的值有可能是小数,放大100倍,收到数据后再转换 442 whiteBoardModelPdu.radius = parseInt(parseFloat(_param.radius)*100);//外部传入的值有可能是小数,放大100倍,收到数据后再转换
442 break; 443 break;
  444 + case TYPE_ELLIPSE:
  445 + whiteBoardModelPdu.radius = parseInt(parseFloat(_param.radius)*100);//外部传入的值有可能是小数,放大100倍,收到数据后再转换
  446 + break;
443 case TYPE_TEXT: 447 case TYPE_TEXT:
444 whiteBoardModelPdu.fontSize = parseInt(parseFloat(_param.fontSize)*100);//外部传入的值有可能是小数,放大100倍,收到数据后再转换 448 whiteBoardModelPdu.fontSize = parseInt(parseFloat(_param.fontSize)*100);//外部传入的值有可能是小数,放大100倍,收到数据后再转换
445 whiteBoardModelPdu.fontName = _param.fontName || null; 449 whiteBoardModelPdu.fontName = _param.fontName || null;
@@ -1056,6 +1056,7 @@ message RCClassStatusInfoPdu { @@ -1056,6 +1056,7 @@ message RCClassStatusInfoPdu {
1056 optional string silenceUsers=25;//课堂用户禁言状态列表 1056 optional string silenceUsers=25;//课堂用户禁言状态列表
1057 optional bool isEnableDraw=26;//课堂用户是否开启绘制权限 1057 optional bool isEnableDraw=26;//课堂用户是否开启绘制权限
1058 optional uint32 videoScale=27;//视频显示的缩放倍数 1058 optional uint32 videoScale=27;//视频显示的缩放倍数
  1059 + optional bool isEnableGift=28;//是否开启送礼物权限
1059 } 1060 }
1060 1061
1061 message RCConferenceRecordRequestPdu { 1062 message RCConferenceRecordRequestPdu {