李勇

新增音频禁用控制功能

@@ -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.32.1.20171123"; 66 + GlobalConfig.sdkVersion = "v2.33.6.20171123";
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 //设置
@@ -102,6 +102,7 @@ export default class MessageEntrance extends Emiter { @@ -102,6 +102,7 @@ export default class MessageEntrance extends Emiter {
102 _webRtc.on(MessageTypes.USER_DEVICE_STATUS_CHAANGE, this.userDeviecStatusChange.bind(this)); //监听摄像头和麦克风的开启状态 102 _webRtc.on(MessageTypes.USER_DEVICE_STATUS_CHAANGE, this.userDeviecStatusChange.bind(this)); //监听摄像头和麦克风的开启状态
103 _webRtc.on(MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE, this.mediaPublishStatusChange.bind(this)); //webRtc推流状态发生改变 103 _webRtc.on(MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE, this.mediaPublishStatusChange.bind(this)); //webRtc推流状态发生改变
104 _webRtc.on(WebRtcApe.RE_JOIN_CHANNEL, this._webRtcRejoinChannel.bind(this)); //重先加入音视频频道 104 _webRtc.on(WebRtcApe.RE_JOIN_CHANNEL, this._webRtcRejoinChannel.bind(this)); //重先加入音视频频道
  105 + _webRtc.on(MessageTypes.MEDIA_ENABLED_CHANGE, this._mediaEnabledChange.bind(this)); //音视频禁用状态改变
105 106
106 // Sass平台层 107 // Sass平台层
107 _sass = Sass; 108 _sass = Sass;
@@ -152,6 +153,7 @@ export default class MessageEntrance extends Emiter { @@ -152,6 +153,7 @@ export default class MessageEntrance extends Emiter {
152 //_confer_ape.on(MessageTypes.SWITCH_HLS_IP, this._switchHlsIpHandler.bind(this)); //MS HLS动态选点 153 //_confer_ape.on(MessageTypes.SWITCH_HLS_IP, this._switchHlsIpHandler.bind(this)); //MS HLS动态选点
153 _confer_ape.on(MessageTypes.STOP_ALL_MEDIA_PUBLISH, this._stopAllMediaPublishHandler.bind(this)); //课堂状态发生改变,需要停止当前的所有推流 154 _confer_ape.on(MessageTypes.STOP_ALL_MEDIA_PUBLISH, this._stopAllMediaPublishHandler.bind(this)); //课堂状态发生改变,需要停止当前的所有推流
154 _confer_ape.on(MessageTypes.CLASS_UPDATE_ROSTER, this._onRosterUpdateHandler.bind(this)); 155 _confer_ape.on(MessageTypes.CLASS_UPDATE_ROSTER, this._onRosterUpdateHandler.bind(this));
  156 + _confer_ape.on(MessageTypes.RECEIVE_MEDIA_ENABLED_CHANGE, this._receiveMeiaEnabledChange.bind(this));
155 157
156 _chat_ape = new ChatApe(); 158 _chat_ape = new ChatApe();
157 _chat_ape.on('*', (type, data) => this._emit(type, data)); 159 _chat_ape.on('*', (type, data) => this._emit(type, data));
@@ -651,6 +653,8 @@ export default class MessageEntrance extends Emiter { @@ -651,6 +653,8 @@ export default class MessageEntrance extends Emiter {
651 randUserId = "A" + randUserId; 653 randUserId = "A" + randUserId;
652 } else if (GlobalConfig.userRole == ApeConsts.presenter) { 654 } else if (GlobalConfig.userRole == ApeConsts.presenter) {
653 randUserId = "P" + randUserId; 655 randUserId = "P" + randUserId;
  656 + } else if (GlobalConfig.userRole == ApeConsts.invisible) {
  657 + randUserId = "I" + randUserId;
654 } else { 658 } else {
655 randUserId = "S" + randUserId; 659 randUserId = "S" + randUserId;
656 } 660 }
@@ -700,7 +704,8 @@ export default class MessageEntrance extends Emiter { @@ -700,7 +704,8 @@ export default class MessageEntrance extends Emiter {
700 let autoLoginMd5 = MD5("" + GlobalConfig.classId + GlobalConfig.paramUserId + GlobalConfig.userRole); 704 let autoLoginMd5 = MD5("" + GlobalConfig.classId + GlobalConfig.paramUserId + GlobalConfig.userRole);
701 //let autoLoginMd5 = MD5("" + GlobalConfig.classId + GlobalConfig.userId + GlobalConfig.userRole); 705 //let autoLoginMd5 = MD5("" + GlobalConfig.classId + GlobalConfig.userId + GlobalConfig.userRole);
702 //loger.log("joinClass-GlobalConfig.autoLogin", GlobalConfig.autoLogin, "autoLoginMd5-", autoLoginMd5); 706 //loger.log("joinClass-GlobalConfig.autoLogin", GlobalConfig.autoLogin, "autoLoginMd5-", autoLoginMd5);
703 - if (GlobalConfig.autoLogin && autoLoginMd5 == GlobalConfig.autoLogin || GlobalConfig.isInvisible) { 707 + if ((GlobalConfig.autoLogin && autoLoginMd5 == GlobalConfig.autoLogin) ||
  708 + GlobalConfig.isInvisible||GlobalConfig.isAssistant||GlobalConfig.isPresenter) {
704 // MD5(classId+userId+userRole)==m 709 // MD5(classId+userId+userRole)==m
705 //自动登录,跳过验证流程 710 //自动登录,跳过验证流程
706 loger.log("自动登录->" + GlobalConfig.userRole); 711 loger.log("自动登录->" + GlobalConfig.userRole);
@@ -1404,7 +1409,17 @@ export default class MessageEntrance extends Emiter { @@ -1404,7 +1409,17 @@ export default class MessageEntrance extends Emiter {
1404 _webRtc.tryAddMobileStream(_data.nodeId); 1409 _webRtc.tryAddMobileStream(_data.nodeId);
1405 } 1410 }
1406 } 1411 }
1407 - 1412 + /*
  1413 + * 收到媒体禁用状态切换的消息
  1414 + * */
  1415 + _receiveMeiaEnabledChange(_data){
  1416 + if(!_data||GlobalConfig.isRecordPlayBack||GlobalConfig.isH5){
  1417 + return;
  1418 + }
  1419 + if(_webRtc){
  1420 + _webRtc.webRtcMeiaEnabledChange(_data);
  1421 + }
  1422 + }
1408 //手动切换MS -> {ip;"xxx.xx.xx","port":"xxxx"} 1423 //手动切换MS -> {ip;"xxx.xx.xx","port":"xxxx"}
1409 _switchMediaServer(_param) { 1424 _switchMediaServer(_param) {
1410 if (GlobalConfig.isRecordPlayBack) { 1425 if (GlobalConfig.isRecordPlayBack) {
@@ -2153,6 +2168,17 @@ export default class MessageEntrance extends Emiter { @@ -2153,6 +2168,17 @@ export default class MessageEntrance extends Emiter {
2153 _webRtcRejoinChannel(_data){ 2168 _webRtcRejoinChannel(_data){
2154 this._reJoinChannel(_data) 2169 this._reJoinChannel(_data)
2155 } 2170 }
  2171 + /*
  2172 + * 监听webRtc
  2173 + * */
  2174 + _mediaEnabledChange(_data){
  2175 + if (!_mcu.connected||GlobalConfig.isRecordPlayBack) {
  2176 + return;
  2177 + }
  2178 + if(_confer_ape){
  2179 + _confer_ape.sendMediaEnabledChange(_data);
  2180 + }
  2181 + }
2156 2182
2157 //监听摄像头麦克风状态 2183 //监听摄像头麦克风状态
2158 userDeviecStatusChange(_data) { 2184 userDeviecStatusChange(_data) {
@@ -4,26 +4,28 @@ @@ -4,26 +4,28 @@
4 import Base64 from 'base64-js'; 4 import Base64 from 'base64-js';
5 import UTF8 from 'utf-8'; 5 import UTF8 from 'utf-8';
6 6
7 -class EngineUtils{  
8 - static isEmptyObject(O){  
9 - for (var x in O){ 7 +class EngineUtils {
  8 + static isEmptyObject(O) {
  9 + for (var x in O) {
10 return false; 10 return false;
11 } 11 }
12 return true; 12 return true;
13 } 13 }
14 - static arrayToJsonString(_param){  
15 - try{ 14 +
  15 + static arrayToJsonString(_param) {
  16 + try {
16 return JSON.stringify(_param); 17 return JSON.stringify(_param);
17 - }catch (err){  
18 - console.warn("数组转JSON失败->ERROR:"+err.message); 18 + } catch (err) {
  19 + console.warn("数组转JSON失败->ERROR:" + err.message);
19 } 20 }
20 return ""; 21 return "";
21 } 22 }
22 - static arrayFromJsonString(_param){  
23 - try{ 23 +
  24 + static arrayFromJsonString(_param) {
  25 + try {
24 return JSON.parse(_param); 26 return JSON.parse(_param);
25 - }catch (err){  
26 - console.warn("JSON转数组失败->ERROR:"+err.message); 27 + } catch (err) {
  28 + console.warn("JSON转数组失败->ERROR:" + err.message);
27 } 29 }
28 return []; 30 return [];
29 } 31 }
@@ -31,182 +33,190 @@ class EngineUtils{ @@ -31,182 +33,190 @@ class EngineUtils{
31 /* 33 /*
32 * 生成随机数 _part 段数 默认3段; splitStr分隔符 34 * 生成随机数 _part 段数 默认3段; splitStr分隔符
33 * */ 35 * */
34 - static creatRandomNum(_part=3,splitStr=""){  
35 - let randNumStr="";  
36 - for(let i=0;i<_part;i++){  
37 - randNumStr+=splitStr+parseInt(Math.random()*1000); 36 + static creatRandomNum(_part = 3, splitStr = "") {
  37 + let randNumStr = "";
  38 + for (let i = 0; i < _part; i++) {
  39 + randNumStr += splitStr + parseInt(Math.random() * 1000);
38 } 40 }
39 return randNumStr; 41 return randNumStr;
40 } 42 }
41 43
42 //生成时间戳后9位 保证唯一 44 //生成时间戳后9位 保证唯一
43 - static creatSoleNumberFromTimestamp(){ 45 + static creatSoleNumberFromTimestamp() {
44 let time = new Date().getTime(); 46 let time = new Date().getTime();
45 - let timestamp= time % 1000000000;//time后9位 47 + let timestamp = time % 1000000000;//time后9位
46 return timestamp; 48 return timestamp;
47 } 49 }
48 50
49 //生成时间戳毫秒 51 //生成时间戳毫秒
50 - static creatTimestamp(){  
51 - let time = parseInt(new Date().getTime()/1000);//精确到秒 52 + static creatTimestamp() {
  53 + let time = parseInt(new Date().getTime() / 1000);//精确到秒
52 return time; 54 return time;
53 } 55 }
  56 +
54 //生成时间戳 string 57 //生成时间戳 string
55 - static creatTimestampStr(){ 58 + static creatTimestampStr() {
56 let curTime = new Date(); 59 let curTime = new Date();
57 let timeStr = "" + curTime.getFullYear() + "-"; 60 let timeStr = "" + curTime.getFullYear() + "-";
58 - timeStr += (curTime.getMonth()+1) + "-"; 61 + timeStr += (curTime.getMonth() + 1) + "-";
59 timeStr += curTime.getDate() + "-"; 62 timeStr += curTime.getDate() + "-";
60 - timeStr+=curTime.getHours() + "-";  
61 - timeStr+=curTime.getMinutes() + "-";  
62 - timeStr+=curTime.getSeconds(); 63 + timeStr += curTime.getHours() + "-";
  64 + timeStr += curTime.getMinutes() + "-";
  65 + timeStr += curTime.getSeconds();
63 return timeStr; 66 return timeStr;
64 } 67 }
  68 +
65 //根据时间戳字符串转换为时间戳 2017-10-27-15-38-15 69 //根据时间戳字符串转换为时间戳 2017-10-27-15-38-15
66 - static getTimestampFromStr(_timeStr){  
67 - if(!_timeStr) return this.creatTimestamp();  
68 - let timeArr=_timeStr.split("_");  
69 - if(timeArr&&timeArr.length==6){  
70 - return parseInt( new Date(timeArr[0],parseInt(timeArr[1])-1,timeArr[2],timeArr[3],timeArr[4],timeArr[5]).getTime()/1000); 70 + static getTimestampFromStr(_timeStr) {
  71 + if (!_timeStr) return this.creatTimestamp();
  72 + let timeArr = _timeStr.split("_");
  73 + if (timeArr && timeArr.length == 6) {
  74 + return parseInt(new Date(timeArr[0], parseInt(timeArr[1]) - 1, timeArr[2], timeArr[3], timeArr[4], timeArr[5]).getTime() / 1000);
71 } 75 }
72 return this.creatTimestamp(); 76 return this.creatTimestamp();
73 } 77 }
  78 +
74 //生成时间戳 格式:"20170209" 79 //生成时间戳 格式:"20170209"
75 - static creatTimestampYMD(){ 80 + static creatTimestampYMD() {
76 let curTime = new Date(); 81 let curTime = new Date();
77 let year = "" + curTime.getFullYear(); 82 let year = "" + curTime.getFullYear();
78 - let month = "" +(curTime.getMonth()+1); 83 + let month = "" + (curTime.getMonth() + 1);
79 let day = "" + curTime.getDate(); 84 let day = "" + curTime.getDate();
80 85
81 - if(month.length<2){  
82 - month="0"+month; 86 + if (month.length < 2) {
  87 + month = "0" + month;
83 } 88 }
84 - if(day.length<2){  
85 - day="0"+day; 89 + if (day.length < 2) {
  90 + day = "0" + day;
86 } 91 }
87 - return year+month+day; 92 + return year + month + day;
88 } 93 }
89 - static objectToBase64(_object){  
90 - try{  
91 - let _objectStr=JSON.stringify(_object); 94 +
  95 + static objectToBase64(_object) {
  96 + try {
  97 + let _objectStr = JSON.stringify(_object);
92 //console.log("objectToBase64------1----------") 98 //console.log("objectToBase64------1----------")
93 - let byte=UTF8.setBytesFromString(_objectStr); 99 + let byte = UTF8.setBytesFromString(_objectStr);
94 //console.log("objectToBase64------2----------") 100 //console.log("objectToBase64------2----------")
95 - let _objectBase64=Base64.fromByteArray(byte); 101 + let _objectBase64 = Base64.fromByteArray(byte);
96 return _objectBase64 102 return _objectBase64
97 - }catch (err){  
98 - console.log("objectToBase64 err:"+err.message); 103 + } catch (err) {
  104 + console.log("objectToBase64 err:" + err.message);
99 return ""; 105 return "";
100 } 106 }
101 return "" 107 return ""
102 } 108 }
103 - static objectFromBase64(_objectBase64){  
104 - try{  
105 - let byte=Base64.toByteArray(_objectBase64);  
106 - let _objectStr=UTF8.getStringFromBytes(byte);  
107 - let _object=JSON.parse(_objectStr); 109 +
  110 + static objectFromBase64(_objectBase64) {
  111 + try {
  112 + let byte = Base64.toByteArray(_objectBase64);
  113 + let _objectStr = UTF8.getStringFromBytes(byte);
  114 + let _object = JSON.parse(_objectStr);
108 return _object 115 return _object
109 - }catch (err){  
110 - console.log("objectFromBase64 err:"+err.message); 116 + } catch (err) {
  117 + console.log("objectFromBase64 err:" + err.message);
111 return null; 118 return null;
112 } 119 }
113 return null; 120 return null;
114 } 121 }
  122 +
115 //优化压缩坐标点数组,去除一些连续重复坐标的点,返回一个数组 123 //优化压缩坐标点数组,去除一些连续重复坐标的点,返回一个数组
116 - static compressPoint(_arr){  
117 - if(!_arr){ 124 + static compressPoint(_arr) {
  125 + if (!_arr) {
118 return []; 126 return [];
119 } 127 }
120 - if(_arr.length<5){ 128 + if (_arr.length < 5) {
121 //点,直线,矩形 坐标点小于5不需要处理 129 //点,直线,矩形 坐标点小于5不需要处理
122 return _arr; 130 return _arr;
123 } 131 }
124 - let tempPointArr=_arr;  
125 - let newPointArr=[]; 132 + let tempPointArr = _arr;
  133 + let newPointArr = [];
126 newPointArr.push(tempPointArr[0]); 134 newPointArr.push(tempPointArr[0]);
127 - let lastW=tempPointArr[0].w;  
128 - let continueNum=0;//坐标相同的连续次数 135 + let lastW = tempPointArr[0].w;
  136 + let continueNum = 0;//坐标相同的连续次数
129 //先筛除水平方向的连续重复坐标点 137 //先筛除水平方向的连续重复坐标点
130 - let len=tempPointArr.length-1;  
131 - for(let i=1;i<len;i++){  
132 - let item=tempPointArr[i];  
133 - if(item&&item.w!=lastW){  
134 - lastW=item.w;  
135 - if(continueNum>0){  
136 - newPointArr.push(tempPointArr[i-1]); 138 + let len = tempPointArr.length - 1;
  139 + for (let i = 1; i < len; i++) {
  140 + let item = tempPointArr[i];
  141 + if (item && item.w != lastW) {
  142 + lastW = item.w;
  143 + if (continueNum > 0) {
  144 + newPointArr.push(tempPointArr[i - 1]);
137 } 145 }
138 newPointArr.push(item); 146 newPointArr.push(item);
139 - continueNum=0;  
140 - }else { 147 + continueNum = 0;
  148 + } else {
141 continueNum++; 149 continueNum++;
142 } 150 }
143 } 151 }
144 //如果最终的坐标点数量小于2,需要把最后一个坐标点添加 152 //如果最终的坐标点数量小于2,需要把最后一个坐标点添加
145 - if(tempPointArr[len]){ 153 + if (tempPointArr[len]) {
146 newPointArr.push(tempPointArr[len]); 154 newPointArr.push(tempPointArr[len]);
147 } 155 }
148 //如果坐标点已经小于等于2不需要继续检测 156 //如果坐标点已经小于等于2不需要继续检测
149 - if(newPointArr.length<=2){ 157 + if (newPointArr.length <= 2) {
150 return newPointArr; 158 return newPointArr;
151 } 159 }
152 160
153 //筛除水垂直向的连续重复坐标点 161 //筛除水垂直向的连续重复坐标点
154 - let finalPointArr=[]; 162 + let finalPointArr = [];
155 finalPointArr.push(newPointArr[0]); 163 finalPointArr.push(newPointArr[0]);
156 - let lastH=newPointArr[0].h;  
157 - continueNum=0;  
158 - len=newPointArr.length-1;  
159 - for(let k=1;k<len;k++){  
160 - let item=newPointArr[k];  
161 - if(item&&item.h!=lastH){  
162 - lastH=item.h;  
163 - if(continueNum>0){  
164 - finalPointArr.push(newPointArr[k-1]); 164 + let lastH = newPointArr[0].h;
  165 + continueNum = 0;
  166 + len = newPointArr.length - 1;
  167 + for (let k = 1; k < len; k++) {
  168 + let item = newPointArr[k];
  169 + if (item && item.h != lastH) {
  170 + lastH = item.h;
  171 + if (continueNum > 0) {
  172 + finalPointArr.push(newPointArr[k - 1]);
165 } 173 }
166 finalPointArr.push(item); 174 finalPointArr.push(item);
167 - continueNum=0;  
168 - }else { 175 + continueNum = 0;
  176 + } else {
169 continueNum++; 177 continueNum++;
170 } 178 }
171 } 179 }
172 - if(newPointArr[len]){ 180 + if (newPointArr[len]) {
173 finalPointArr.push(newPointArr[len]); 181 finalPointArr.push(newPointArr[len]);
174 } 182 }
175 return finalPointArr; 183 return finalPointArr;
176 } 184 }
  185 +
177 //压缩数据,把坐标点数组转换为字符串,返回字符串 186 //压缩数据,把坐标点数组转换为字符串,返回字符串
178 - static optimizePoint(_pointGroup){  
179 - if(!_pointGroup){ 187 + static optimizePoint(_pointGroup) {
  188 + if (!_pointGroup) {
180 return ""; 189 return "";
181 } 190 }
182 - let tempStr=""; 191 + let tempStr = "";
183 try { 192 try {
184 - tempStr=JSON.stringify(_pointGroup);  
185 - }catch (err){ 193 + tempStr = JSON.stringify(_pointGroup);
  194 + } catch (err) {
186 return ""; 195 return "";
187 } 196 }
188 - let regexp1=/},{"w":/g;  
189 - let regexp2=/,"h":/g;  
190 - tempStr=tempStr.replace(regexp1,"#");  
191 - tempStr=tempStr.replace(regexp2,"&"); 197 + let regexp1 = /},{"w":/g;
  198 + let regexp2 = /,"h":/g;
  199 + tempStr = tempStr.replace(regexp1, "#");
  200 + tempStr = tempStr.replace(regexp2, "&");
192 //console.log("标注压缩后的字符长度->",tempStr.length); 201 //console.log("标注压缩后的字符长度->",tempStr.length);
193 return tempStr; 202 return tempStr;
194 } 203 }
  204 +
195 //把字符串坐标点集合转换为数组,返回数组的JSON 205 //把字符串坐标点集合转换为数组,返回数组的JSON
196 - static unPackOptimizePoint(_str){  
197 - if(!_str){ 206 + static unPackOptimizePoint(_str) {
  207 + if (!_str) {
198 return ""; 208 return "";
199 } 209 }
200 - let tempStr=_str;  
201 - let regexp1=/#/g;  
202 - let regexp2=/&/g;  
203 - tempStr=tempStr.replace(regexp1,'},{"w":');  
204 - tempStr=tempStr.replace(regexp2,',"h":'); 210 + let tempStr = _str;
  211 + let regexp1 = /#/g;
  212 + let regexp2 = /&/g;
  213 + tempStr = tempStr.replace(regexp1, '},{"w":');
  214 + tempStr = tempStr.replace(regexp2, ',"h":');
205 215
206 - let dataArr=[]; 216 + let dataArr = [];
207 try { 217 try {
208 - dataArr=JSON.parse(tempStr);  
209 - }catch (err){ 218 + dataArr = JSON.parse(tempStr);
  219 + } catch (err) {
210 220
211 } 221 }
212 return dataArr; 222 return dataArr;
@@ -111,6 +111,8 @@ MessageTypes.WEB_RTC_JOIN_FAILED = "web_rtc_join_failed"; @@ -111,6 +111,8 @@ MessageTypes.WEB_RTC_JOIN_FAILED = "web_rtc_join_failed";
111 MessageTypes.WEB_RTC_PUBLISH_FAILED = "web_rtc_publish_failed"; 111 MessageTypes.WEB_RTC_PUBLISH_FAILED = "web_rtc_publish_failed";
112 MessageTypes.GET_DEVICES_SUCCESS = "get_devices_success"; 112 MessageTypes.GET_DEVICES_SUCCESS = "get_devices_success";
113 MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE = "media_publish_status_change";//音视频推流的状态发生改变 113 MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE = "media_publish_status_change";//音视频推流的状态发生改变
  114 +MessageTypes.MEDIA_ENABLED_CHANGE = "media_enabled_change";//媒体禁用或开启状态改变
  115 +MessageTypes.RECEIVE_MEDIA_ENABLED_CHANGE = "receive_media_enabled_change";//收到媒体禁用状态控制的消息
114 116
115 //MCU MS 117 //MCU MS
116 MessageTypes.SWITCH_MCU_IP = "switch_mcu_ip"; //切换mcu 重新选点 118 MessageTypes.SWITCH_MCU_IP = "switch_mcu_ip"; //切换mcu 重新选点
@@ -27,6 +27,8 @@ ApeConsts.USER_ACTION_SILENCE_STATUS_CHANGE = 3; //更改用户的禁言状态 @@ -27,6 +27,8 @@ ApeConsts.USER_ACTION_SILENCE_STATUS_CHANGE = 3; //更改用户的禁言状态
27 ApeConsts.CLASS_ACTION_KICK_OUT_ROSTER=4; //指定的人踢出课堂 27 ApeConsts.CLASS_ACTION_KICK_OUT_ROSTER=4; //指定的人踢出课堂
28 ApeConsts.STOP_ALL_PUBLISH=5; //所有人停止推流 28 ApeConsts.STOP_ALL_PUBLISH=5; //所有人停止推流
29 ApeConsts.CLASS_ACTION_DRAW_STATUS_CHANGE = 6; //更改用户的画笔状态 29 ApeConsts.CLASS_ACTION_DRAW_STATUS_CHANGE = 6; //更改用户的画笔状态
  30 +ApeConsts.MEDIA_ENABLED_CHANGE = 7; //更改用户的音视频禁用状态
  31 +
30 32
31 //课堂类型 1:1v1(2路流) 2:直播(1路流) 3:小班课(可以多路流) 33 //课堂类型 1:1v1(2路流) 2:直播(1路流) 3:小班课(可以多路流)
32 ApeConsts.CLASS_TYPE_1v1 = 1; // 互动课堂,通过MS转发音视频,不能进行H5观看 1v1(2路流) 34 ApeConsts.CLASS_TYPE_1v1 = 1; // 互动课堂,通过MS转发音视频,不能进行H5观看 1v1(2路流)
@@ -855,6 +855,17 @@ class ConferApe extends Ape { @@ -855,6 +855,17 @@ class ConferApe extends Ape {
855 loger.warn('chatMsg->JSON数据解析失败'); 855 loger.warn('chatMsg->JSON数据解析失败');
856 } 856 }
857 break; 857 break;
  858 + case ApeConsts.MEDIA_ENABLED_CHANGE:
  859 + let mediaMsgObj = null;
  860 + try {
  861 + mediaMsgObj = JSON.parse(chatMsg.message);
  862 + if (mediaMsgObj) {
  863 + this.receiveChangeUserMediaEnabledStatus(mediaMsgObj);
  864 + }
  865 + } catch (err) {
  866 + loger.warn('chatMsg->JSON数据解析失败',chatMsg.message);
  867 + }
  868 + break;
858 default: 869 default:
859 break; 870 break;
860 } 871 }
@@ -1028,6 +1039,11 @@ class ConferApe extends Ape { @@ -1028,6 +1039,11 @@ class ConferApe extends Ape {
1028 loger.log("监课进入或更新数据"); 1039 loger.log("监课进入或更新数据");
1029 return; 1040 return;
1030 } 1041 }
  1042 + if (nodeData.role == ApeConsts.NR_ASSISTANT && GlobalConfig.userRole != ApeConsts.invisible && GlobalConfig.userRole != ApeConsts.assistant) {
  1043 + loger.log("助教进入或更新数据");
  1044 + return;
  1045 + }
  1046 +
1031 if (!rosterExists) { 1047 if (!rosterExists) {
1032 //this.rosterLen = Object.keys(this.rosters).length; 1048 //this.rosterLen = Object.keys(this.rosters).length;
1033 //GlobalConfig.rosterNum = this.rosterLen;//记录当前的总人数 1049 //GlobalConfig.rosterNum = this.rosterLen;//记录当前的总人数
@@ -1091,11 +1107,36 @@ class ConferApe extends Ape { @@ -1091,11 +1107,36 @@ class ConferApe extends Ape {
1091 } 1107 }
1092 } 1108 }
1093 1109
1094 - //设备状态更新 1110 + /*
  1111 + * 设备状态更新
  1112 + * */
1095 updaterUserDeviecStatusChange(_data) { 1113 updaterUserDeviecStatusChange(_data) {
1096 loger.log("音视频设备状态更新->", _data); 1114 loger.log("音视频设备状态更新->", _data);
1097 this.updateUserInfo(); 1115 this.updateUserInfo();
1098 } 1116 }
  1117 + /*
  1118 + * 媒体开启或禁用
  1119 + * */
  1120 + sendMediaEnabledChange(_data){
  1121 + if(!_data){
  1122 + return;
  1123 + }
  1124 +
  1125 + try{
  1126 + loger.log("发送->媒体开启或禁用",_data);
  1127 + this.sendConferMsg({"to": 0, "message":JSON.stringify(_data), "actionType": ApeConsts.MEDIA_ENABLED_CHANGE});
  1128 + }catch (err){
  1129 + loger.warn("发送->媒体开启或禁用->失败",_data,err.message);
  1130 + }
  1131 +
  1132 + }
  1133 +
  1134 + /*
  1135 + * 收到媒体开启或禁用控制
  1136 + * */
  1137 + receiveChangeUserMediaEnabledStatus(_data){
  1138 + this._emit(MessageTypes.RECEIVE_MEDIA_ENABLED_CHANGE,_data);
  1139 + }
1099 1140
1100 //删除用户 1141 //删除用户
1101 rosterDelHandler(nodeId) { 1142 rosterDelHandler(nodeId) {
@@ -1114,12 +1155,9 @@ class ConferApe extends Ape { @@ -1114,12 +1155,9 @@ class ConferApe extends Ape {
1114 if(GlobalConfig.classType!= ApeConsts.CLASS_TYPE_ZHIBO){ 1155 if(GlobalConfig.classType!= ApeConsts.CLASS_TYPE_ZHIBO){
1115 loger.log(nodeId, "->离开课堂->身份->", user.userRole); 1156 loger.log(nodeId, "->离开课堂->身份->", user.userRole);
1116 } 1157 }
1117 -  
1118 } 1158 }
1119 delete this.rosters[nodeId]; 1159 delete this.rosters[nodeId];
1120 GlobalConfig.rosters = this.rosters; 1160 GlobalConfig.rosters = this.rosters;
1121 - //this.rosterLen = Object.keys(this.rosters).length;  
1122 - //GlobalConfig.rosterNum = this.rosterLen;//记录当前的总人数  
1123 1161
1124 if(!GlobalConfig.isH5) { 1162 if(!GlobalConfig.isH5) {
1125 this.emitRosterChange(); 1163 this.emitRosterChange();
1 //* 1 //*
2 // WebRtc 2 // WebRtc
3 // */ 3 // */
  4 +require('../assets/css/mcuStyle.css');
  5 +
4 import Emiter from 'Emiter'; 6 import Emiter from 'Emiter';
5 import Loger from "Loger"; 7 import Loger from "Loger";
6 import $ from "jquery"; 8 import $ from "jquery";
@@ -10,12 +12,13 @@ import EngineUtils from 'EngineUtils'; @@ -10,12 +12,13 @@ import EngineUtils from 'EngineUtils';
10 import MessageTypes from 'MessageTypes'; 12 import MessageTypes from 'MessageTypes';
11 var AgoraRTC = require('../AgoraRTCSDK-1.14.0'); 13 var AgoraRTC = require('../AgoraRTCSDK-1.14.0');
12 let loger = Loger.getLoger('WebRtcApe'); 14 let loger = Loger.getLoger('WebRtcApe');
13 -const SIZE_480=480;  
14 -const SIZE_360=360;  
15 -const SIZE_320=320;  
16 -const SIZE_240=240;  
17 -const SIZE_160=160;  
18 -const SIZE_120=120; 15 +const SIZE_480 = 480;
  16 +const SIZE_360 = 360;
  17 +const SIZE_320 = 320;
  18 +const SIZE_240 = 240;
  19 +const SIZE_160 = 160;
  20 +const SIZE_120 = 120;
  21 +
19 class WebRtcApe extends Emiter { 22 class WebRtcApe extends Emiter {
20 constructor() { 23 constructor() {
21 super(); 24 super();
@@ -24,10 +27,10 @@ class WebRtcApe extends Emiter { @@ -24,10 +27,10 @@ class WebRtcApe extends Emiter {
24 this.appCertificate = ""; 27 this.appCertificate = "";
25 this.appRecordingKey = ""; 28 this.appRecordingKey = "";
26 29
27 - this.setConfigTimestamp=0;//设置旁路地址的时间戳 30 + this.setConfigTimestamp = 0;//设置旁路地址的时间戳
28 this.configPublisherUrl = "";//旁路地址; 31 this.configPublisherUrl = "";//旁路地址;
29 - this.m3u8Url="";//旁路拉流地址  
30 - this.rtmpUrl="";//旁路拉流地址 32 + this.m3u8Url = "";//旁路拉流地址
  33 + this.rtmpUrl = "";//旁路拉流地址
31 34
32 this.channelKey = null; 35 this.channelKey = null;
33 this.channelId = ""; 36 this.channelId = "";
@@ -47,10 +50,10 @@ class WebRtcApe extends Emiter { @@ -47,10 +50,10 @@ class WebRtcApe extends Emiter {
47 50
48 this.remoteVideoList = {};//记录远程视频流 51 this.remoteVideoList = {};//记录远程视频流
49 52
50 - this.pWidth=SIZE_480;  
51 - this.pHeight=SIZE_360;  
52 - this.pFrameRate=30;  
53 - this.pBitrate=500; 53 + this.pWidth = SIZE_480;
  54 + this.pHeight = SIZE_360;
  55 + this.pFrameRate = 30;
  56 + this.pBitrate = 500;
54 57
55 //120P 0 160x120 15 65 58 //120P 0 160x120 15 65
56 //240P 20 320x240 15 200 59 //240P 20 320x240 15 200
@@ -58,10 +61,10 @@ class WebRtcApe extends Emiter { @@ -58,10 +61,10 @@ class WebRtcApe extends Emiter {
58 this.videoResolution = "240P"; 61 this.videoResolution = "240P";
59 this.isOpenVideo = true; 62 this.isOpenVideo = true;
60 63
61 - this.firstPublishSuccess=false;//记录加入频道成功之后是否推流成功过,离开频道之后需要设置为false 64 + this.firstPublishSuccess = false;//记录加入频道成功之后是否推流成功过,离开频道之后需要设置为false
62 65
63 this.isPublish = false;//当前是否正在推流 66 this.isPublish = false;//当前是否正在推流
64 - this.videoScale=1;//视图的缩放比例,默认为1; 67 + this.videoScale = 1;//视图的缩放比例,默认为1;
65 68
66 69
67 this.normalRemoteViewId = ""; 70 this.normalRemoteViewId = "";
@@ -85,10 +88,10 @@ class WebRtcApe extends Emiter { @@ -85,10 +88,10 @@ class WebRtcApe extends Emiter {
85 this.invisibleVideoHeight = SIZE_360; 88 this.invisibleVideoHeight = SIZE_360;
86 this.xdyRemote = "xdy_remote"; 89 this.xdyRemote = "xdy_remote";
87 90
88 - this.localWebRtcVideoClass='localWebRtcVideoClass';//本地视图统一的class名称  
89 - this.invisibleWebRtcVideoClass='invisibleWebRtcVideoClass';  
90 - this.normalWebRtcVideoClass='normalWebRtcVideoClass';  
91 - this.hostWebRtcVideoClass='hostWebRtcVideoClass'; 91 + this.localWebRtcVideoClass = 'localWebRtcVideoClass';//本地视图统一的class名称
  92 + this.invisibleWebRtcVideoClass = 'invisibleWebRtcVideoClass';
  93 + this.normalWebRtcVideoClass = 'normalWebRtcVideoClass';
  94 + this.hostWebRtcVideoClass = 'hostWebRtcVideoClass';
92 95
93 //webRtc sdk 96 //webRtc sdk
94 this.client = AgoraRTC.createClient({mode: this.mode}); 97 this.client = AgoraRTC.createClient({mode: this.mode});
@@ -146,7 +149,7 @@ class WebRtcApe extends Emiter { @@ -146,7 +149,7 @@ class WebRtcApe extends Emiter {
146 this.client.on('stream-published', (evt)=> { 149 this.client.on('stream-published', (evt)=> {
147 loger.log("webRtc->推流成功->", new Date().getTime()); 150 loger.log("webRtc->推流成功->", new Date().getTime());
148 this.isPublish = true; 151 this.isPublish = true;
149 - this.firstPublishSuccess=true; 152 + this.firstPublishSuccess = true;
150 GlobalConfig.openCamera = EngineUtils.creatTimestamp(); 153 GlobalConfig.openCamera = EngineUtils.creatTimestamp();
151 GlobalConfig.openMicrophones = GlobalConfig.openCamera; 154 GlobalConfig.openMicrophones = GlobalConfig.openCamera;
152 this._emit(MessageTypes.USER_DEVICE_STATUS_CHAANGE, { 155 this._emit(MessageTypes.USER_DEVICE_STATUS_CHAANGE, {
@@ -208,41 +211,47 @@ class WebRtcApe extends Emiter { @@ -208,41 +211,47 @@ class WebRtcApe extends Emiter {
208 } 211 }
209 212
210 //添加之前先删除之前存在的重复视图 213 //添加之前先删除之前存在的重复视图
211 - let len=$("#"+this.xdyRemote + uid+" #player_" + uid).length;  
212 - if(len<1){  
213 - loger.log("添加之前先删除之前存在的重复视图",uid);  
214 - $("#"+this.xdyRemote + uid).remove(); 214 + let len = $("#" + this.xdyRemote + uid + " #player_" + uid).length;
  215 + if (len < 1) {
  216 + loger.log("添加之前先删除之前存在的重复视图", uid);
  217 + $("#" + this.xdyRemote + uid).remove();
  218 + }
  219 + let audioMutedDiv = "";
  220 + if (GlobalConfig.isTeachOrAssistant || GlobalConfig.isInvisible) {
  221 + audioMutedDiv = `<div class="audioMuted audioOpen" id=${"audioMuted_"+uid}></div>`;
215 } 222 }
216 223
217 if (userRole == ApeConsts.invisible) { 224 if (userRole == ApeConsts.invisible) {
218 - let nameDiv = `<div style=${this.invisibleVideoWidth}px;height:20px; position: absolute;bottom: 0; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; color: #cccccc;display:${this.nameDisplay}">${userName}</div>`; 225 + let nameDiv = `<div style=${this.invisibleVideoWidth}px;height:22px; position: absolute;bottom: 2px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; vertical-align: middle;background-color: #2926251a;color: #e7e7e7display:${this.nameDisplay}">${userName + audioMutedDiv}</div>`;
219 //把远程视频添加到监课列表 226 //把远程视频添加到监课列表
220 loger.log("获取远程视频流成功->监课:" + userName + "->" + uid, new Date().getTime()); 227 loger.log("获取远程视频流成功->监课:" + userName + "->" + uid, new Date().getTime());
221 - let viewDiv = `<div id="${this.xdyRemote + uid}" class="${this.invisibleWebRtcVideoClass}" style="width:${this.invisibleVideoWidth*this.videoScale}px;height:${this.invisibleVideoHeight*this.videoScale}px;float: left;margin-right: 1px;pointer-events: none;">${nameDiv}</div>`; 228 + let viewDiv = `<div id="${this.xdyRemote + uid}" class="${this.invisibleWebRtcVideoClass}" style="width:${this.invisibleVideoWidth * this.videoScale}px;height:${this.invisibleVideoHeight * this.videoScale}px;float: left;margin-right: 1px;">${nameDiv}</div>`;
222 $(this.invisibleViewId).append(viewDiv); 229 $(this.invisibleViewId).append(viewDiv);
223 - } else if (userRole == ApeConsts.host||userRole == ApeConsts.assistant||userRole == ApeConsts.presenter) {  
224 - let nameDiv = `<div style="width:${this.hostRemoteVideoWidth}px;height:20px; position: absolute;bottom: 0; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; color: #cccccc;display:${this.nameDisplay}">${userName}</div>`; 230 + } else if (userRole == ApeConsts.host || userRole == ApeConsts.assistant || userRole == ApeConsts.presenter) {
  231 + let nameDiv = `<div style="width:${this.hostRemoteVideoWidth}px;height:22px; position: absolute;bottom: 2px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right;vertical-align: middle; background-color: #2926251a;color: #e7e7e7;display:${this.nameDisplay}">${userName + audioMutedDiv}</div>`;
225 //把远程视图添加到老师列表 232 //把远程视图添加到老师列表
226 - loger.log("获取远程视频流成功->userRole:"+userRole+":" + userName + "->" + uid, new Date().getTime());  
227 - let viewDiv = `<div id="${this.xdyRemote + uid}" class="${this.hostWebRtcVideoClass}" style="width:${this.hostRemoteVideoWidth*this.videoScale}px;height:${this.hostRemoteVideoHeight*this.videoScale}px;float: left;margin-right: 1px;pointer-events: none;">${nameDiv}</div>`; 233 + loger.log("获取远程视频流成功->userRole:" + userRole + ":" + userName + "->" + uid, new Date().getTime());
  234 + let viewDiv = `<div id="${this.xdyRemote + uid}" class="${this.hostWebRtcVideoClass}" style="width:${this.hostRemoteVideoWidth * this.videoScale}px;height:${this.hostRemoteVideoHeight * this.videoScale}px;float: left;margin-right: 1px;">${nameDiv}</div>`;
228 $(this.hostRemoteViewId).prepend(viewDiv); 235 $(this.hostRemoteViewId).prepend(viewDiv);
229 } else { 236 } else {
230 - let nameDiv = `<div style="width:${this.normalRemoteVideoWidth}px;height:20px; position: absolute;bottom: 0; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; color: #cccccc;display:${this.nameDisplay}">${userName}</div>`; 237 + let nameDiv = `<div style="width:${this.normalRemoteVideoWidth}px;height:22px; position: absolute;bottom: 2px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right;vertical-align: middle;background-color: #2926251a;color: #e7e7e7;display:${this.nameDisplay}">${userName + audioMutedDiv}</div>`;
231 //把视图添加到学生列表 238 //把视图添加到学生列表
232 loger.log("获取远程视频流成功->学生:" + userName + "->" + uid, new Date().getTime()); 239 loger.log("获取远程视频流成功->学生:" + userName + "->" + uid, new Date().getTime());
233 - let viewDiv = `<div id="${this.xdyRemote + uid}" class="${this.normalWebRtcVideoClass}" style="width:${this.normalRemoteVideoWidth*this.videoScale}px;height:${this.normalRemoteVideoHeight*this.videoScale}px;float: left;margin-right: 1px;pointer-events: none;">${nameDiv}</div>`; 240 + let viewDiv = `<div id="${this.xdyRemote + uid}" class="${this.normalWebRtcVideoClass}" style="width:${this.normalRemoteVideoWidth * this.videoScale}px;height:${this.normalRemoteVideoHeight * this.videoScale}px;float: left;margin-right: 1px;">${nameDiv}</div>`;
234 $(this.normalRemoteViewId).append(viewDiv); 241 $(this.normalRemoteViewId).append(viewDiv);
235 } 242 }
  243 + $("#audioMuted_" + uid).off("click", this._clickAudioMuted.bind(this));
  244 + $("#audioMuted_" + uid).on("click", this._clickAudioMuted.bind(this));
236 //播放视频,隐藏控制条 245 //播放视频,隐藏控制条
237 try { 246 try {
238 - $("bar_" + stream.getId()).hide(); 247 + $("#bar_" + stream.getId()).hide();
239 stream.play(this.xdyRemote + stream.getId()); 248 stream.play(this.xdyRemote + stream.getId());
240 } catch (err) { 249 } catch (err) {
241 //添加之前先删除之前存在的重复视图 250 //添加之前先删除之前存在的重复视图
242 - let len=$("#"+this.xdyRemote + uid+" #player_" + uid).length;  
243 - if(len<1){  
244 - lloger.log("流播放失败->删除视图",uid);  
245 - $("#"+this.xdyRemote + uid).remove(); 251 + let len = $("#" + this.xdyRemote + uid + " #player_" + uid).length;
  252 + if (len < 1) {
  253 + loger.log("流播放失败->删除视图", uid);
  254 + $("#" + this.xdyRemote + uid).remove();
246 } 255 }
247 } 256 }
248 if (user && (user.deviceType == GlobalConfig.deviceIOS || user.deviceType == GlobalConfig.deviceAndroid)) { 257 if (user && (user.deviceType == GlobalConfig.deviceIOS || user.deviceType == GlobalConfig.deviceAndroid)) {
@@ -252,43 +261,44 @@ class WebRtcApe extends Emiter { @@ -252,43 +261,44 @@ class WebRtcApe extends Emiter {
252 261
253 this.clearInvalidVideoView(); 262 this.clearInvalidVideoView();
254 } 263 }
  264 +
255 //清除无效的视图 265 //清除无效的视图
256 - clearInvalidVideoView(){  
257 - let normalList=document.getElementsByClassName(this.normalWebRtcVideoClass);  
258 - let hostList=document.getElementsByClassName(this.hostWebRtcVideoClass);  
259 - let localList=document.getElementsByClassName(this.localWebRtcVideoClass);  
260 -  
261 - let divItem=null;  
262 - if(normalList){  
263 - for (let i=normalList.length-1;i>=0;i--){  
264 - divItem=normalList[i];  
265 - if(divItem&&divItem.children.length<2){ 266 + clearInvalidVideoView() {
  267 + let normalList = document.getElementsByClassName(this.normalWebRtcVideoClass);
  268 + let hostList = document.getElementsByClassName(this.hostWebRtcVideoClass);
  269 + let localList = document.getElementsByClassName(this.localWebRtcVideoClass);
  270 +
  271 + let divItem = null;
  272 + if (normalList) {
  273 + for (let i = normalList.length - 1; i >= 0; i--) {
  274 + divItem = normalList[i];
  275 + if (divItem && divItem.children.length < 2) {
266 console.log("删除无效的学生视图"); 276 console.log("删除无效的学生视图");
267 divItem.remove(); 277 divItem.remove();
268 } 278 }
269 } 279 }
270 } 280 }
271 - divItem=null;  
272 - if(hostList){  
273 - for (let i=hostList.length-1;i>=0;i--){  
274 - divItem=hostList[i];  
275 - if(divItem&&divItem.children.length<2){ 281 + divItem = null;
  282 + if (hostList) {
  283 + for (let i = hostList.length - 1; i >= 0; i--) {
  284 + divItem = hostList[i];
  285 + if (divItem && divItem.children.length < 2) {
276 console.log("删除无效的老师视图"); 286 console.log("删除无效的老师视图");
277 divItem.remove(); 287 divItem.remove();
278 } 288 }
279 } 289 }
280 } 290 }
281 - divItem=null;  
282 - if(localList){  
283 - for (let i=localList.length-1;i>=0;i--){  
284 - divItem=localList[i];  
285 - if(divItem&&divItem.children.length<2){ 291 + divItem = null;
  292 + if (localList) {
  293 + for (let i = localList.length - 1; i >= 0; i--) {
  294 + divItem = localList[i];
  295 + if (divItem && divItem.children.length < 2) {
286 console.log("删除无效的本地视图"); 296 console.log("删除无效的本地视图");
287 divItem.remove(); 297 divItem.remove();
288 } 298 }
289 } 299 }
290 } 300 }
291 - divItem=null; 301 + divItem = null;
292 } 302 }
293 303
294 304
@@ -331,8 +341,8 @@ class WebRtcApe extends Emiter { @@ -331,8 +341,8 @@ class WebRtcApe extends Emiter {
331 //console.log("remoteView->", remoteView) 341 //console.log("remoteView->", remoteView)
332 if (remoteView) { 342 if (remoteView) {
333 let player = document.getElementById("player_" + nodeId); 343 let player = document.getElementById("player_" + nodeId);
334 - let len=$("#"+this.xdyRemote + nodeId+" #player_" + nodeId).length;  
335 - if (len>0) { 344 + let len = $("#" + this.xdyRemote + nodeId + " #player_" + nodeId).length;
  345 + if (len > 0) {
336 loger.log(nodeId + " 流已经添加显示,不需要再处理"); 346 loger.log(nodeId + " 流已经添加显示,不需要再处理");
337 return; 347 return;
338 } else { 348 } else {
@@ -358,29 +368,29 @@ class WebRtcApe extends Emiter { @@ -358,29 +368,29 @@ class WebRtcApe extends Emiter {
358 368
359 //记录加入频道成功之后是否立即推流,默认false 369 //记录加入频道成功之后是否立即推流,默认false
360 //一般只有在刷新重进频道的时候会用到 370 //一般只有在刷新重进频道的时候会用到
361 - this.immediatePublish=_params.immediatePublish||false; 371 + this.immediatePublish = _params.immediatePublish || false;
362 372
363 //根据不同身份设置不同的分辨率 373 //根据不同身份设置不同的分辨率
364 - if(GlobalConfig.isTeachOrAssistant){  
365 - if(GlobalConfig.maxMediaChannels==1){ 374 + if (GlobalConfig.isTeachOrAssistant) {
  375 + if (GlobalConfig.maxMediaChannels == 1) {
366 //直播时使用标清最高档 376 //直播时使用标清最高档
367 - this.videoResolution="360P_8";  
368 - }else {  
369 - this.videoResolution="240P"; 377 + this.videoResolution = "360P_8";
  378 + } else {
  379 + this.videoResolution = "240P";
370 } 380 }
371 - }else if(GlobalConfig.isInvisible){  
372 - this.videoResolution="120P";  
373 - }else { 381 + } else if (GlobalConfig.isInvisible) {
  382 + this.videoResolution = "120P";
  383 + } else {
374 //学生在两路视频的时候使用240P 其他多人课堂的时候使用低清的 384 //学生在两路视频的时候使用240P 其他多人课堂的时候使用低清的
375 - if(GlobalConfig.maxMediaChannels==2||GlobalConfig.maxMediaChannels>3){  
376 - this.videoResolution="240P"  
377 - }else { 385 + if (GlobalConfig.maxMediaChannels == 2 || GlobalConfig.maxMediaChannels > 3) {
  386 + this.videoResolution = "240P"
  387 + } else {
378 //180P_4 13 240x180 15 120 388 //180P_4 13 240x180 15 120
379 - this.videoResolution="180P_4" 389 + this.videoResolution = "180P_4"
380 } 390 }
381 } 391 }
382 392
383 - loger.log("开始加入视频通话频道->channelId:" + this.channelId, "uid:" + this.uid,"videoResolution:"+this.videoResolution); 393 + loger.log("开始加入视频通话频道->channelId:" + this.channelId, "uid:" + this.uid, "videoResolution:" + this.videoResolution);
384 this.client.join(this.channelKey, "" + this.channelId, this.uid, (uid)=> { 394 this.client.join(this.channelKey, "" + this.channelId, this.uid, (uid)=> {
385 this.uid = uid; 395 this.uid = uid;
386 loger.log("加入视频通话频道->成功->channelId:" + this.channelId, "uid:" + this.uid); 396 loger.log("加入视频通话频道->成功->channelId:" + this.channelId, "uid:" + this.uid);
@@ -388,12 +398,12 @@ class WebRtcApe extends Emiter { @@ -388,12 +398,12 @@ class WebRtcApe extends Emiter {
388 this.openLoaclStream(); 398 this.openLoaclStream();
389 399
390 //加入频道成功之后需要判断是否立即开启推流 400 //加入频道成功之后需要判断是否立即开启推流
391 - if(this.immediatePublish==true){  
392 - loger.log("加入音视频频道成功->立刻开始推流->"+this.immediatePublish); 401 + if (this.immediatePublish == true) {
  402 + loger.log("加入音视频频道成功->立刻开始推流->" + this.immediatePublish);
393 clearTimeout(this.rePublishDelay); 403 clearTimeout(this.rePublishDelay);
394 - this.rePublishDelay=setTimeout(()=>{ 404 + this.rePublishDelay = setTimeout(()=> {
395 this.publish(); 405 this.publish();
396 - },200); 406 + }, 200);
397 } 407 }
398 }, (err)=> { 408 }, (err)=> {
399 loger.error("加入视频通话频道->失败->", err); 409 loger.error("加入视频通话频道->失败->", err);
@@ -439,11 +449,11 @@ class WebRtcApe extends Emiter { @@ -439,11 +449,11 @@ class WebRtcApe extends Emiter {
439 } 449 }
440 450
441 leaveChannel() { 451 leaveChannel() {
442 - loger.log("调用离开视频通话频道->isPublish"+this.isPublish); 452 + loger.log("调用离开视频通话频道->isPublish" + this.isPublish);
443 if (!this.client) { 453 if (!this.client) {
444 return; 454 return;
445 } 455 }
446 - this.firstPublishSuccess=false; 456 + this.firstPublishSuccess = false;
447 this.unpublish(); 457 this.unpublish();
448 this.client.leave(() => { 458 this.client.leave(() => {
449 loger.log("离开视频通话频道->成功"); 459 loger.log("离开视频通话频道->成功");
@@ -469,31 +479,39 @@ class WebRtcApe extends Emiter { @@ -469,31 +479,39 @@ class WebRtcApe extends Emiter {
469 /* 479 /*
470 * 设置旁录地址 480 * 设置旁录地址
471 * */ 481 * */
472 - setConfigPublisherUrl(_publishUrl){  
473 - this.firstPublishSuccess=false;  
474 - this.setConfigTimestamp=new Date().getTime()/1000;  
475 - this.configPublisherUrl=_publishUrl;  
476 - if(this.client&& this.configPublisherUrl){  
477 - let configObj={width: parseInt(this.pWidth), height: parseInt(this.pHeight), framerate: parseInt(this.pFrameRate), bitrate: parseInt(this.pBitrate), publishUrl:""+this.configPublisherUrl}; 482 + setConfigPublisherUrl(_publishUrl) {
  483 + this.firstPublishSuccess = false;
  484 + this.setConfigTimestamp = new Date().getTime() / 1000;
  485 + this.configPublisherUrl = _publishUrl;
  486 + if (this.client && this.configPublisherUrl) {
  487 + let configObj = {
  488 + width: parseInt(this.pWidth),
  489 + height: parseInt(this.pHeight),
  490 + framerate: parseInt(this.pFrameRate),
  491 + bitrate: parseInt(this.pBitrate),
  492 + publishUrl: "" + this.configPublisherUrl
  493 + };
478 //let configObj={width: 480, height:360, framerate:30, bitrate:500, publishUrl:_publishUrl}; 494 //let configObj={width: 480, height:360, framerate:30, bitrate:500, publishUrl:_publishUrl};
479 //let configObj={width: 480, height:360, framerate:30, bitrate:500, publishUrl:'rtmp://txlivepush.xuedianyun.com/live/markettest_395312484_T8440_983041_1507888360?bizid=11220&txSecret=15cc50d93f86f9e1a2a76a10db2b09a8&txTime=59e135a8&record=hls|flv&record_interval=5400'}; 495 //let configObj={width: 480, height:360, framerate:30, bitrate:500, publishUrl:'rtmp://txlivepush.xuedianyun.com/live/markettest_395312484_T8440_983041_1507888360?bizid=11220&txSecret=15cc50d93f86f9e1a2a76a10db2b09a8&txTime=59e135a8&record=hls|flv&record_interval=5400'};
480 - loger.warn("设置旁路地址->",configObj); 496 + loger.warn("设置旁路地址->", configObj);
481 this.client.configPublisher(configObj); 497 this.client.configPublisher(configObj);
482 - }else {  
483 - loger.warn("设置旁路地址->失败->为初始化或旁路地址无效",_publishUrl); 498 + } else {
  499 + loger.warn("设置旁路地址->失败->为初始化或旁路地址无效", _publishUrl);
484 } 500 }
485 } 501 }
  502 +
486 /* 503 /*
487 * 设置旁录拉流地址 504 * 设置旁录拉流地址
488 * */ 505 * */
489 - setRtmpM3u8Path(_param){ 506 + setRtmpM3u8Path(_param) {
490 //_webRtc.setRtmpM3u8Path({m3u8Url:m3u8Stream,rtmpUrl:rtmpStream}); 507 //_webRtc.setRtmpM3u8Path({m3u8Url:m3u8Stream,rtmpUrl:rtmpStream});
491 - loger.log("设置旁录拉流地址",_param);  
492 - if(_param){  
493 - this.m3u8Url=_param.m3u8Url||"";  
494 - this.rtmpUrl=_param.rtmpUrl||""; 508 + loger.log("设置旁录拉流地址", _param);
  509 + if (_param) {
  510 + this.m3u8Url = _param.m3u8Url || "";
  511 + this.rtmpUrl = _param.rtmpUrl || "";
495 } 512 }
496 } 513 }
  514 +
497 publish(_params) { 515 publish(_params) {
498 if (!this.client || !this.localStream) { 516 if (!this.client || !this.localStream) {
499 loger.warn("推流失败->未加入频道!"); 517 loger.warn("推流失败->未加入频道!");
@@ -504,13 +522,13 @@ class WebRtcApe extends Emiter { @@ -504,13 +522,13 @@ class WebRtcApe extends Emiter {
504 return; 522 return;
505 } 523 }
506 //老师-助教-主讲人-->设置旁路大于30秒没有推流,推流服务会停止,需要重设旁录和重加频道; 524 //老师-助教-主讲人-->设置旁路大于30秒没有推流,推流服务会停止,需要重设旁录和重加频道;
507 - if(this.setConfigTimestamp>0&&GlobalConfig.isTeachOrAssistant){ 525 + if (this.setConfigTimestamp > 0 && GlobalConfig.isTeachOrAssistant) {
508 //如果间隔大于28秒并且没有推过流需要重新加入频道,推成功一次之后就不需要 526 //如果间隔大于28秒并且没有推过流需要重新加入频道,推成功一次之后就不需要
509 - let interval=parseInt(new Date().getTime()/1000-this.setConfigTimestamp);  
510 - loger.log("设置旁路的时间和推流时间的间隔->"+interval+" firstPublishSuccess:"+ this.firstPublishSuccess);  
511 - if(interval>=28&&!this.firstPublishSuccess){ 527 + let interval = parseInt(new Date().getTime() / 1000 - this.setConfigTimestamp);
  528 + loger.log("设置旁路的时间和推流时间的间隔->" + interval + " firstPublishSuccess:" + this.firstPublishSuccess);
  529 + if (interval >= 28 && !this.firstPublishSuccess) {
512 loger.warn("设置旁路大于30秒没有推流,推流服务会停止,需要重设旁录和重加频道"); 530 loger.warn("设置旁路大于30秒没有推流,推流服务会停止,需要重设旁录和重加频道");
513 - this._emit(WebRtcApe.RE_JOIN_CHANNEL,{publish:true}); 531 + this._emit(WebRtcApe.RE_JOIN_CHANNEL, {publish: true});
514 return; 532 return;
515 } 533 }
516 } 534 }
@@ -520,9 +538,9 @@ class WebRtcApe extends Emiter { @@ -520,9 +538,9 @@ class WebRtcApe extends Emiter {
520 let viewName = 'localVideoBox_' + this.uid; 538 let viewName = 'localVideoBox_' + this.uid;
521 let videoBox = document.createElement("div"); 539 let videoBox = document.createElement("div");
522 videoBox.id = viewName; 540 videoBox.id = viewName;
523 - videoBox.className=this.localWebRtcVideoClass;  
524 - videoBox.style.width = (this.localVideoWidth*this.videoScale) + 'px';  
525 - videoBox.style.height = (this.localVideoHeight*this.videoScale) + 'px'; 541 + videoBox.className = this.localWebRtcVideoClass;
  542 + videoBox.style.width = (this.localVideoWidth * this.videoScale) + 'px';
  543 + videoBox.style.height = (this.localVideoHeight * this.videoScale) + 'px';
526 videoBox.style.float = 'left'; 544 videoBox.style.float = 'left';
527 videoBox.style.marginRight = "1px"; 545 videoBox.style.marginRight = "1px";
528 videoBox.style.pointerEvents = 'none'; 546 videoBox.style.pointerEvents = 'none';
@@ -536,8 +554,14 @@ class WebRtcApe extends Emiter { @@ -536,8 +554,14 @@ class WebRtcApe extends Emiter {
536 if (user) { 554 if (user) {
537 userName = user.name || ""; 555 userName = user.name || "";
538 } 556 }
539 - let nameDiv = `<div id="${"videoOwnerName_" + this.uid}" class="localVideoOwnerName" style="width:${this.localVideoWidth}px;height:20px; position: absolute;bottom: 0; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; color: #cccccc;display:${this.nameDisplay}">${userName}</div>`; 557 + let audioMutedDiv = "";
  558 + if (GlobalConfig.isTeachOrAssistant) {
  559 + audioMutedDiv = `<div class="audioMuted audioOpen" id=${"audioMuted_"+this.uid}></div>`;
  560 + }
  561 + let nameDiv = `<div id="${"videoOwnerName_" + this.uid}" class="localVideoOwnerName" style="width:${this.localVideoWidth}px;height:22px; position: absolute;bottom: 2px; z-index: 1;overflow:hidden;font-size: 14px;text-align: right; vertical-align: middle;background-color: #2926251a;color: #e7e7e7;display:${this.nameDisplay}">${userName + audioMutedDiv}</div>`;
540 $(this.localViewId).prepend(nameDiv); 562 $(this.localViewId).prepend(nameDiv);
  563 + $(".audioMuted").off("click", this._clickAudioMuted.bind(this));
  564 + $(".audioMuted").on("click", this._clickAudioMuted.bind(this));
541 565
542 loger.log("webRtc->推流->", viewName, new Date().getTime()); 566 loger.log("webRtc->推流->", viewName, new Date().getTime());
543 this.localStream.play(viewName); 567 this.localStream.play(viewName);
@@ -553,31 +577,31 @@ class WebRtcApe extends Emiter { @@ -553,31 +577,31 @@ class WebRtcApe extends Emiter {
553 this.isPublish = false; 577 this.isPublish = false;
554 this.clearLocalView(); 578 this.clearLocalView();
555 this._emit(MessageTypes.WEB_RTC_PUBLISH_FAILED, err); 579 this._emit(MessageTypes.WEB_RTC_PUBLISH_FAILED, err);
556 - if(err) { 580 + if (err) {
557 switch (err.msg) { 581 switch (err.msg) {
558 case "DEVICES_NOT_FOUND": 582 case "DEVICES_NOT_FOUND":
559 - this.curCameraId="";  
560 - this.curMicrophoneId=""; 583 + this.curCameraId = "";
  584 + this.curMicrophoneId = "";
561 this.unpublish(); 585 this.unpublish();
562 break; 586 break;
563 case "NOT_SUPPORTED": 587 case "NOT_SUPPORTED":
564 - this.curCameraId="";  
565 - this.curMicrophoneId=""; 588 + this.curCameraId = "";
  589 + this.curMicrophoneId = "";
566 this.unpublish(); 590 this.unpublish();
567 break; 591 break;
568 case "PERMISSION_DENIED": 592 case "PERMISSION_DENIED":
569 - this.curCameraId="";  
570 - this.curMicrophoneId=""; 593 + this.curCameraId = "";
  594 + this.curMicrophoneId = "";
571 this.unpublish(); 595 this.unpublish();
572 break; 596 break;
573 case "CONSTRAINT_NOT_SATISFIED": 597 case "CONSTRAINT_NOT_SATISFIED":
574 - this.curCameraId="";  
575 - this.curMicrophoneId=""; 598 + this.curCameraId = "";
  599 + this.curMicrophoneId = "";
576 this.unpublish(); 600 this.unpublish();
577 break; 601 break;
578 case "STREAM_ALREADY_INITIALIZED": 602 case "STREAM_ALREADY_INITIALIZED":
579 - this.curCameraId="";  
580 - this.curMicrophoneId=""; 603 + this.curCameraId = "";
  604 + this.curMicrophoneId = "";
581 this.unpublish(); 605 this.unpublish();
582 break; 606 break;
583 default: 607 default:
@@ -617,38 +641,38 @@ class WebRtcApe extends Emiter { @@ -617,38 +641,38 @@ class WebRtcApe extends Emiter {
617 $('#localVideoBox_' + this.uid).remove(); 641 $('#localVideoBox_' + this.uid).remove();
618 $("#videoOwnerName_" + this.uid).remove(); 642 $("#videoOwnerName_" + this.uid).remove();
619 $(".localVideoOwnerName").remove(); 643 $(".localVideoOwnerName").remove();
620 - $("."+this.localWebRtcVideoClass).remove(); 644 + $("." + this.localWebRtcVideoClass).remove();
621 } 645 }
622 646
623 /* 647 /*
624 * 更新所有视频的尺寸大小 648 * 更新所有视频的尺寸大小
625 * */ 649 * */
626 - updateAllVideoSize(){  
627 - $("."+this.localWebRtcVideoClass).css("width",this.localVideoWidth*this.videoScale);  
628 - $("."+this.localWebRtcVideoClass).css("height",this.localVideoHeight*this.videoScale); 650 + updateAllVideoSize() {
  651 + $("." + this.localWebRtcVideoClass).css("width", this.localVideoWidth * this.videoScale);
  652 + $("." + this.localWebRtcVideoClass).css("height", this.localVideoHeight * this.videoScale);
629 653
630 - $("."+this.hostWebRtcVideoClass).css("width",this.hostRemoteVideoWidth*this.videoScale);  
631 - $("."+this.hostWebRtcVideoClass).css("height",this.hostRemoteVideoHeight*this.videoScale); 654 + $("." + this.hostWebRtcVideoClass).css("width", this.hostRemoteVideoWidth * this.videoScale);
  655 + $("." + this.hostWebRtcVideoClass).css("height", this.hostRemoteVideoHeight * this.videoScale);
632 656
633 - $("."+this.normalWebRtcVideoClass).css("width",this.normalRemoteVideoWidth*this.videoScale);  
634 - $("."+this.normalWebRtcVideoClass).css("height",this.normalRemoteVideoHeight*this.videoScale); 657 + $("." + this.normalWebRtcVideoClass).css("width", this.normalRemoteVideoWidth * this.videoScale);
  658 + $("." + this.normalWebRtcVideoClass).css("height", this.normalRemoteVideoHeight * this.videoScale);
635 659
636 } 660 }
637 661
638 /* 662 /*
639 * 设置rtc视频的属性 663 * 设置rtc视频的属性
640 * */ 664 * */
641 - changeRtcVideoConfig(_params){ 665 + changeRtcVideoConfig(_params) {
642 //{videoScale:1} 666 //{videoScale:1}
643 - if(!_params){ 667 + if (!_params) {
644 return; 668 return;
645 } 669 }
646 - let scale=parseInt(_params.videoScale)||1;//最小值只能为1,这个是按倍数缩放视频  
647 - if(this.videoScale==scale){ 670 + let scale = parseInt(_params.videoScale) || 1;//最小值只能为1,这个是按倍数缩放视频
  671 + if (this.videoScale == scale) {
648 return; 672 return;
649 } 673 }
650 - this.videoScale=scale;  
651 - loger.log("更新视频视图大小->videoScale:"+this.videoScale); 674 + this.videoScale = scale;
  675 + loger.log("更新视频视图大小->videoScale:" + this.videoScale);
652 this.updateAllVideoSize(); 676 this.updateAllVideoSize();
653 } 677 }
654 678
@@ -663,8 +687,8 @@ class WebRtcApe extends Emiter { @@ -663,8 +687,8 @@ class WebRtcApe extends Emiter {
663 this.localVideoHeight = parseInt(_params.height) || SIZE_360; 687 this.localVideoHeight = parseInt(_params.height) || SIZE_360;
664 this.nameDisplay = _params.nameDisplay || "block"; 688 this.nameDisplay = _params.nameDisplay || "block";
665 689
666 - this.localVideoWidth=this.localVideoWidth;  
667 - this.localVideoHeight=this.localVideoHeight; 690 + this.localVideoWidth = this.localVideoWidth;
  691 + this.localVideoHeight = this.localVideoHeight;
668 } 692 }
669 693
670 /* 694 /*
@@ -676,8 +700,8 @@ class WebRtcApe extends Emiter { @@ -676,8 +700,8 @@ class WebRtcApe extends Emiter {
676 this.hostRemoteStyle = _params.styleStr || ""; 700 this.hostRemoteStyle = _params.styleStr || "";
677 this.hostRemoteVideoWidth = parseInt(_params.width) || SIZE_480; 701 this.hostRemoteVideoWidth = parseInt(_params.width) || SIZE_480;
678 this.hostRemoteVideoHeight = parseInt(_params.height) || SIZE_360; 702 this.hostRemoteVideoHeight = parseInt(_params.height) || SIZE_360;
679 - this.hostRemoteVideoWidth=this.hostRemoteVideoWidth;  
680 - this.hostRemoteVideoHeight=this.hostRemoteVideoHeight; 703 + this.hostRemoteVideoWidth = this.hostRemoteVideoWidth;
  704 + this.hostRemoteVideoHeight = this.hostRemoteVideoHeight;
681 } 705 }
682 706
683 /* 707 /*
@@ -690,8 +714,8 @@ class WebRtcApe extends Emiter { @@ -690,8 +714,8 @@ class WebRtcApe extends Emiter {
690 this.normalRemoteVideoWidth = parseInt(_params.width) || SIZE_480; 714 this.normalRemoteVideoWidth = parseInt(_params.width) || SIZE_480;
691 this.normalRemoteVideoHeight = parseInt(_params.height) || SIZE_360; 715 this.normalRemoteVideoHeight = parseInt(_params.height) || SIZE_360;
692 716
693 - this.normalRemoteVideoWidth=this.normalRemoteVideoWidth;  
694 - this.normalRemoteVideoHeight=this.normalRemoteVideoHeight; 717 + this.normalRemoteVideoWidth = this.normalRemoteVideoWidth;
  718 + this.normalRemoteVideoHeight = this.normalRemoteVideoHeight;
695 } 719 }
696 720
697 /* 721 /*
@@ -708,12 +732,12 @@ class WebRtcApe extends Emiter { @@ -708,12 +732,12 @@ class WebRtcApe extends Emiter {
708 /* 732 /*
709 * 设置旁录推流的参数 733 * 设置旁录推流的参数
710 * */ 734 * */
711 - setConfigPublisher(_params){  
712 - loger.log("设置旁录推流的参数",_params);  
713 - this.pWidth=_params.width||SIZE_480;  
714 - this.pHeight=_params.height||SIZE_360;  
715 - this.pFrameRate=_params.frameRate||30;  
716 - this.pBitrate=_params.bitrate||500; 735 + setConfigPublisher(_params) {
  736 + loger.log("设置旁录推流的参数", _params);
  737 + this.pWidth = _params.width || SIZE_480;
  738 + this.pHeight = _params.height || SIZE_360;
  739 + this.pFrameRate = _params.frameRate || 30;
  740 + this.pBitrate = _params.bitrate || 500;
717 } 741 }
718 742
719 /* 743 /*
@@ -776,7 +800,7 @@ class WebRtcApe extends Emiter { @@ -776,7 +800,7 @@ class WebRtcApe extends Emiter {
776 for (let i = 0; i < devices.length; i++) { 800 for (let i = 0; i < devices.length; i++) {
777 let device = devices[i]; 801 let device = devices[i];
778 //{"deviceId":"default","kind":"audiooutput","label":"默认","groupId":"cf49a03ca26700235629fc13d3e6630bd34407c66438d157056a34dd3ae03ef5"} 802 //{"deviceId":"default","kind":"audiooutput","label":"默认","groupId":"cf49a03ca26700235629fc13d3e6630bd34407c66438d157056a34dd3ae03ef5"}
779 - if(device){ 803 + if (device) {
780 if (device.kind == 'audioinput') { 804 if (device.kind == 'audioinput') {
781 this.microphones.push(device); 805 this.microphones.push(device);
782 GlobalConfig.microphones.push(device.label); 806 GlobalConfig.microphones.push(device.label);
@@ -796,13 +820,107 @@ class WebRtcApe extends Emiter { @@ -796,13 +820,107 @@ class WebRtcApe extends Emiter {
796 }); 820 });
797 } 821 }
798 822
  823 + _clickAudioMuted(evt) {
  824 + let className = evt.currentTarget.className;
  825 + console.log("点击禁音",evt.currentTarget.id);
  826 + let idArr = (evt.currentTarget.id).split("_");
  827 + let uid = 10000000;//默认设置一个不存在的uid
  828 + if (idArr && idArr.length > 1) {
  829 + uid = parseInt(idArr[1]);
  830 + }
  831 + if (className.indexOf("audioOpen") > 0) {
  832 + loger.log("点击禁音->"+uid);
  833 + // evt.currentTarget.className="audioMuted audioClose";
  834 + if (uid != GlobalConfig.nodeId) {
  835 + this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: false});
  836 + $("#audioMuted_" + uid).removeClass();
  837 + $("#audioMuted_" + uid).addClass("audioMuted audioClose");
  838 + } else {
  839 + this.disableAudio(uid);
  840 + }
  841 + } else {
  842 + loger.log("点击开启声音");
  843 + //evt.currentTarget.className="audioMuted audioOpen";
  844 + if (uid != GlobalConfig.nodeId) {
  845 + this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: true});
  846 + $("#audioMuted_" + uid).removeClass();
  847 + $("#audioMuted_" + uid).addClass("audioMuted audioOpen");
  848 + } else {
  849 + this.enableAudio(uid);
  850 + }
  851 + }
  852 + }
  853 +
  854 + /*
  855 + * 发送控制音视频禁用消息
  856 + * */
  857 + sendChangeUserMediaEnabled(_param) {
  858 + this._emit(MessageTypes.MEDIA_ENABLED_CHANGE, _param);
  859 + }
  860 +
  861 + /*
  862 + * 收到控制音视频禁用消息
  863 + * */
  864 + webRtcMeiaEnabledChange(_data) {
  865 + loger.log("收到控制音视频禁用消息",_data);
  866 + // {nodeId: uid, video: true, audio: false}
  867 + if(!_data){
  868 + return;
  869 + }
  870 + if(_data.nodeId!=GlobalConfig.nodeId){
  871 + if(_data.audio==false){
  872 + $("#audioMuted_" + _data.nodeId).removeClass();
  873 + $("#audioMuted_" + _data.nodeId).addClass("audioMuted audioClose");
  874 + }else {
  875 + $("#audioMuted_" + _data.nodeId).removeClass();
  876 + $("#audioMuted_" + _data.nodeId).addClass("audioMuted audioOpen");
  877 + }
  878 +
  879 + }else{
  880 + if(_data.audio==false){
  881 + this.disableAudio(_data.nodeId);
  882 + }else {
  883 + this.enableAudio(_data.nodeId);
  884 + }
  885 + }
  886 +
  887 + }
  888 +
  889 + /*
  890 + * 开启禁音
  891 + * */
  892 + disableAudio(uid) {
  893 + loger.log("开启禁音:" + uid);
  894 + if (parseInt(uid) == GlobalConfig.nodeId) {
  895 + if (this.localStream) {
  896 + $("#audioMuted_" + uid).removeClass();
  897 + $("#audioMuted_" + uid).addClass("audioMuted audioClose");
  898 + this.localStream.disableAudio();
  899 + }
  900 + }
  901 + }
  902 +
  903 + /*
  904 + * 开启音频
  905 + * */
  906 + enableAudio(_uid) {
  907 + loger.log("开启音频:" + _uid);
  908 + if (parseInt(_uid) == GlobalConfig.nodeId) {
  909 + if (this.localStream) {
  910 + this.localStream.enableAudio();
  911 + $("#audioMuted_" + _uid).removeClass();
  912 + $("#audioMuted_" + _uid).addClass("audioMuted audioOpen");
  913 + }
  914 + }
  915 + }
  916 +
799 //组织数据,发送给服务器,控制录制和开启录制-推流和停止推流 status:0 停止推流 1:开始推流(同时开启录制),2:停止录制(同时停止推流) 917 //组织数据,发送给服务器,控制录制和开启录制-推流和停止推流 status:0 停止推流 1:开始推流(同时开启录制),2:停止录制(同时停止推流)
800 packMediaInfoData(_status) { 918 packMediaInfoData(_status) {
801 let curTimestamp = new Date().getTime(); 919 let curTimestamp = new Date().getTime();
802 let data = `appId=${GlobalConfig.appId}&channel=${GlobalConfig.channelId}&channelKey=${GlobalConfig.appCertificate}&uid=${GlobalConfig.userUid}&status=${_status}&userId=${GlobalConfig.userId}&userName=${GlobalConfig.userName}&userRole=${GlobalConfig.userRole}&timestamp=${curTimestamp}&recordTimestamp=${GlobalConfig.recordTimestamp}`; 920 let data = `appId=${GlobalConfig.appId}&channel=${GlobalConfig.channelId}&channelKey=${GlobalConfig.appCertificate}&uid=${GlobalConfig.userUid}&status=${_status}&userId=${GlobalConfig.userId}&userName=${GlobalConfig.userName}&userRole=${GlobalConfig.userRole}&timestamp=${curTimestamp}&recordTimestamp=${GlobalConfig.recordTimestamp}`;
803 921
804 //markettest_623790840_T9540_1508207080 922 //markettest_623790840_T9540_1508207080
805 - let streamId=GlobalConfig.siteId+"_"+GlobalConfig.classId+"_"+GlobalConfig.userId+"_"+curTimestamp; 923 + let streamId = GlobalConfig.siteId + "_" + GlobalConfig.classId + "_" + GlobalConfig.userId + "_" + curTimestamp;
806 //mcu记录一份数据 924 //mcu记录一份数据
807 this._emit(MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE, { 925 this._emit(MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE, {
808 appId: GlobalConfig.appId, 926 appId: GlobalConfig.appId,
@@ -815,10 +933,10 @@ class WebRtcApe extends Emiter { @@ -815,10 +933,10 @@ class WebRtcApe extends Emiter {
815 userRole: GlobalConfig.userRole, 933 userRole: GlobalConfig.userRole,
816 timestamp: curTimestamp, 934 timestamp: curTimestamp,
817 recordTimestamp: GlobalConfig.recordTimestamp, 935 recordTimestamp: GlobalConfig.recordTimestamp,
818 - streamId:streamId,  
819 - publishUrl:this.configPublisherUrl,  
820 - m3u8Url:this.m3u8Url,  
821 - rtmpUrl:this.rtmpUrl 936 + streamId: streamId,
  937 + publishUrl: this.configPublisherUrl,
  938 + m3u8Url: this.m3u8Url,
  939 + rtmpUrl: this.rtmpUrl
822 }); 940 });
823 return data; 941 return data;
824 } 942 }
@@ -833,7 +951,7 @@ class WebRtcApe extends Emiter { @@ -833,7 +951,7 @@ class WebRtcApe extends Emiter {
833 } 951 }
834 let url = GlobalConfig.locationProtocol + GlobalConfig.recordInterfaces; 952 let url = GlobalConfig.locationProtocol + GlobalConfig.recordInterfaces;
835 let data = this.packMediaInfoData(_status); 953 let data = this.packMediaInfoData(_status);
836 - loger.log("调用服务器端更新视频录制状态->status",_status); 954 + loger.log("调用服务器端更新视频录制状态->status", _status);
837 fetch(encodeURI(url), { 955 fetch(encodeURI(url), {
838 method: 'POST', 956 method: 'POST',
839 headers: { 957 headers: {
@@ -866,11 +984,11 @@ class WebRtcApe extends Emiter { @@ -866,11 +984,11 @@ class WebRtcApe extends Emiter {
866 * 切换音视频的录制状态 984 * 切换音视频的录制状态
867 * */ 985 * */
868 changeMediaRecordStatus(_params) { 986 changeMediaRecordStatus(_params) {
869 - if (!GlobalConfig.recordInterfaces||!_params) {  
870 - loger.warn("切换音视频的录制状态->失败->接口地址无效",_params); 987 + if (!GlobalConfig.recordInterfaces || !_params) {
  988 + loger.warn("切换音视频的录制状态->失败->接口地址无效", _params);
871 return; 989 return;
872 } 990 }
873 - loger.warn("切换音视频的录制状态->"+_params); 991 + loger.warn("切换音视频的录制状态->" + _params);
874 let url = GlobalConfig.locationProtocol + GlobalConfig.recordInterfaces; 992 let url = GlobalConfig.locationProtocol + GlobalConfig.recordInterfaces;
875 let curTimestamp = new Date().getTime(); 993 let curTimestamp = new Date().getTime();
876 let data = `appId=${GlobalConfig.appId}&channel=${GlobalConfig.channelId}&channelKey=${GlobalConfig.appCertificate}&uid=${GlobalConfig.userUid}&status=${_params.status}&userId=${GlobalConfig.userId}&userName=${GlobalConfig.userName}&userRole=${GlobalConfig.userRole}&timestamp=${curTimestamp}&recordTimestamp=${GlobalConfig.recordTimestamp}`; 994 let data = `appId=${GlobalConfig.appId}&channel=${GlobalConfig.channelId}&channelKey=${GlobalConfig.appCertificate}&uid=${GlobalConfig.userUid}&status=${_params.status}&userId=${GlobalConfig.userId}&userName=${GlobalConfig.userName}&userRole=${GlobalConfig.userRole}&timestamp=${curTimestamp}&recordTimestamp=${GlobalConfig.recordTimestamp}`;
  1 +@charset "utf-8";
  2 +
  3 +/*禁音按钮*/
  4 +.audioMuted{
  5 + margin-left: 6px;
  6 + float: right;
  7 + width: 20px;
  8 + height: 20px;
  9 + cursor: pointer;
  10 + background-size: auto;
  11 + background-repeat: no-repeat;
  12 +}
  13 +.audioClose {
  14 + background-image: url(../../assets/img/audioClose.png);
  15 +}
  16 +.audioOpen {
  17 + background-image: url(../../assets/img/audioOpen.png);
  18 +}