diff --git a/node_modules/iphunter/dist/main.js b/node_modules/iphunter/dist/main.js
index c98d393..7da04af 100644
--- a/node_modules/iphunter/dist/main.js
+++ b/node_modules/iphunter/dist/main.js
@@ -1 +1 @@
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.iphunter=t():e.iphunter=t()}(this,function(){return function(e){function t(i){if(n[i])return n[i].exports;var o=n[i]={exports:{},id:i,loaded:!1};return e[i].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3;if(!(e&&e.length&&t))throw new Error("ips and callback are required.");new r(e,t,n)}Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();t.default=i;var r=function(){function e(t,i,o){n(this,e),this.version="v2.0.1.20170819",this.ip="",this.ipcallback=i,this.timeoutId=null,this.reqsCache=[];for(var r=0;r<t.length;r++)this.reqsCache.push(this.send(t[r],o-10));this.timeoutId=setTimeout(this.notify.bind(this),o)}return o(e,[{key:"clearAll",value:function(){this.reqsCache&&this.reqsCache.length&&this.reqsCache.forEach(function(e){e.abort()}),clearTimeout(this.timeoutId),this.ip="",this.ipcallback=null,this.timeoutId=null,this.reqsCache=[]}},{key:"clearReq",value:function(e){this.reqsCache.splice(this.reqsCache.indexOf(e),1)}},{key:"notify",value:function(){this.ipcallback&&this.ipcallback(this.ip),this.clearAll()}},{key:"send",value:function(e,t){var n=this,i=new XMLHttpRequest;return i.open("HEAD","//"+e+"/?_="+Date.now()),i.timeout=t,i.onload=function(){n.ip=e,n.clearReq(i),i.onload=null,n.notify()},i.ontimeout=function(){n.clearReq(i),i.ontimeout=null},i.onerror=function(){n.clearReq(i),i.onerror=null},i.onabort=function(){n.clearReq(i),i.onabort=null},i.send(),i}}]),e}();(function(){"undefined"!=typeof __REACT_HOT_LOADER__&&(__REACT_HOT_LOADER__.register(r,"IpHunter","D:/work/McuClient/node_modules/iphunter/src/main.js"),__REACT_HOT_LOADER__.register(i,"check","D:/work/McuClient/node_modules/iphunter/src/main.js"))})()}])});
\ No newline at end of file
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.iphunter=t():e.iphunter=t()}(this,function(){return function(e){function t(i){if(n[i])return n[i].exports;var o=n[i]={exports:{},id:i,loaded:!1};return e[i].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3;if(!(e&&e.length&&t))throw new Error("ips and callback are required.");new r(e,t,n)}Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();t.default=i;var r=function(){function e(t,i,o){n(this,e),this.version="v2.0.1.20170819",this.ip="",this.ipcallback=i,this.timeoutId=null,this.reqsCache=[];for(var r=0;r<t.length;r++)this.reqsCache.push(this.send(t[r],o));this.timeoutId=setTimeout(this.notify.bind(this),o)}return o(e,[{key:"clearAll",value:function(){this.reqsCache&&this.reqsCache.length&&this.reqsCache.forEach(function(e){e.abort()}),clearTimeout(this.timeoutId),this.ip="",this.ipcallback=null,this.timeoutId=null,this.reqsCache=[]}},{key:"clearReq",value:function(e){this.reqsCache.splice(this.reqsCache.indexOf(e),1)}},{key:"notify",value:function(){this.ipcallback&&this.ipcallback(this.ip),this.clearAll()}},{key:"send",value:function(e,t){var n=this,i=new XMLHttpRequest;return i.open("HEAD","//"+e+"/?_="+Date.now()),i.timeout=t,i.onload=function(){n.ip=e,n.clearReq(i),i.onload=null,n.notify()},i.ontimeout=function(){n.clearReq(i),i.ontimeout=null},i.onerror=function(){n.clearReq(i),i.onerror=null},i.onabort=function(){n.clearReq(i),i.onabort=null},i.send(),i}}]),e}();(function(){"undefined"!=typeof __REACT_HOT_LOADER__&&(__REACT_HOT_LOADER__.register(r,"IpHunter","D:/work/McuClient/node_modules/iphunter/src/main.js"),__REACT_HOT_LOADER__.register(i,"check","D:/work/McuClient/node_modules/iphunter/src/main.js"))})()}])});
\ No newline at end of file
diff --git a/node_modules/iphunter/src/main.js b/node_modules/iphunter/src/main.js
index 80bb5a5..1728d93 100644
--- a/node_modules/iphunter/src/main.js
+++ b/node_modules/iphunter/src/main.js
@@ -7,7 +7,8 @@ class IpHunter {
     this.reqsCache = [];
 
     for (let i = 0; i < ips.length; i++) {
-      this.reqsCache.push(this.send(ips[i], timeout - 10));
+      //this.reqsCache.push(this.send(ips[i], timeout - 10));
+      this.reqsCache.push(this.send(ips[i], timeout));
     }
     this.timeoutId = setTimeout(this.notify.bind(this), timeout);
   }
diff --git a/src/EngineEntrance.js b/src/EngineEntrance.js
index 8bc12eb..1a6f6b6 100644
--- a/src/EngineEntrance.js
+++ b/src/EngineEntrance.js
@@ -58,7 +58,7 @@ export default class MessageEntrance extends Emiter {
   constructor() {
     super();
     //sdk 信息
-    GlobalConfig.sdkVersion = "v1.81.19.20170828";
+    GlobalConfig.sdkVersion = "v1.82.11.20170829";
     loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
 
     //设置
@@ -87,7 +87,7 @@ export default class MessageEntrance extends Emiter {
     this.isGetFastestRtmpPullCallback = false; //是否RTMP拉流地址测试结束
     this.isGetFastestHlsPullCallback = false; //是否HLS拉流地址测试结束
     this.isGetFastestRsCallback = false; //是否录制回放HLS拉流地址测试结束
-
+    this.saveClassStatusTimer=0;//保存课堂数据的计时器间隔,防止同一瞬间多次提交
     //全局的Error处理
     this.on(MessageTypes.MCU_ERROR, this._mcuErrorHandler.bind(this));
 
@@ -420,21 +420,19 @@ export default class MessageEntrance extends Emiter {
   //开启录制成功
   _onClassRecordSuccess(_param) {
     clearTimeout(this.classRecordStatusUpdateTimer);
-    let _this = this;
-    this.classRecordStatusUpdateTimer = setTimeout(function () {
+    this.classRecordStatusUpdateTimer = setTimeout(()=> {
       clearTimeout(this.classRecordStatusUpdateTimer);
-      _this.updaterRecordAllApeStatus(_param);
+      this.updaterRecordAllApeStatus(_param);
     }, 1600);
-
   }
 
   //录制状态发送改变,更新所有模块的当前数据发送到MCU
   updaterRecordAllApeStatus(_param) {
-    if(GlobalConfig.isRecordPlayBack){
+    if(GlobalConfig.isRecordPlayBack||!_confer_ape){
       return;
     }
     //老师身份和非录制回放的时候执行,录制状态发送改变,需要更新当前的数据,否则已有的消息会录制不上
-    if (GlobalConfig.isHost||GlobalConfig.rosterNumber<=1) {
+    if (_confer_ape.checkHasRecordControl()) {
       loger.warn('录制状态发送改变->更新所有模块的当前数据发送到MCU');
       //目前录制的模块[文档模块、白板模块、视频模块(包含屏幕共享)、音频模块、媒体共享,聊天模块]
       if (_doc_ape) {
@@ -452,6 +450,9 @@ export default class MessageEntrance extends Emiter {
       if (_mediaShareApe) {
         _mediaShareApe.updaterRecordApeStatus();
       }
+      if (_musicShareApe) {
+        _musicShareApe.updaterRecordApeStatus();
+      }
       //聊天模块不需要更新
     }
   }
@@ -825,11 +826,11 @@ export default class MessageEntrance extends Emiter {
       loger.warn("课堂最终使用的服务列表->来自本地Server.json");
     }
 
-    loger.warn("mcuListFinal", GlobalConfig.mcuListFinal);
-    loger.warn("msListFinal", GlobalConfig.msListFinal);
-    loger.warn("rtmpPullListFinal", GlobalConfig.rtmpPullListFinal);
-    loger.warn("hlsListFinal", GlobalConfig.hlsPullListFinal);
-    loger.warn("rsListFinal", GlobalConfig.rsPullListFinal);
+    loger.warn(" MCU-List", GlobalConfig.mcuListFinal);
+    loger.warn(" MS-List", GlobalConfig.msListFinal);
+    loger.warn(" RTMP-List", GlobalConfig.rtmpPullListFinal);
+    loger.warn(" HLS-List", GlobalConfig.hlsPullListFinal);
+    loger.warn(" RS-List", GlobalConfig.rsPullListFinal);
   }
 
   //从Sass中选择的mcu、ms列表
@@ -876,7 +877,6 @@ export default class MessageEntrance extends Emiter {
         GlobalConfig.isp,
         ServerConfig.serverList);
     }
-    loger.warn("Sass中获取的服务器信息;");
 
     //拉流地址列表的特殊处理,
     // 1.如果RTMP拉流地址没有配置,就默认使用MS推流地址列表
@@ -889,11 +889,11 @@ export default class MessageEntrance extends Emiter {
     }
 
     loger.warn("课堂最终使用的服务列表->来自Sass");
-    loger.warn(" GlobalConfig.mcuListFinal", GlobalConfig.mcuListFinal);
-    loger.warn(" GlobalConfig.msListFinal", GlobalConfig.msListFinal);
-    loger.warn(" GlobalConfig.rtmpPullListFinal", GlobalConfig.rtmpPullListFinal);
-    loger.warn(" GlobalConfig.hlsListFinal", GlobalConfig.hlsPullListFinal);
-    loger.warn(" GlobalConfig.rsListFinal", GlobalConfig.rsPullListFinal);
+    loger.warn(" MCU-List", GlobalConfig.mcuListFinal);
+    loger.warn(" MS-List", GlobalConfig.msListFinal);
+    loger.warn(" RTMP-List", GlobalConfig.rtmpPullListFinal);
+    loger.warn(" HLS-List", GlobalConfig.hlsPullListFinal);
+    loger.warn(" RS-List", GlobalConfig.rsPullListFinal);
 
   }
 
@@ -955,54 +955,37 @@ export default class MessageEntrance extends Emiter {
 
   //保存课堂状态信息
   _sassSaveClassStatusInfo(_param) {
+    if (!_mcu||!_mcu.connected) {
+      loger.warn("不能保存课堂数据->MCU已经断开");
+      return ;
+    }
+    if(!_confer_ape){
+      return;
+    }
     //{isForce:true}   isForce->是否强制提交(true为是)
     //这个是特殊权限
     let isForce = false;
     if (_param && _param.isForce == true) {
       isForce = true;
     }
-
-  /* if (GlobalConfig.isHost || isForce) {
-      //只有加入课堂之后才能保存数据
-      if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
-        //POST 保存数据
-        _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo}); //保存课堂状态信息
-      } else {
-        loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());
-      }
-    } else {
-      loger.log("没有保存课堂状态信息的权限->身份", GlobalConfig.userRole);
-    }*/
-    if (GlobalConfig.isHost || isForce||GlobalConfig.rosterNumber<=1) {
-      //只有加入课堂之后才能保存数据
-      /*if (GlobalConfig.getCurrentStatus().code == GlobalConfig.statusCode_2.code) {
-        //POST 保存数据
-        _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo}); //保存课堂状态信息
-      } else {
-        loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());
-      }*/
-      if (_mcu&&_mcu.connected) {
+    if (_confer_ape.checkHasRecordControl()||isForce) {
        //POST 保存数据
-         _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo}); //保存课堂状态信息
-       } else {
-       loger.error("不能保存课堂数据", GlobalConfig.getCurrentStatus());
-       }
-
+        clearTimeout(this.saveClassStatusTimer);
+        this.saveClassStatusTimer=setTimeout(()=>{
+          _sass.saveClassStatusInfo({"classStatusInfo": GlobalConfig.classStatusInfo}); //保存课堂状态信息
+        },600);
     } else {
-      loger.log("没有保存课堂状态信息的权限->身份", GlobalConfig.userRole);
+      loger.log("没有保存课堂状态信息的权限->当前身份->"+GlobalConfig.userRole);
     }
-
   }
 
   //保存会态信息成功
   _sassSaveClassStatusInfoSuccessHandler(_data) {
-    loger.log('保存课堂状态信息成功.');
-    loger.log(_data);
+    //loger.log('Saas保存课堂状态信息成功');
   }
 
   _sassSaveClassRecordInfoSuccessHandler(_data) {
-    loger.log('保存课堂录制信息成功.');
-    loger.log(_data);
+    //loger.log('Saas保存课堂录制信息成功',_data);
   }
 
   //Sass校验流程结束之后,开始加入MCU
@@ -1208,11 +1191,22 @@ export default class MessageEntrance extends Emiter {
       GlobalConfig.MS_PUBLISH_IP = _param.ip || "";
       GlobalConfig.MS_PUBLISH_PORT = _param.port || "";
     }
+    GlobalConfig.MS_PLAY_RTMP_IP = GlobalConfig.MS_PUBLISH_IP;
+    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地址,需要更新用户数据
     if (_confer_ape) {
       _confer_ape.updateUserInfo();
     }
+
+    //音视频模块对当前正在播放的流进行更换MS
+    if(_video_ape){
+      _video_ape.changeMediaMs();
+    }
+    if(_audio_ape){
+      _audio_ape.changeMediaMs();
+    }
   }
 
   //切换MS ->_param->{reConnect:false} //reConnect(是否立即替换当前的ip并且重新连接)
@@ -1381,13 +1375,10 @@ export default class MessageEntrance extends Emiter {
       return;
     }
     if (_confer_ape) {
-      //开始录制
-      setTimeout(()=> {
-        _confer_ape.startRecord();
-      },2000);
-
       //开始上课
       _confer_ape.startClass(_param);
+     ////开始录制
+     //_confer_ape.startRecord();
     }
   }
 
@@ -2082,7 +2073,7 @@ export default class MessageEntrance extends Emiter {
 
   //文档加入频道成功,同步到MCU服务器上的数据
   docJoinChannelSuccess() {
-    loger.log("docJoinChannelSuccess->isHost=", GlobalConfig.isHost, "当前总人数:", GlobalConfig.rosterNumber, "sassDoclength=", GlobalConfig.docListPrepare.length);
+    loger.log("文档加入频道成功->isHost=", GlobalConfig.isHost, "当前总人数:", GlobalConfig.rosterNumber, "sassDoclength=", GlobalConfig.docListPrepare.length);
     //loger.log("docJoinChannelSuccess  docListPrepare=");
     //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传
     if (GlobalConfig.docListPrepare && GlobalConfig.docListPrepare.length > 0) {
diff --git a/src/GlobalConfig.js b/src/GlobalConfig.js
index 99a3eae..9725f4d 100644
--- a/src/GlobalConfig.js
+++ b/src/GlobalConfig.js
@@ -100,9 +100,9 @@ class GlobalConfig {
     }
     //设置当前的课堂状态的信息
   static setClassStatusInfo(_data) {
-    loger.log("setClassStatusInfo");
+    //loger.log("setClassStatusInfo");
     if (_data == null) {
-      loger.warn("classStatusInfo error,_data:", _data);
+      loger.warn("设置当前的课堂状态的信失败:", _data);
       return;
     }
     let data = _data;
@@ -137,7 +137,7 @@ class GlobalConfig {
 
     //this.recordStatus = data.recordStatus || this.recordStatus; //当前录制状态
     this.recordStatus = data.recordStatus ||false; //当前录制状态
-    this.recordTimestamp = data.recordTimestamp || this.recordTimestamp; //相对于首次开始录制的时间戳
+    this.recordTimestamp =Math.max(parseInt(data.recordTimestamp), this.recordTimestamp); //录制时间取最大值
     this.recordFileName = data.recordFileName || this.recordFileName; //录制的文件名
     this.recordDownloadUrl = data.recordDownloadUrl || this.recordDownloadUrl; //下载地址
     this.currentSceneTableId = data.currentSceneTableId || 0; //文档区域的模块显示
@@ -523,7 +523,8 @@ GlobalConfig.recordReplaytickValues = {}; // 滚动条关键点,用于快进�
 
 GlobalConfig.isAutoStartClass = 0; //是否自动开始上课 0-否 ;1 是
 
-GlobalConfig.updateClassInfoDelay = 20; //(秒),每隔30秒同步一次课堂状态的并保存到Sass
+GlobalConfig.updateRecordTimeDelay = 4; //(秒),同步一次课堂录制状态的并保存到Sass
+GlobalConfig.updateClassInfoDelay = 10; //(秒),同步一次课堂状态的并保存到Sass
 GlobalConfig.msDynamicChooseIpDelay = 60 * 3; //(秒)MS动态选点的间隔
 //GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get  set 获取
 
diff --git a/src/IpManager.js b/src/IpManager.js
index 22d8fa7..45271f2 100644
--- a/src/IpManager.js
+++ b/src/IpManager.js
@@ -404,7 +404,7 @@ class IpManager extends Emiter {
         }
 
         //isp province都没有,使用default
-        let defaultData = countryData.default
+        let defaultData = countryData.default;
         if (defaultData) {
             // loger.log("_returnServerMS->defaultData",defaultData);
             return defaultData;
diff --git a/src/LogManager.js b/src/LogManager.js
index 1c0ecba..00eb028 100644
--- a/src/LogManager.js
+++ b/src/LogManager.js
@@ -148,7 +148,7 @@ class LogManager {
       })
       .then(ret => {
         if (ret == 0) {
-          console.log('保存日志信息 完成');
+          //console.log('保存日志信息 完成');
           tempArr=[];
         } else {
           console.warn('保存日志信息 失败.', ret);
diff --git a/src/Sass.js b/src/Sass.js
index d9340e8..380d915 100644
--- a/src/Sass.js
+++ b/src/Sass.js
@@ -440,7 +440,7 @@ class Sass extends Emiter {
     //let url = `http://${GlobalConfig.portal}/3m/api/meeting/saveInfo.do`;
     let url = `${GlobalConfig.locationProtocol+GlobalConfig.portal}/3m/api/meeting/saveInfo.do`;
 
-    loger.log('saveClassStatusInfo', url);
+    //loger.log('saveClassStatusInfo', url);
     fetch(url, {
         method: 'POST',
         headers: {
@@ -460,7 +460,7 @@ class Sass extends Emiter {
       })
       .then(ret => {
         if (ret.code === 0) {
-          loger.log('saveClassStatusInfo 完成');
+          //loger.log('saveClassStatusInfo 完成');
           this._emit(Sass.CLASS_SAVE_STATUS_INFO_SUCCESS, _param);
         } else if (ret.code === 1) {
           loger.log('saveClassStatusInfo 失败 课堂号为空');
@@ -485,7 +485,7 @@ class Sass extends Emiter {
       loger.log('录制回放中,不需要保存');
       return;
     }
-    loger.log('保存开始录制信息');
+    // loger.log('保存开始录制信息');
     let key = "3mang123A";
     let siteID = GlobalConfig.siteId;
     let meetingID = GlobalConfig.classId;
@@ -499,14 +499,14 @@ class Sass extends Emiter {
     let confRecordFileName = GlobalConfig.recordFileName;
     let downloadUrl = "";
     let recordStatus = GlobalConfig.classStatus;
-    let recordTimestamp = GlobalConfig.classTimestamp;
+    let recordTimestamp = GlobalConfig.recordTimestamp;//GlobalConfig.classTimestamp;//使用录制时间,不再使用课堂的进行时间
 
     let timestamp = new Date().getTime();
     let authId = MD5(key + siteID + meetingID + timestamp);
     //let url = `http://${GlobalConfig.portal}/3m/recordingMeeting/insertRecordingMeeting.do`;
     let url = `${GlobalConfig.locationProtocol+GlobalConfig.portal}/3m/recordingMeeting/insertRecordingMeeting.do`;
 
-    loger.log('saveClassRecordContrlInfo', url);
+    loger.log('保存开始录制信息:', url);
 
     fetch(encodeURI(url), {
       method: 'POST',
diff --git a/src/apes/ApeConsts.js b/src/apes/ApeConsts.js
index 02d6c38..7797de0 100644
--- a/src/apes/ApeConsts.js
+++ b/src/apes/ApeConsts.js
@@ -25,6 +25,8 @@ ApeConsts.CLASS_ACTION_CLOSE_ALL = 1; //所有人关闭课堂
 ApeConsts.CLASS_ACTION_HANDUP_STATUS_CHANGE = 2; //更改用户的举手状态
 ApeConsts.USER_ACTION_SILENCE_STATUS_CHANGE = 3; //更改用户的禁言状态
 ApeConsts.CLASS_ACTION_KICK_OUT_ROSTER=4; //指定的人踢出课堂
+ApeConsts.STOP_ALL_PUBLISH=5; //所有人停止推流
+
 
 //课堂类型 1:1v1(2路流) 2:直播(1路流) 3:小班课(可以多路流)
 ApeConsts.CLASS_TYPE_1 = 1; // 互动课堂,通过MS转发音视频,不能进行H5观看 1v1(2路流)
diff --git a/src/apes/AudioApe.js b/src/apes/AudioApe.js
index 8141e96..6f93700 100644
--- a/src/apes/AudioApe.js
+++ b/src/apes/AudioApe.js
@@ -384,7 +384,10 @@ class AudioApe extends Ape {
       this._emit(MessageTypes.AUDIO_BROADCAST, audioReceivePdu);
     }
   }
+  //切换了MS,重新更新一下当前正在播放的流地址
+  changeMediaMs(){
 
+  }
   tableUpdateHandler(owner, itemIdx, itemData, seek) {
     let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
     loger.log("tableUpdateHandler->channel", itemIdx, 'status->', unpackChannelInfo.status, "seek->", seek);
@@ -479,6 +482,10 @@ class AudioApe extends Ape {
         } else {
           channelInfo.owner = channelInfo.fromNodeId;
         }
+        //owner为0就是没有使用
+        if(channelInfo.owner==0){
+          channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED
+        }
         this.sendTableUpdateHandler(channelInfo);
       }
     }
diff --git a/src/apes/ConferApe.js b/src/apes/ConferApe.js
index a9fa710..dbf21bf 100644
--- a/src/apes/ConferApe.js
+++ b/src/apes/ConferApe.js
@@ -27,7 +27,7 @@ class ConferApe extends Ape {
     this.rosters = {}; //用户列表
     this.rosterLen = 0;//当前课堂人数
     this.timerCounter = new TimerCounter(); //计时器
-    this.startClassTimer;//开始课堂和开始录制的计时器
+    this.startRecordTimer;//开始录制的计时器
 
     //第三方消息控制 parent和Iframe直接的通讯
     this.thirdMessage = new ThirdMessage();
@@ -271,50 +271,64 @@ class ConferApe extends Ape {
       loger.warn('不能再录制,录制时间已经达到最大限制', GlobalConfig.recordTimestamp);
       return;
     }
-    loger.warn('检测是否需要开启录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
+    //如果已经开始录制就不再开启
+    if(GlobalConfig.recordStatus&&this.rosterLen>1){
+      loger.warn('目前已经是录制状态->当前课堂人数:'+this.rosterLen);
+      return false;
+    }
     //如果是host或者当前课堂只有1个人
-    if (GlobalConfig.isHost||this.rosterLen<=1) {
-     /* if(GlobalConfig.recordStatus){
-        loger.warn("课堂已经是录制状态不->不需要再开启,isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
-      }else{
-        loger.warn('开启录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
-        GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
-        this.sendConferRecordMsg({"recordStatus": true});
-        this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
-        this._emit(MessageTypes.CLASS_RECORD_START); //课堂开始录制
-      }*/
+    if (this.checkHasRecordControl()) {
         loger.warn('开启录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
-        GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
+      //如果录制的文件名不存在,需要创建一个名字
+      let timestampYMD = EngineUtils.creatTimestampYMD();
+      if(!GlobalConfig.recordFileName){
+        GlobalConfig.recordFileName=GlobalConfig.siteId + "/" + timestampYMD + "/" + GlobalConfig.classId + "_" + timestampYMD + ".rec"; //4、文件名称 $RECORD_HOME/`site id`/`日期`/`filename`    例:/data/record/su/20161216/`filename`
+      }
+      GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
         this.sendConferRecordMsg({"recordStatus": true});
         this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
         this._emit(MessageTypes.CLASS_RECORD_START); //课堂开始录制
     }
   }
 
+  //检测是否有控制录制操作的权限
+  checkHasRecordControl(){
+    //loger.warn('检测是否有控制录制操作的权限', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus,"当前人数:"+this.rosterLen);
+    //1.如果自己是老师或者当前课堂只有一个人
+    if(GlobalConfig.isHost||this.rosterLen<=1){
+      return true;
+    }
+    //2.如果自己不是老师,需要判断当前课堂内是否有老师,如果有老师就不做操作
+    for(let i in this.rosters){
+      //如果就老师就停止
+      let rosterItem=this.rosters[i];
+      if(rosterItem&&rosterItem.userRole==ApeConsts.host){
+        return false;
+      }
+    }
+    //3.课堂内有多个人并且都不是老师,选择一个nodeId最小的来操作
+    for(let k in this.rosters){
+      //如果选择的nodeId是自己就有权限,否则没有权限
+      if(k==GlobalConfig.nodeId){
+        return true;
+      }else {
+        return false;
+      }
+    }
+    return false
+  }
   //停止录制
   stopRecord(isForce) {
-   /* if (isForce && isForce == true) {
-      //强制停止,可以是host之外的身份(比如当前课堂老师异常退出,没有老师,会随机选择一个人来做释放操作)
-      if (GlobalConfig.recordStatus) {
-        loger.warn('停止录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
+    //判断是否有权限
+    if (this.checkHasRecordControl()){
+      loger.warn('停止录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
+      //this.sendUpdaterClassStatusInfo({"actionType":GlobalConfig.classStatus, isStopAllPublishMedia: true});
+      this.sendConferMsg({"to": 0, "message": "STOP_ALL_PUBLISH", "actionType": ApeConsts.STOP_ALL_PUBLISH});
+      setTimeout(()=>{
         GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
-        this.sendConferRecordMsg({"recordStatus": false});
         this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
-      }
-    } else {
-      //身份是host,并且当前正在录制中
-      if (GlobalConfig.isHost && GlobalConfig.recordStatus) {
-        GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
         this.sendConferRecordMsg({"recordStatus": false});
-        this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
-      }
-    }*/
-    //身份是host
-    if (GlobalConfig.isHost) {
-      loger.warn('停止录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
-      GlobalConfig.classStopTime = EngineUtils.creatTimestampStr();
-      this.sendConferRecordMsg({"recordStatus": false});
-      this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
+      },2000);
     }else {
       loger.warn('没有权限停止录制', "isHost", GlobalConfig.isHost, "recordStatus", GlobalConfig.recordStatus);
     }
@@ -363,7 +377,6 @@ class ConferApe extends Ape {
     this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
     //this.sendUpdaterClassStatusInfo({"actionType": 0, isStopAllPublishMedia: true});
     this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_WAIT, isStopAllPublishMedia: false});
-    loger.log('restorClass');
   }
 
   // 全局禁言
@@ -400,10 +413,12 @@ class ConferApe extends Ape {
       let timestamp = EngineUtils.creatTimestampStr();
       GlobalConfig.classStopTime = timestamp;
 
+/*
       //如果录制的文件名不存在,需要创建一个名字
       let timestampYMD = EngineUtils.creatTimestampYMD();
       GlobalConfig.recordFileName = GlobalConfig.recordFileName ||
         GlobalConfig.siteId + "/" + timestampYMD + "/" + GlobalConfig.classId + "_" + timestampYMD + ".rec"; //4、文件名称 $RECORD_HOME/`site id`/`日期`/`filename`    例:/data/record/su/20161216/`filename`
+*/
 
       if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_WAIT) {
         //之前是为开始状态,第一次点开始
@@ -418,8 +433,8 @@ class ConferApe extends Ape {
       //同步课堂状态
       //this.sendUpdaterClassStatusInfo({"actionType": 1, isStopAllPublishMedia: true});
       this.sendUpdaterClassStatusInfo({"actionType": ApeConsts.CLASS_STATUS_STARTED, isStopAllPublishMedia: false});
-      //开始计时
-      this.startTimerCounter();
+      ////开始计时
+      //this.startTimerCounter();
     } else {
       loger.warn('没有开始课堂的权限');
     }
@@ -451,7 +466,7 @@ class ConferApe extends Ape {
     loger.warn("调用关闭课堂->");
     this.stopTimerCounter();
     this.restorClass();
-    //把所有人都踢出课堂
+    //停止所有人推流,把所有人都踢出课堂
     this.sendConferMsg({"to": 0, "message": "所有人退出课堂", "actionType": ApeConsts.CLASS_ACTION_CLOSE_ALL});
     this.stopRecord();//关闭课堂的时候停止录制
   }
@@ -557,7 +572,7 @@ class ConferApe extends Ape {
   //更新课堂信息
   sendUpdaterClassStatusInfo(_param) {
     //{"actionType": 1,isStopAllPublishMedia:false}    //actionType课堂状态   isStopAllPublishMedia是否停止当前的所有推流
-    loger.log('发送更新课堂信息->');
+      //loger.log('发送更新课堂信息->');
     if (_param == null || EngineUtils.isEmptyObject(_param)) {
       loger.log('发送更新课堂信息->参数错误');
       this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
@@ -610,21 +625,11 @@ class ConferApe extends Ape {
     }
     loger.log('课堂模块初始完成->当前课堂状态:'+ GlobalConfig.classStatus,"recordStatus:"+GlobalConfig.recordStatus);
     this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1);
-
-    //2秒后执行开始上课和开始录制的判断逻辑
-    clearTimeout(this.startClassTimer);
-    this.startClassTimer=setTimeout(()=>{
-      //开启录制,录制接口中会自动判断是否需要录制
+    this.startTimerCounter();
+    this.startClass();
+    clearTimeout(this.startRecordTimer);
+    this.startRecordTimer=setTimeout(()=>{
       this.startRecord();
-      //如果当前课堂正在进行中,开启计时器
-      if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
-        //开始计时
-        this.startTimerCounter();
-        //this.startRecord();
-      } else {
-        loger.log('自动开始上课->classStatus:', GlobalConfig.classStatus, " isHost:", GlobalConfig.isHost, " isAutoStartClass:", GlobalConfig.isAutoStartClass, " isRecordPlayBack:", GlobalConfig.isRecordPlayBack);
-        this.startClass();
-      }
     },2000);
 
    /* //如果当前课堂正在进行中,开启计时器
@@ -672,7 +677,7 @@ class ConferApe extends Ape {
       //以一定的时间间隔同步课堂内所有人的累积上课时间
       if (GlobalConfig.classTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
         //如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
-        if (GlobalConfig.isHost||this.rosterLen<=1) {
+        if (this.checkHasRecordControl()) {
           //保存数据到Sass
           this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
           //同步消息给其他人
@@ -690,8 +695,23 @@ class ConferApe extends Ape {
         this._emit(MessageTypes.SWITCH_HLS_IP);
       }
     }
+
+
     //更新录制进行时间
+    GlobalConfig.recordTimestamp = GlobalConfig.recordTimestamp + 1;
+    if (this.checkHasRecordControl()) {
+      //以一定的时间间隔同步课堂内所有人的累积上课时间
+      if (GlobalConfig.recordTimestamp % GlobalConfig.updateRecordTimeDelay == 0) {
+        //保存数据到Sass
+        this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE);
+      }
+
+      if (GlobalConfig.recordTimestamp % GlobalConfig.updateClassInfoDelay == 0) {
+        //MCU同步消息给其他人
+        this.sendUpdaterClassStatusInfo({"actionType": GlobalConfig.classStatus, isStopAllPublishMedia: false});
+      }
 
+    }
    /* if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
       GlobalConfig.classTimestamp = GlobalConfig.classTimestamp + 1; //计时
       //老师身份的时候要记录录制的时间
@@ -774,9 +794,11 @@ class ConferApe extends Ape {
   tableUpdateHandler(owner, itemIdx, itemData) {
     try {
       let model = this.unPackPdu(owner, itemIdx, itemData);
-      loger.log("课堂更新->",model);
+      //loger.log("课堂更新->",model.classStatusInfo);
+      //{"itemIdx":720899,"from":976168842,"owner":976168842,"actionType":null,"classStatusInfo":{"nodeId":976168842,"userId":"user_979813","userName":"user_979813","siteId":"markettest","classId":889112694,"className":"ly828-1v1","classType":1,"classStatus":1,"classStartTime":"2017-8-28-16-33-18","classStopTime":"2017-8-29-11-9-28","classTimestamp":1930,"classBeginTime":"2017-08-28 16:00:00","classEndTime":"2017-08-31 18:00:00","recordStatus":false,"recordTimestamp":2825,"recordFileName":"markettest/20170828/889112694_20170828.rec","recordDownloadUrl":"","serverTimestamp":1503976246,"activeDocId":976170739,"activeDocCurPage":1,"isStopAllPublishMedia":false,"currentSceneTableId":0,"silence":false,"silenceUsers":"{}","isEnableDraw":true}}
       //处理课堂更新的信息
       if (model && model.classStatusInfo) {
+          // loger.log("课堂更新->",model.classStatusInfo);
         try {
           model.classStatusInfo.silenceUsers = JSON.parse(model.classStatusInfo.silenceUsers);
         } catch (err) {
@@ -801,13 +823,13 @@ class ConferApe extends Ape {
         return;
       }
 
-      if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
+   /* if (GlobalConfig.classStatus == ApeConsts.CLASS_STATUS_STARTED) {
         //如果课堂在进行中,开始计时器
         this.startTimerCounter();
       } else {
         //停止计时
         this.stopTimerCounter();
-      }
+      }*/
     } catch (err) {
       loger.warn('课堂更新->error', err.message);
     }
@@ -825,8 +847,15 @@ class ConferApe extends Ape {
     switch (chatMsg.actionType) {
       case ApeConsts.CLASS_ACTION_CLOSE_ALL:
         loger.log(chatMsg.message);
+        //关闭之前停止所有推流
+        this._emit(MessageTypes.STOP_ALL_MEDIA_PUBLISH);
         //收到课堂关闭,所有人都退出,执行自己关闭的流程
-        this._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 1});
+        setTimeout(()=>{
+          this._emit(MessageTypes.CLASS_RUN_EXIT, {'type': 1});
+        },2000);
+        break;
+      case ApeConsts.STOP_ALL_PUBLISH:
+        this._emit(MessageTypes.STOP_ALL_MEDIA_PUBLISH);
         break;
       case ApeConsts.CLASS_ACTION_KICK_OUT_ROSTER:
         if (chatMsg.toNodeID == GlobalConfig.nodeId) {
@@ -1116,23 +1145,15 @@ class ConferApe extends Ape {
       //当前人员列表中抽一个人来检查离开人员是否占用频道
       for (let key in this.rosters) {
         let randNodeId = parseInt(key);
-        //如果抽到的人是自己就处理以下操作
+        //判断是否是自己就处理以下操作
         if (randNodeId == GlobalConfig.nodeId) {
-          loger.log(randNodeId, "有权限检查离开的人员是否占用channel");
+          loger.log("检查离开的人员是否占用channel");
           this._emit(MessageTypes.CLASS_NONENTITY_ROSTER, {"nodeId": nodeId, "rosterLen": this.rosterLen});
           //如果离开的人员是老师,需要暂停当前的课堂
-
           if (user && user.role == ApeConsts.NR_HOST) {
             this.pauseClass();
-
-           /* //强制停止录制
-            this.stopRecord(true)*/;
-
           }
-        } else {
-          loger.warn(GlobalConfig.nodeId, "没有权限检查离开的人员是否占用channel");
         }
-        //查找到一个就跳出操作
         return;
       }
     }
@@ -1207,7 +1228,7 @@ class ConferApe extends Ape {
       let modelPdu = pdu['RCClassSendDataModelPdu'].decode(itemData);
       return modelPdu;
     } catch (err) {
-      loger.log("课堂收到数据 unPackPdu Pdu解析错误,itemIdx=" + itemIdx + "  err:" + err.message);
+      loger.log("课堂收到数据解析错误:" + itemIdx + "  err:" + err.message);
     }
     return null;
   }
diff --git a/src/apes/DocApe.js b/src/apes/DocApe.js
index ced70a4..8c38bce 100644
--- a/src/apes/DocApe.js
+++ b/src/apes/DocApe.js
@@ -389,7 +389,7 @@ class DocApe extends Ape {
     docDataModel.animationStep = 1;//切换文档之后动画步数还原
 
     //loger.log('切换文档,当前文档和上一个显示的文档都需要更新状态');
-    loger.log({"oldDoc": oldDocModel, "nowDoc": docDataModel});
+    //loger.log({"oldDoc": oldDocModel, "nowDoc": docDataModel});
     //更新当前选择的文档
     this.updaterDoc(docDataModel, docDataModel.itemIdx);
 
@@ -673,7 +673,7 @@ class DocApe extends Ape {
   }
 
   onJoinChannelHandlerSuccess() {
-    loger.log(this._session_name + ' onJoinChannelHandlerSuccess===========================');
+    //loger.log(this._session_name + ' onJoinChannelHandlerSuccess===========================');
     if (this._apeDelayed) {
       // this._apeDelayedMsgs.push(regBuffer);
       // this._apeDelayedStart();
diff --git a/src/apes/VideoApe.js b/src/apes/VideoApe.js
index 0761585..40a9bba 100644
--- a/src/apes/VideoApe.js
+++ b/src/apes/VideoApe.js
@@ -309,7 +309,7 @@ class VideoApe extends Ape {
 
   //释放nodeId占用的指定的channelId频道
   _releaseChannelForNodeId(nodeId, channelId) {
-    loger.log(nodeId, "_releaseChannelForNodeId-->channelId", channelId);
+    loger.log(nodeId, "停止-->channelId", channelId);
     let channelInfo = this.mediaModule.mediaChannels[channelId];
     if (channelInfo && channelInfo.status == ApeConsts.CHANNEL_STATUS_OPENING) {
       if (channelInfo.fromNodeId == nodeId) {
@@ -480,11 +480,13 @@ class VideoApe extends Ape {
       this._emit(MessageTypes.VIDEO_BROADCAST, videoReceivePdu);
     }
   }
+  //切换了MS,重新更新一下当前正在播放的流地址
+  changeMediaMs(){
 
-
+  }
   tableUpdateHandler(owner, itemIdx, itemData, seek) {
     let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
-    loger.log("tableUpdateHandler->channel", itemIdx, 'mediaType', unpackChannelInfo.mediaType, 'status->', unpackChannelInfo.status, "seek->", seek);
+    loger.log("视频模块数据更新->channel", itemIdx, 'mediaType', unpackChannelInfo.mediaType, 'status->', unpackChannelInfo.status, "seek->", seek);
 
     //****很重要********
     //如果owner的值为0,代表的是这个歌频道已经被释放了(mcu服务端对于占用channel的掉线用户,就是把owner设置为0)
@@ -586,8 +588,6 @@ class VideoApe extends Ape {
         });
       }
     }
-
-
     if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE) {
       //非屏幕共享情况的处理
       MediaModule.allMediaChannelsList[itemIdx] = unpackChannelInfo;
@@ -610,7 +610,7 @@ class VideoApe extends Ape {
         }
         //owner为0就是没有使用
         if(channelInfo.owner==0){
-          channelInfo.status == ApeConsts.CHANNEL_STATUS_RELEASED
+          channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED
         }
         this.sendTableUpdateHandler(channelInfo);
       }