李勇

1.修复录制回放文件匹配;2.优化日志上报

@@ -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.26.9.20171107"; 66 + GlobalConfig.sdkVersion = "v2.27.11.20171109";
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 //设置
@@ -126,6 +126,7 @@ export default class MessageEntrance extends Emiter { @@ -126,6 +126,7 @@ export default class MessageEntrance extends Emiter {
126 _mcu.on('*', (type, data) => this._emit(type, data)); 126 _mcu.on('*', (type, data) => this._emit(type, data));
127 _mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this)); //加入MCU课堂完成 127 _mcu.on(MessageTypes.CLASS_JOIN_MCU_SUCCESS, this._mcuJoinMCUClassSuccessHandler.bind(this)); //加入MCU课堂完成
128 _mcu.on(MessageTypes.SWITCH_MCU_IP, this._switchMcuIpHandler.bind(this)); //切换MCU,重新选点 128 _mcu.on(MessageTypes.SWITCH_MCU_IP, this._switchMcuIpHandler.bind(this)); //切换MCU,重新选点
  129 + _mcu.on(MessageTypes.SOCKET_MAX_RECONNECT_FAILED, this._socketMaxReconnectFailed.bind(this)); //mcu断线重连已经达到最大次数,不再重连
129 130
130 //录制回放 131 //录制回放
131 _recordPlayback = RecordPlayBackParse; 132 _recordPlayback = RecordPlayBackParse;
@@ -445,9 +446,16 @@ export default class MessageEntrance extends Emiter { @@ -445,9 +446,16 @@ export default class MessageEntrance extends Emiter {
445 return; 446 return;
446 } 447 }
447 this._leaveClass(_type); 448 this._leaveClass(_type);
  449 + this._leaveChannel();
448 //记录是否已经离开课堂,离开之后不做MCU重连 450 //记录是否已经离开课堂,离开之后不做MCU重连
449 GlobalConfig.classExit=true; 451 GlobalConfig.classExit=true;
  452 + LogManager.sendLogToServer();
  453 + this._emit(MessageTypes.CLASS_EXIT, {type:6});
  454 + //2秒后停止日志上报
  455 + setTimeout(()=>{
450 LogManager.IS_OPEN_SEND_LOG = false;//断开之后不再上报日志 456 LogManager.IS_OPEN_SEND_LOG = false;//断开之后不再上报日志
  457 + },2000);
  458 +
451 } 459 }
452 460
453 //当前的课堂状态信息发生改变,需要保存课堂状态到Sass 461 //当前的课堂状态信息发生改变,需要保存课堂状态到Sass
@@ -1276,6 +1284,11 @@ export default class MessageEntrance extends Emiter { @@ -1276,6 +1284,11 @@ export default class MessageEntrance extends Emiter {
1276 } 1284 }
1277 } 1285 }
1278 1286
  1287 + //MCU已经达到最大重连次数,不在继续重连,需要退出课堂
  1288 + _socketMaxReconnectFailed(_param){
  1289 + //执行离开课堂的逻辑
  1290 + this._runClassExit();
  1291 + }
1279 //切换MCU ->_param->{reConnect:false} //reConnect(是否立即替换当前的ip并且重新连接) 1292 //切换MCU ->_param->{reConnect:false} //reConnect(是否立即替换当前的ip并且重新连接)
1280 _switchMcuIpHandler(_param) { 1293 _switchMcuIpHandler(_param) {
1281 if (GlobalConfig.isRecordPlayBack) { 1294 if (GlobalConfig.isRecordPlayBack) {
@@ -1718,13 +1731,6 @@ export default class MessageEntrance extends Emiter { @@ -1718,13 +1731,6 @@ export default class MessageEntrance extends Emiter {
1718 console.log("已经离开课堂",_param); 1731 console.log("已经离开课堂",_param);
1719 return; 1732 return;
1720 } 1733 }
1721 - //离开视频通话频道  
1722 - /* if(GlobalConfig.deviceType==0||GlobalConfig.deviceType==3){  
1723 - if(_webRtc){  
1724 - _webRtc.leaveChannel();  
1725 - }  
1726 - }*/  
1727 -  
1728 //停止推流 1734 //停止推流
1729 if (_video_ape) { 1735 if (_video_ape) {
1730 _video_ape.stopPublishVideo(); 1736 _video_ape.stopPublishVideo();
@@ -2541,7 +2547,7 @@ export default class MessageEntrance extends Emiter { @@ -2541,7 +2547,7 @@ export default class MessageEntrance extends Emiter {
2541 loger.log("文档加入频道成功->isHost=", GlobalConfig.isHost, "当前总人数:", GlobalConfig.rosterNumber, "sassDoclength=", GlobalConfig.docListPrepare.length); 2547 loger.log("文档加入频道成功->isHost=", GlobalConfig.isHost, "当前总人数:", GlobalConfig.rosterNumber, "sassDoclength=", GlobalConfig.docListPrepare.length);
2542 2548
2543 //如果当前课堂内只有自己或者离开上次课堂的时间大于8分钟,需要停止服务端的视频录制,设备不是H5 2549 //如果当前课堂内只有自己或者离开上次课堂的时间大于8分钟,需要停止服务端的视频录制,设备不是H5
2544 - if(GlobalConfig.rosterNumber<=1&&interval>=(8*60)&&GlobalConfig.deviceType!=3){ 2550 + if(GlobalConfig.rosterNumber<=1&&interval>=(6*60)&&GlobalConfig.deviceType!=3){
2545 loger.log("调用服务端音视频停止录制->interval:"+interval); 2551 loger.log("调用服务端音视频停止录制->interval:"+interval);
2546 this._mediaRecordControl({"status": WebRtcApe.RECORD_STATUS_2}); 2552 this._mediaRecordControl({"status": WebRtcApe.RECORD_STATUS_2});
2547 } 2553 }
@@ -3280,7 +3286,7 @@ export default class MessageEntrance extends Emiter { @@ -3280,7 +3286,7 @@ export default class MessageEntrance extends Emiter {
3280 if (!_params) { 3286 if (!_params) {
3281 return; 3287 return;
3282 } 3288 }
3283 - loger.log("设置appConfig"); 3289 + loger.log("设置appConfig",_params);
3284 if (GlobalConfig.appId) { 3290 if (GlobalConfig.appId) {
3285 loger.log("本地已经设置appConfig,不需要再设置"); 3291 loger.log("本地已经设置appConfig,不需要再设置");
3286 return; 3292 return;
@@ -3294,6 +3300,7 @@ export default class MessageEntrance extends Emiter { @@ -3294,6 +3300,7 @@ export default class MessageEntrance extends Emiter {
3294 GlobalConfig.stopRecordingInterfaces = _params.stopRecordingInterfaces || ""; 3300 GlobalConfig.stopRecordingInterfaces = _params.stopRecordingInterfaces || "";
3295 GlobalConfig.getTxRecordInfoInterfaces = _params.getTxRecordInfoInterfaces || ""; 3301 GlobalConfig.getTxRecordInfoInterfaces = _params.getTxRecordInfoInterfaces || "";
3296 GlobalConfig.getRecordFileURLAgoInterfaces = _params.getRecordFileURLAgoInterfaces || ""; 3302 GlobalConfig.getRecordFileURLAgoInterfaces = _params.getRecordFileURLAgoInterfaces || "";
  3303 + GlobalConfig.recordFileSever = _params.recordFileSever || "";
3297 3304
3298 //去掉协议头 3305 //去掉协议头
3299 try { 3306 try {
@@ -3313,7 +3320,10 @@ export default class MessageEntrance extends Emiter { @@ -3313,7 +3320,10 @@ export default class MessageEntrance extends Emiter {
3313 GlobalConfig.getRecordFileURLAgoInterfaces = GlobalConfig.getRecordFileURLAgoInterfaces.replace('http://', ""); 3320 GlobalConfig.getRecordFileURLAgoInterfaces = GlobalConfig.getRecordFileURLAgoInterfaces.replace('http://', "");
3314 GlobalConfig.getRecordFileURLAgoInterfaces = GlobalConfig.getRecordFileURLAgoInterfaces.replace('https://', ""); 3321 GlobalConfig.getRecordFileURLAgoInterfaces = GlobalConfig.getRecordFileURLAgoInterfaces.replace('https://', "");
3315 } 3322 }
3316 - 3323 + if (GlobalConfig.recordFileSever) {
  3324 + GlobalConfig.recordFileSever = GlobalConfig.recordFileSever.replace('http://', "");
  3325 + GlobalConfig.recordFileSever = GlobalConfig.recordFileSever.replace('https://', "");
  3326 + }
3317 if (GlobalConfig.stopRecordingInterfaces) { 3327 if (GlobalConfig.stopRecordingInterfaces) {
3318 GlobalConfig.stopRecordingInterfaces = GlobalConfig.stopRecordingInterfaces.replace('http://', ""); 3328 GlobalConfig.stopRecordingInterfaces = GlobalConfig.stopRecordingInterfaces.replace('http://', "");
3319 GlobalConfig.stopRecordingInterfaces = GlobalConfig.stopRecordingInterfaces.replace('https://', ""); 3329 GlobalConfig.stopRecordingInterfaces = GlobalConfig.stopRecordingInterfaces.replace('https://', "");
@@ -3325,8 +3335,6 @@ export default class MessageEntrance extends Emiter { @@ -3325,8 +3335,6 @@ export default class MessageEntrance extends Emiter {
3325 } catch (err) { 3335 } catch (err) {
3326 3336
3327 } 3337 }
3328 -  
3329 -  
3330 } 3338 }
3331 3339
3332 //录制状态控制和推流状态控制 3340 //录制状态控制和推流状态控制
@@ -15,12 +15,13 @@ @@ -15,12 +15,13 @@
15 import Emiter from 'Emiter'; 15 import Emiter from 'Emiter';
16 import Loger from 'Loger'; 16 import Loger from 'Loger';
17 import GlobalConfig from 'GlobalConfig'; 17 import GlobalConfig from 'GlobalConfig';
18 - 18 +import LogManager from 'LogManager';
19 let loger = Loger.getLoger('EverSocket'); 19 let loger = Loger.getLoger('EverSocket');
20 -const MCU_MAX_RECONNECTION = 4;//最多重连次数 20 +const MCU_MAX_RECONNECTION = 3;//最多重连次数
21 class EverSocket extends Emiter { 21 class EverSocket extends Emiter {
22 constructor() { 22 constructor() {
23 super(); 23 super();
  24 + this.mcuReconnectCounter=0;//(重要)记录mcu连续重连的次数,最大连续8次就不再重连
24 this._connected = false; 25 this._connected = false;
25 this._lastActiveTime = 0;//最后一次收到消息的时间 26 this._lastActiveTime = 0;//最后一次收到消息的时间
26 this._enableEverSocket = false; 27 this._enableEverSocket = false;
@@ -111,10 +112,17 @@ class EverSocket extends Emiter { @@ -111,10 +112,17 @@ class EverSocket extends Emiter {
111 this._clear(); 112 this._clear();
112 window.clearTimeout(this.reConnectionTimeout); 113 window.clearTimeout(this.reConnectionTimeout);
113 this.reConnectionCounter++; 114 this.reConnectionCounter++;
  115 + this.mcuReconnectCounter++;
114 if (this.reConnectionCounter > MCU_MAX_RECONNECTION) { 116 if (this.reConnectionCounter > MCU_MAX_RECONNECTION) {
115 - loger.warn('MCU断线重连->已经达到最大重连次数!'); 117 + if( this.mcuReconnectCounter>=MCU_MAX_RECONNECTION*2){
  118 + loger.warn('MCU断线重连->已经达到最大重连次数->停止重连');
  119 + this._emit(EverSocket.ERROR, EverSocket.ERR_SOCKET_MAX_RECONNECT_FAILED);
  120 + return;
  121 + }
  122 +
116 this._emit(EverSocket.ERROR, EverSocket.ERR_SOCKET_RECONNECT_FAILED); 123 this._emit(EverSocket.ERROR, EverSocket.ERR_SOCKET_RECONNECT_FAILED);
117 this.reConnectionCounter = 0; 124 this.reConnectionCounter = 0;
  125 +
118 } 126 }
119 127
120 this.reConnectionTimeout = window.setTimeout(() => { 128 this.reConnectionTimeout = window.setTimeout(() => {
@@ -175,6 +183,7 @@ class EverSocket extends Emiter { @@ -175,6 +183,7 @@ class EverSocket extends Emiter {
175 _onOpen() { 183 _onOpen() {
176 loger.log('WebSocket建立成功', this.wsURL); 184 loger.log('WebSocket建立成功', this.wsURL);
177 this.reConnectionCounter = 0; 185 this.reConnectionCounter = 0;
  186 + this.mcuReconnectCounter=0;
178 187
179 //启动心跳,检查socket链接状态 188 //启动心跳,检查socket链接状态
180 this.pingTimer = window.setInterval(this._sendPingHandler.bind(this), EverSocket.PING_INTERVAL); 189 this.pingTimer = window.setInterval(this._sendPingHandler.bind(this), EverSocket.PING_INTERVAL);
@@ -239,7 +248,8 @@ EverSocket.prototype.PING_INTERVAL = EverSocket.PING_INTERVAL = 10000;//敹歲 @@ -239,7 +248,8 @@ EverSocket.prototype.PING_INTERVAL = EverSocket.PING_INTERVAL = 10000;//敹歲
239 EverSocket.prototype.RECONN_INTERVAL = EverSocket.RECONN_INTERVAL = 5000;//重连的间隔 248 EverSocket.prototype.RECONN_INTERVAL = EverSocket.RECONN_INTERVAL = 5000;//重连的间隔
240 249
241 250
242 -EverSocket.prototype.ERR_SOCKET_RECONNECT_FAILED = EverSocket.ERR_SOCKET_RECONNECT_FAILED = 20001;//MCU自动重连失败,已经达到最大重连次数 251 +EverSocket.prototype.ERR_SOCKET_RECONNECT_FAILED = EverSocket.ERR_SOCKET_RECONNECT_FAILED = 20001;//MCU自动重连失败,
  252 +EverSocket.prototype.ERR_SOCKET_MAX_RECONNECT_FAILED = EverSocket.ERR_SOCKET_MAX_RECONNECT_FAILED = 20002;//MCU自动重连失败,已经达到最大重连次数
243 253
244 EverSocket.prototype.CONNECTING = EverSocket.CONNECTING = 0; 254 EverSocket.prototype.CONNECTING = EverSocket.CONNECTING = 0;
245 EverSocket.prototype.OPEN = EverSocket.OPEN = 1; 255 EverSocket.prototype.OPEN = EverSocket.OPEN = 1;
@@ -621,7 +621,7 @@ GlobalConfig.stopRecordingInterfaces="";//停止录制的接口 @@ -621,7 +621,7 @@ GlobalConfig.stopRecordingInterfaces="";//停止录制的接口
621 GlobalConfig.getTxRecordInfoInterfaces="";//获取媒体录制信息数据的接口(tx) 621 GlobalConfig.getTxRecordInfoInterfaces="";//获取媒体录制信息数据的接口(tx)
622 GlobalConfig.getRecordFileURLAgoInterfaces="";//获取媒体录制信息数据的接口(ago) 622 GlobalConfig.getRecordFileURLAgoInterfaces="";//获取媒体录制信息数据的接口(ago)
623 GlobalConfig.getChannelToken="";//获取token的地址 623 GlobalConfig.getChannelToken="";//获取token的地址
624 - 624 +GlobalConfig.recordFileSever="";//录制文件路径和文件地址(ago)
625 GlobalConfig.videoScale=1;//视频的缩放倍数,默认1倍无缩放 625 GlobalConfig.videoScale=1;//视频的缩放倍数,默认1倍无缩放
626 626
627 export default GlobalConfig; 627 export default GlobalConfig;
@@ -117,6 +117,8 @@ MessageTypes.SWITCH_MCU_IP = "switch_mcu_ip"; //切换mcu 重新选点 @@ -117,6 +117,8 @@ MessageTypes.SWITCH_MCU_IP = "switch_mcu_ip"; //切换mcu 重新选点
117 MessageTypes.SWITCH_MS_IP = "switch_ms_ip"; //切换ms 重新选点 117 MessageTypes.SWITCH_MS_IP = "switch_ms_ip"; //切换ms 重新选点
118 MessageTypes.SWITCH_RTMP_PULL_IP = "switch_rtmp_pull_ip"; //切换ms MS拉流选点 118 MessageTypes.SWITCH_RTMP_PULL_IP = "switch_rtmp_pull_ip"; //切换ms MS拉流选点
119 MessageTypes.SWITCH_HLS_IP = "switch_hls_ip"; //切换ms HLS拉流选点 119 MessageTypes.SWITCH_HLS_IP = "switch_hls_ip"; //切换ms HLS拉流选点
  120 +MessageTypes.SOCKET_MAX_RECONNECT_FAILED = "socket_max_reconnect_failed"; //mcu重连次数已经达到最大次数
  121 +
120 122
121 //录制回放 123 //录制回放
122 MessageTypes.RECORD_PLAYBACK_UPDATE = "record_playback_update"; //录制回放更新信息 124 MessageTypes.RECORD_PLAYBACK_UPDATE = "record_playback_update"; //录制回放更新信息
@@ -14,6 +14,7 @@ import Base64 from 'base64-js'; @@ -14,6 +14,7 @@ import Base64 from 'base64-js';
14 import GlobalConfig from 'GlobalConfig'; 14 import GlobalConfig from 'GlobalConfig';
15 import EngineUtils from 'EngineUtils'; 15 import EngineUtils from 'EngineUtils';
16 import TimerCounter from "TimerCounter"; 16 import TimerCounter from "TimerCounter";
  17 +import RecordInfoMatch from "RecordInfoMatch";
17 18
18 let parseBuffer; 19 let parseBuffer;
19 // 日志对象 20 // 日志对象
@@ -53,6 +54,10 @@ class RecordPlayBackParse extends Emiter { @@ -53,6 +54,10 @@ class RecordPlayBackParse extends Emiter {
53 54
54 this.agoTiemstampMessages={};//ago推流时间戳消息数据集合 55 this.agoTiemstampMessages={};//ago推流时间戳消息数据集合
55 this.agoAllMedias={};//ago录制的文件集合 56 this.agoAllMedias={};//ago录制的文件集合
  57 +
  58 + this.allStreams={};//记录课堂内所有的流id
  59 + this.recordInfoMatch=RecordInfoMatch;
  60 + this.recordInfoMatch.on(RecordInfoMatch.RECORD_INFO_MATCH_COMPLETE,this.onRecordInfoMatchComplete.bind(this));
56 } 61 }
57 62
58 //method--------------------内部--------------------------------------------- 63 //method--------------------内部---------------------------------------------
@@ -208,6 +213,25 @@ class RecordPlayBackParse extends Emiter { @@ -208,6 +213,25 @@ class RecordPlayBackParse extends Emiter {
208 } 213 }
209 } 214 }
210 215
  216 + //消息和录制文件匹配完成
  217 + onRecordInfoMatchComplete(_data){
  218 + console.log("消息和录制文件匹配完成",_data);
  219 + if(_data){
  220 + for(let k in _data){
  221 + //优先使用TXY的,没有的时候再使用AGO
  222 + /* if(! MediaModule.streams[k]){
  223 + MediaModule.streams[k]=_data[k];
  224 + }else {
  225 + console.log(k+" 已经存在",MediaModule.streams[k]);
  226 + }*/
  227 + MediaModule.streams[k]=_data[k];
  228 +
  229 + }
  230 + }
  231 + console.warn("最终匹配完成的视频流数据", MediaModule.streams);
  232 + //解析课堂录制的rec文件
  233 + this.parseArrayBuf();
  234 + }
211 //保存各个模块的MCU原始数据 235 //保存各个模块的MCU原始数据
212 saveParseData(data, timestamp, apeMessages) { 236 saveParseData(data, timestamp, apeMessages) {
213 let messageItem = apeMessages[timestamp]; 237 let messageItem = apeMessages[timestamp];
@@ -302,7 +326,8 @@ class RecordPlayBackParse extends Emiter { @@ -302,7 +326,8 @@ class RecordPlayBackParse extends Emiter {
302 parseBuffer.clear(); 326 parseBuffer.clear();
303 parseBuffer.append(arrayBuffer); 327 parseBuffer.append(arrayBuffer);
304 //rec数据加载完成后,继续加载音视频相关的录制数据,然后再解析rec数据 328 //rec数据加载完成后,继续加载音视频相关的录制数据,然后再解析rec数据
305 - this.getMediaRecrodInfoFromTx(()=>{ 329 +
  330 + /* this.getMediaRecrodInfoFromTx(()=>{
306 //解析录制的rec数据 331 //解析录制的rec数据
307 this.isLoadTxRecordInfo=true; 332 this.isLoadTxRecordInfo=true;
308 if(this.isLoadTxRecordInfo&&this.isLoadAgoRecordInfo&&this.isgetRecordFileURLFromAgo){ 333 if(this.isLoadTxRecordInfo&&this.isLoadAgoRecordInfo&&this.isgetRecordFileURLFromAgo){
@@ -325,7 +350,12 @@ class RecordPlayBackParse extends Emiter { @@ -325,7 +350,12 @@ class RecordPlayBackParse extends Emiter {
325 this.matchingVideoUrlFromTime(this.agoTiemstampMessages,this.agoAllMedias); 350 this.matchingVideoUrlFromTime(this.agoTiemstampMessages,this.agoAllMedias);
326 this.parseArrayBuf(); 351 this.parseArrayBuf();
327 } 352 }
328 - }) 353 + })*/
  354 + this.getMediaRecrodInfoFromTx(()=>{
  355 + //AGO启动录制消息和文件匹配
  356 + this.recordInfoMatch.start();
  357 + });
  358 +
329 } 359 }
330 } 360 }
331 //时间戳转换为UTC 时间字符串 361 //时间戳转换为UTC 时间字符串
@@ -402,9 +432,9 @@ class RecordPlayBackParse extends Emiter { @@ -402,9 +432,9 @@ class RecordPlayBackParse extends Emiter {
402 for(let k in finelMediaInfo){ 432 for(let k in finelMediaInfo){
403 let okItem=finelMediaInfo[k]; 433 let okItem=finelMediaInfo[k];
404 let seek=(parseInt(noItem.timestamp)-parseInt(okItem.timestamp))/1000; 434 let seek=(parseInt(noItem.timestamp)-parseInt(okItem.timestamp))/1000;
405 - console.log("seek",seek); 435 + //console.log("seek",seek);
406 if(noItem.uid==okItem.uid&&seek<15&&noItem.timestamp!=okItem.timestamp){ 436 if(noItem.uid==okItem.uid&&seek<15&&noItem.timestamp!=okItem.timestamp){
407 - console.log(noItem,okItem); 437 + //console.log(noItem,okItem);
408 noItem.video_url=okItem.video_url; 438 noItem.video_url=okItem.video_url;
409 noItem.seek=seek; 439 noItem.seek=seek;
410 finelMediaInfo [noItem.timestamp]=noItem; 440 finelMediaInfo [noItem.timestamp]=noItem;
@@ -505,7 +535,7 @@ class RecordPlayBackParse extends Emiter { @@ -505,7 +535,7 @@ class RecordPlayBackParse extends Emiter {
505 } 535 }
506 }) 536 })
507 .then(ret => { 537 .then(ret => {
508 - loger.log('AG-获取媒体录制信息-完成',ret); 538 + loger.log('AG-获取媒体录制信息-完成');
509 //console.log("getRecordInfo success",ret); 539 //console.log("getRecordInfo success",ret);
510 if(ret&&ret.returnData&&ret.returnData.data){ 540 if(ret&&ret.returnData&&ret.returnData.data){
511 let dataArr=ret.returnData.data; 541 let dataArr=ret.returnData.data;
@@ -564,7 +594,7 @@ class RecordPlayBackParse extends Emiter { @@ -564,7 +594,7 @@ class RecordPlayBackParse extends Emiter {
564 } 594 }
565 }) 595 })
566 .then(ret => { 596 .then(ret => {
567 - loger.log('TX-获取媒体录制信息-完成',ret); 597 + loger.log('TX-获取媒体录制信息-完成');
568 /* {"code": 200, 598 /* {"code": 200,
569 "returnData":{ 599 "returnData":{
570 "data":[ 600 "data":[
@@ -758,6 +788,14 @@ class RecordPlayBackParse extends Emiter { @@ -758,6 +788,14 @@ class RecordPlayBackParse extends Emiter {
758 return {"code": ApeConsts.RETURN_FAILED, "data": "录制回放还未准备完成"}; 788 return {"code": ApeConsts.RETURN_FAILED, "data": "录制回放还未准备完成"};
759 } 789 }
760 loger.log("classStatusInfo",GlobalConfig.classStatusInfo); 790 loger.log("classStatusInfo",GlobalConfig.classStatusInfo);
  791 + console.log("所有流ID",this.allStreams);
  792 + for(let i in this.allStreams){
  793 + if(MediaModule.streams[i]){
  794 + console.log("匹配成功的流:"+i,MediaModule.streams[i]);
  795 + }else {
  796 + console.warn("未匹配成功的流:"+i);
  797 + }
  798 + }
761 this._startTimerCounter(); 799 this._startTimerCounter();
762 this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": PLAY}); 800 this._emit(MessageTypes.RECORD_PLAYBACK_UPDATE, {"status": PLAY});
763 } 801 }
@@ -1159,6 +1197,8 @@ class RecordPlayBackParse extends Emiter { @@ -1159,6 +1197,8 @@ class RecordPlayBackParse extends Emiter {
1159 let statusStr="关"; 1197 let statusStr="关";
1160 if(videoChannelInfo&&videoChannelInfo.status==1){ 1198 if(videoChannelInfo&&videoChannelInfo.status==1){
1161 statusStr="开"; 1199 statusStr="开";
  1200 + this.allStreams[videoChannelInfo.streamId]=videoChannelInfo;
  1201 + console.log("视频流"+videoChannelInfo.streamId);
1162 } 1202 }
1163 this.mediaChannleList[videoChannelInfo.channelId][timestamp]={parseData:videoChannelInfo,byteData:data,timestamp: timestamp,status:statusStr}; 1203 this.mediaChannleList[videoChannelInfo.channelId][timestamp]={parseData:videoChannelInfo,byteData:data,timestamp: timestamp,status:statusStr};
1164 } catch (err) { 1204 } catch (err) {
@@ -467,7 +467,7 @@ class AudioApe extends Ape { @@ -467,7 +467,7 @@ class AudioApe extends Ape {
467 } 467 }
468 468
469 MediaModule.allMediaChannelsList[itemIdx] = unpackChannelInfo; 469 MediaModule.allMediaChannelsList[itemIdx] = unpackChannelInfo;
470 - console.log('MediaModule.allMediaChannelsList', MediaModule.allMediaChannelsList); 470 + //console.log('MediaModule.allMediaChannelsList', MediaModule.allMediaChannelsList);
471 this._emit(MessageTypes.AUDIO_UPDATE, unpackChannelInfo); 471 this._emit(MessageTypes.AUDIO_UPDATE, unpackChannelInfo);
472 } 472 }
473 473
@@ -28,7 +28,7 @@ class ConferApe extends Ape { @@ -28,7 +28,7 @@ class ConferApe extends Ape {
28 this.rosterLen = 0;//当前课堂人数 28 this.rosterLen = 0;//当前课堂人数
29 this.timerCounter = new TimerCounter(); //计时器 29 this.timerCounter = new TimerCounter(); //计时器
30 this.startRecordTimer;//开始录制的计时器 30 this.startRecordTimer;//开始录制的计时器
31 - 31 + this.recordStatus=false;//记录录制状态
32 //第三方消息控制 parent和Iframe直接的通讯 32 //第三方消息控制 parent和Iframe直接的通讯
33 this.thirdMessage = new ThirdMessage(); 33 this.thirdMessage = new ThirdMessage();
34 this.thirdMessage.on(ThirdMessage.RECIVE_MESSAGE, this.onThirdReciveParentMessage.bind(this)); 34 this.thirdMessage.on(ThirdMessage.RECIVE_MESSAGE, this.onThirdReciveParentMessage.bind(this));
@@ -245,6 +245,10 @@ class ConferApe extends Ape { @@ -245,6 +245,10 @@ class ConferApe extends Ape {
245 optional string filename = 4; // 录像文件名称,filename中增加目录部分 245 optional string filename = 4; // 录像文件名称,filename中增加目录部分
246 }*/ 246 }*/
247 247
  248 + if(this.recordStatus==conferRecordSendPdu.record){
  249 + //已经有录制文件,不再发送
  250 + return;
  251 + }
248 //保存当前的录制状态 252 //保存当前的录制状态
249 GlobalConfig.recordStatus = _param.recordStatus || false; 253 GlobalConfig.recordStatus = _param.recordStatus || false;
250 let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu']; 254 let conferRecordSendPdu = new pdu['RCConferenceRecordRequestPdu'];
@@ -296,12 +300,12 @@ class ConferApe extends Ape { @@ -296,12 +300,12 @@ class ConferApe extends Ape {
296 checkHasRecordControl() { 300 checkHasRecordControl() {
297 //loger.warn('检测是否有控制录制操作的权限', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen); 301 //loger.warn('检测是否有控制录制操作的权限', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
298 //1.如果自己是老师或者当前课堂只有一个人 302 //1.如果自己是老师或者当前课堂只有一个人
299 - if (GlobalConfig.isHost || this.rosterLen <= 1) { 303 + if (GlobalConfig.isHost || this.rosterLen <= 1&&GlobalConfig.deviceType!=3) {
300 return true; 304 return true;
301 } 305 }
302 //2.如果自己不是老师,需要判断当前课堂内是否有老师,如果有老师就不做操作 306 //2.如果自己不是老师,需要判断当前课堂内是否有老师,如果有老师就不做操作
303 for (let i in this.rosters) { 307 for (let i in this.rosters) {
304 - //如果老师就停止 308 + //如果老师就停止
305 let rosterItem = this.rosters[i]; 309 let rosterItem = this.rosters[i];
306 if (rosterItem && rosterItem.userRole == ApeConsts.host) { 310 if (rosterItem && rosterItem.userRole == ApeConsts.host) {
307 return false; 311 return false;
@@ -912,7 +916,12 @@ class ConferApe extends Ape { @@ -912,7 +916,12 @@ class ConferApe extends Ape {
912 let conferRecordSendPdu = pdu['RCConferenceRecordRequestPdu'].decode(_data); 916 let conferRecordSendPdu = pdu['RCConferenceRecordRequestPdu'].decode(_data);
913 //{"initiator":564398684,"record":true,"classTime":39,"filename":"markettest/20170823/1096250804_20170823.rec"}//开启成功 917 //{"initiator":564398684,"record":true,"classTime":39,"filename":"markettest/20170823/1096250804_20170823.rec"}//开启成功
914 //{"initiator":564398684,"record":false,"classTime":39,"filename":"markettest/20170823/1096250804_20170823.rec"} //停止成功 918 //{"initiator":564398684,"record":false,"classTime":39,"filename":"markettest/20170823/1096250804_20170823.rec"} //停止成功
  919 + if(this.recordStatus==conferRecordSendPdu.record){
  920 + //已经开启过录制之后就不再处理
  921 + return;
  922 + }
915 loger.warn("录制回放控制操作成功->", conferRecordSendPdu); 923 loger.warn("录制回放控制操作成功->", conferRecordSendPdu);
  924 + this.recordStatus=conferRecordSendPdu.record;
916 if (conferRecordSendPdu) { 925 if (conferRecordSendPdu) {
917 if (conferRecordSendPdu.record == true || conferRecordSendPdu.record == "true") { 926 if (conferRecordSendPdu.record == true || conferRecordSendPdu.record == "true") {
918 //每次开启录制的时候,需要把当前显示的文档数据更新一次,否则无法录制已经显示的文件 927 //每次开启录制的时候,需要把当前显示的文档数据更新一次,否则无法录制已经显示的文件
@@ -1006,7 +1015,10 @@ class ConferApe extends Ape { @@ -1006,7 +1015,10 @@ class ConferApe extends Ape {
1006 this.rosterLen = Object.keys(this.rosters).length; 1015 this.rosterLen = Object.keys(this.rosters).length;
1007 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数 1016 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数
1008 newNodeData.rosterLen = this.rosterLen; 1017 newNodeData.rosterLen = this.rosterLen;
  1018 + if(GlobalConfig.classType!= ApeConsts.CLASS_TYPE_2){
1009 loger.log("人员加入->", newNodeData); 1019 loger.log("人员加入->", newNodeData);
  1020 + }
  1021 +
1010 this._emit(MessageTypes.CLASS_INSERT_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData}); 1022 this._emit(MessageTypes.CLASS_INSERT_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData});
1011 this.emitRosterChange(); 1023 this.emitRosterChange();
1012 } else { 1024 } else {
@@ -1015,8 +1027,10 @@ class ConferApe extends Ape { @@ -1015,8 +1027,10 @@ class ConferApe extends Ape {
1015 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数 1027 GlobalConfig.rosterNumber = this.rosterLen;//记录当前的总人数
1016 newNodeData.rosterLen = this.rosterLen; 1028 newNodeData.rosterLen = this.rosterLen;
1017 if (nodeId != GlobalConfig.nodeId) { 1029 if (nodeId != GlobalConfig.nodeId) {
  1030 + if(GlobalConfig.classType!= ApeConsts.CLASS_TYPE_2){
1018 loger.log("人员更新信息->", newNodeData); 1031 loger.log("人员更新信息->", newNodeData);
1019 } 1032 }
  1033 + }
1020 this._emit(MessageTypes.CLASS_UPDATE_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData}); 1034 this._emit(MessageTypes.CLASS_UPDATE_ROSTER, {"nodeId": nodeId, "nodeData": newNodeData});
1021 } 1035 }
1022 } 1036 }
@@ -1073,8 +1087,11 @@ class ConferApe extends Ape { @@ -1073,8 +1087,11 @@ class ConferApe extends Ape {
1073 } else { 1087 } else {
1074 let user = this.rosters[nodeId]; 1088 let user = this.rosters[nodeId];
1075 if (user) { 1089 if (user) {
  1090 + if(GlobalConfig.classType!= ApeConsts.CLASS_TYPE_2){
1076 loger.log(nodeId, "->离开课堂->身份->", user.userRole); 1091 loger.log(nodeId, "->离开课堂->身份->", user.userRole);
1077 } 1092 }
  1093 +
  1094 + }
1078 delete this.rosters[nodeId]; 1095 delete this.rosters[nodeId];
1079 GlobalConfig.rosters = this.rosters; 1096 GlobalConfig.rosters = this.rosters;
1080 this.rosterLen = Object.keys(this.rosters).length; 1097 this.rosterLen = Object.keys(this.rosters).length;
@@ -403,7 +403,7 @@ class DocApe extends Ape { @@ -403,7 +403,7 @@ class DocApe extends Ape {
403 let docDataModel = this.docList[paramInfo.itemIdx]; 403 let docDataModel = this.docList[paramInfo.itemIdx];
404 if (docDataModel == null) { 404 if (docDataModel == null) {
405 loger.warn('切换文档失败,文档不存在', paramInfo); 405 loger.warn('切换文档失败,文档不存在', paramInfo);
406 - this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 406 + // this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
407 return; 407 return;
408 } 408 }
409 409
@@ -760,7 +760,7 @@ class VideoApe extends Ape { @@ -760,7 +760,7 @@ class VideoApe extends Ape {
760 ) { 760 ) {
761 //非屏幕共享情况的处理 761 //非屏幕共享情况的处理
762 MediaModule.allMediaChannelsList[itemIdx] = unpackChannelInfo; 762 MediaModule.allMediaChannelsList[itemIdx] = unpackChannelInfo;
763 - console.log('MediaModule.allMediaChannelsList', MediaModule.allMediaChannelsList); 763 + //console.log('MediaModule.allMediaChannelsList', MediaModule.allMediaChannelsList);
764 this._emit(MessageTypes.VIDEO_UPDATE, unpackChannelInfo); 764 this._emit(MessageTypes.VIDEO_UPDATE, unpackChannelInfo);
765 } 765 }
766 766
@@ -828,11 +828,12 @@ class WebRtcApe extends Emiter { @@ -828,11 +828,12 @@ class WebRtcApe extends Emiter {
828 //status:0 停止推流 1:开始推流(同时开启录制),2:停止录制(同时停止推流) 828 //status:0 停止推流 1:开始推流(同时开启录制),2:停止录制(同时停止推流)
829 changePublishStatusAndServerRecord(_status) { 829 changePublishStatusAndServerRecord(_status) {
830 if (!GlobalConfig.recordInterfaces) { 830 if (!GlobalConfig.recordInterfaces) {
831 - loger.log("调用服务器端开启录制->失败->接口地址无效"); 831 + loger.log("调用服务器端更新视频录制状态->失败->接口地址无效");
832 return; 832 return;
833 } 833 }
834 let url = GlobalConfig.locationProtocol + GlobalConfig.recordInterfaces; 834 let url = GlobalConfig.locationProtocol + GlobalConfig.recordInterfaces;
835 let data = this.packMediaInfoData(_status); 835 let data = this.packMediaInfoData(_status);
  836 + loger.log("调用服务器端更新视频录制状态->status",_status);
836 fetch(encodeURI(url), { 837 fetch(encodeURI(url), {
837 method: 'POST', 838 method: 'POST',
838 headers: { 839 headers: {
@@ -845,19 +846,19 @@ class WebRtcApe extends Emiter { @@ -845,19 +846,19 @@ class WebRtcApe extends Emiter {
845 if (ret.ok) { 846 if (ret.ok) {
846 return ret.json(); 847 return ret.json();
847 } else { 848 } else {
848 - loger.error(`调用服务器端开启录制-网络异常.状态码:${ret.status}`); 849 + loger.error(`调用服务器端更新视频录制状态-网络异常.状态码:${ret.status}`);
849 throw ''; 850 throw '';
850 } 851 }
851 }) 852 })
852 .then(ret => { 853 .then(ret => {
853 if (ret) { 854 if (ret) {
854 - loger.log('调用服务器端开启录制完成', ret); 855 + loger.log('调用服务器端更新视频录制状态', ret);
855 } else { 856 } else {
856 - loger.warn('调用服务器端开启录制 失败.', ret); 857 + loger.warn('调用服务器端更新视频录制状态 失败.', ret);
857 } 858 }
858 }) 859 })
859 .catch(err => { 860 .catch(err => {
860 - loger.error(`调用服务器端开启录制.状态码:${err}`); 861 + loger.error(`调用服务器端更新视频录制状态.状态码:${err}`);
861 }); 862 });
862 } 863 }
863 864
@@ -55,6 +55,18 @@ class MCU extends Emiter { @@ -55,6 +55,18 @@ class MCU extends Emiter {
55 if (_errorCode == everSocket.ERR_SOCKET_RECONNECT_FAILED) { 55 if (_errorCode == everSocket.ERR_SOCKET_RECONNECT_FAILED) {
56 this._emit(MessageTypes.SWITCH_MCU_IP); 56 this._emit(MessageTypes.SWITCH_MCU_IP);
57 } 57 }
  58 + switch(_errorCode){
  59 + case everSocket.ERR_SOCKET_MAX_RECONNECT_FAILED:
  60 + //mcu已经达到最大重连次数,不再重连
  61 + this._emit(MessageTypes.SOCKET_MAX_RECONNECT_FAILED);
  62 + break;
  63 + case everSocket.ERR_SOCKET_RECONNECT_FAILED:
  64 + //重连失败,尝试更换MCU再重连
  65 + this._emit(MessageTypes.SWITCH_MCU_IP);
  66 + break;
  67 + default :
  68 + break;
  69 + }
58 } 70 }
59 71
60 //MCU-发送加入课堂请求 72 //MCU-发送加入课堂请求