李勇

新增音频禁用控制功能

... ... @@ -63,7 +63,7 @@ export default class MessageEntrance extends Emiter {
super();
this.lastClassActiveTime=0;//最后一次课堂激活的时间戳
//sdk 信息
GlobalConfig.sdkVersion = "v2.32.1.20171123";
GlobalConfig.sdkVersion = "v2.33.6.20171123";
loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
console.log("sdkVersion:" + GlobalConfig.sdkVersion);
//设置
... ... @@ -102,6 +102,7 @@ export default class MessageEntrance extends Emiter {
_webRtc.on(MessageTypes.USER_DEVICE_STATUS_CHAANGE, this.userDeviecStatusChange.bind(this)); //监听摄像头和麦克风的开启状态
_webRtc.on(MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE, this.mediaPublishStatusChange.bind(this)); //webRtc推流状态发生改变
_webRtc.on(WebRtcApe.RE_JOIN_CHANNEL, this._webRtcRejoinChannel.bind(this)); //重先加入音视频频道
_webRtc.on(MessageTypes.MEDIA_ENABLED_CHANGE, this._mediaEnabledChange.bind(this)); //音视频禁用状态改变
// Sass平台层
_sass = Sass;
... ... @@ -152,6 +153,7 @@ export default class MessageEntrance extends Emiter {
//_confer_ape.on(MessageTypes.SWITCH_HLS_IP, this._switchHlsIpHandler.bind(this)); //MS HLS动态选点
_confer_ape.on(MessageTypes.STOP_ALL_MEDIA_PUBLISH, this._stopAllMediaPublishHandler.bind(this)); //课堂状态发生改变,需要停止当前的所有推流
_confer_ape.on(MessageTypes.CLASS_UPDATE_ROSTER, this._onRosterUpdateHandler.bind(this));
_confer_ape.on(MessageTypes.RECEIVE_MEDIA_ENABLED_CHANGE, this._receiveMeiaEnabledChange.bind(this));
_chat_ape = new ChatApe();
_chat_ape.on('*', (type, data) => this._emit(type, data));
... ... @@ -651,6 +653,8 @@ export default class MessageEntrance extends Emiter {
randUserId = "A" + randUserId;
} else if (GlobalConfig.userRole == ApeConsts.presenter) {
randUserId = "P" + randUserId;
} else if (GlobalConfig.userRole == ApeConsts.invisible) {
randUserId = "I" + randUserId;
} else {
randUserId = "S" + randUserId;
}
... ... @@ -700,7 +704,8 @@ export default class MessageEntrance extends Emiter {
let autoLoginMd5 = MD5("" + GlobalConfig.classId + GlobalConfig.paramUserId + GlobalConfig.userRole);
//let autoLoginMd5 = MD5("" + GlobalConfig.classId + GlobalConfig.userId + GlobalConfig.userRole);
//loger.log("joinClass-GlobalConfig.autoLogin", GlobalConfig.autoLogin, "autoLoginMd5-", autoLoginMd5);
if (GlobalConfig.autoLogin && autoLoginMd5 == GlobalConfig.autoLogin || GlobalConfig.isInvisible) {
if ((GlobalConfig.autoLogin && autoLoginMd5 == GlobalConfig.autoLogin) ||
GlobalConfig.isInvisible||GlobalConfig.isAssistant||GlobalConfig.isPresenter) {
// MD5(classId+userId+userRole)==m
//自动登录,跳过验证流程
loger.log("自动登录->" + GlobalConfig.userRole);
... ... @@ -1404,7 +1409,17 @@ export default class MessageEntrance extends Emiter {
_webRtc.tryAddMobileStream(_data.nodeId);
}
}
/*
* 收到媒体禁用状态切换的消息
* */
_receiveMeiaEnabledChange(_data){
if(!_data||GlobalConfig.isRecordPlayBack||GlobalConfig.isH5){
return;
}
if(_webRtc){
_webRtc.webRtcMeiaEnabledChange(_data);
}
}
//手动切换MS -> {ip;"xxx.xx.xx","port":"xxxx"}
_switchMediaServer(_param) {
if (GlobalConfig.isRecordPlayBack) {
... ... @@ -2153,6 +2168,17 @@ export default class MessageEntrance extends Emiter {
_webRtcRejoinChannel(_data){
this._reJoinChannel(_data)
}
/*
* 监听webRtc
* */
_mediaEnabledChange(_data){
if (!_mcu.connected||GlobalConfig.isRecordPlayBack) {
return;
}
if(_confer_ape){
_confer_ape.sendMediaEnabledChange(_data);
}
}
//监听摄像头麦克风状态
userDeviecStatusChange(_data) {
... ...
... ... @@ -4,212 +4,222 @@
import Base64 from 'base64-js';
import UTF8 from 'utf-8';
class EngineUtils{
static isEmptyObject(O){
for (var x in O){
return false;
}
return true;
class EngineUtils {
static isEmptyObject(O) {
for (var x in O) {
return false;
}
static arrayToJsonString(_param){
try{
return JSON.stringify(_param);
}catch (err){
console.warn("数组转JSON失败->ERROR:"+err.message);
}
return "";
return true;
}
static arrayToJsonString(_param) {
try {
return JSON.stringify(_param);
} catch (err) {
console.warn("数组转JSON失败->ERROR:" + err.message);
}
static arrayFromJsonString(_param){
try{
return JSON.parse(_param);
}catch (err){
console.warn("JSON转数组失败->ERROR:"+err.message);
}
return [];
return "";
}
static arrayFromJsonString(_param) {
try {
return JSON.parse(_param);
} catch (err) {
console.warn("JSON转数组失败->ERROR:" + err.message);
}
return [];
}
/*
* 生成随机数 _part 段数 默认3段; splitStr分隔符
* */
static creatRandomNum(_part=3,splitStr=""){
let randNumStr="";
for(let i=0;i<_part;i++){
randNumStr+=splitStr+parseInt(Math.random()*1000);
}
return randNumStr;
}
//生成时间戳后9位 保证唯一
static creatSoleNumberFromTimestamp(){
let time = new Date().getTime();
let timestamp= time % 1000000000;//time后9位
return timestamp;
}
//生成时间戳毫秒
static creatTimestamp(){
let time = parseInt(new Date().getTime()/1000);//精确到秒
return time;
}
//生成时间戳 string
static creatTimestampStr(){
let curTime = new Date();
let timeStr = "" + curTime.getFullYear() + "-";
timeStr += (curTime.getMonth()+1) + "-";
timeStr += curTime.getDate() + "-";
timeStr+=curTime.getHours() + "-";
timeStr+=curTime.getMinutes() + "-";
timeStr+=curTime.getSeconds();
return timeStr;
}
//根据时间戳字符串转换为时间戳 2017-10-27-15-38-15
static getTimestampFromStr(_timeStr){
if(!_timeStr) return this.creatTimestamp();
let timeArr=_timeStr.split("_");
if(timeArr&&timeArr.length==6){
return parseInt( new Date(timeArr[0],parseInt(timeArr[1])-1,timeArr[2],timeArr[3],timeArr[4],timeArr[5]).getTime()/1000);
}
return this.creatTimestamp();
/*
* 生成随机数 _part 段数 默认3段; splitStr分隔符
* */
static creatRandomNum(_part = 3, splitStr = "") {
let randNumStr = "";
for (let i = 0; i < _part; i++) {
randNumStr += splitStr + parseInt(Math.random() * 1000);
}
//生成时间戳 格式:"20170209"
static creatTimestampYMD(){
let curTime = new Date();
let year = "" + curTime.getFullYear();
let month = "" +(curTime.getMonth()+1);
let day = "" + curTime.getDate();
return randNumStr;
}
if(month.length<2){
month="0"+month;
}
if(day.length<2){
day="0"+day;
}
return year+month+day;
}
static objectToBase64(_object){
try{
let _objectStr=JSON.stringify(_object);
//console.log("objectToBase64------1----------")
let byte=UTF8.setBytesFromString(_objectStr);
//console.log("objectToBase64------2----------")
let _objectBase64=Base64.fromByteArray(byte);
return _objectBase64
}catch (err){
console.log("objectToBase64 err:"+err.message);
return "";
}
return ""
}
static objectFromBase64(_objectBase64){
try{
let byte=Base64.toByteArray(_objectBase64);
let _objectStr=UTF8.getStringFromBytes(byte);
let _object=JSON.parse(_objectStr);
return _object
}catch (err){
console.log("objectFromBase64 err:"+err.message);
return null;
}
return null;
//生成时间戳后9位 保证唯一
static creatSoleNumberFromTimestamp() {
let time = new Date().getTime();
let timestamp = time % 1000000000;//time后9位
return timestamp;
}
//生成时间戳毫秒
static creatTimestamp() {
let time = parseInt(new Date().getTime() / 1000);//精确到秒
return time;
}
//生成时间戳 string
static creatTimestampStr() {
let curTime = new Date();
let timeStr = "" + curTime.getFullYear() + "-";
timeStr += (curTime.getMonth() + 1) + "-";
timeStr += curTime.getDate() + "-";
timeStr += curTime.getHours() + "-";
timeStr += curTime.getMinutes() + "-";
timeStr += curTime.getSeconds();
return timeStr;
}
//根据时间戳字符串转换为时间戳 2017-10-27-15-38-15
static getTimestampFromStr(_timeStr) {
if (!_timeStr) return this.creatTimestamp();
let timeArr = _timeStr.split("_");
if (timeArr && timeArr.length == 6) {
return parseInt(new Date(timeArr[0], parseInt(timeArr[1]) - 1, timeArr[2], timeArr[3], timeArr[4], timeArr[5]).getTime() / 1000);
}
//优化压缩坐标点数组,去除一些连续重复坐标的点,返回一个数组
static compressPoint(_arr){
if(!_arr){
return [];
}
if(_arr.length<5){
//点,直线,矩形 坐标点小于5不需要处理
return _arr;
}
let tempPointArr=_arr;
let newPointArr=[];
newPointArr.push(tempPointArr[0]);
let lastW=tempPointArr[0].w;
let continueNum=0;//坐标相同的连续次数
//先筛除水平方向的连续重复坐标点
let len=tempPointArr.length-1;
for(let i=1;i<len;i++){
let item=tempPointArr[i];
if(item&&item.w!=lastW){
lastW=item.w;
if(continueNum>0){
newPointArr.push(tempPointArr[i-1]);
}
newPointArr.push(item);
continueNum=0;
}else {
continueNum++;
}
}
//如果最终的坐标点数量小于2,需要把最后一个坐标点添加
if(tempPointArr[len]){
newPointArr.push(tempPointArr[len]);
}
//如果坐标点已经小于等于2不需要继续检测
if(newPointArr.length<=2){
return newPointArr;
}
return this.creatTimestamp();
}
//筛除水垂直向的连续重复坐标点
let finalPointArr=[];
finalPointArr.push(newPointArr[0]);
let lastH=newPointArr[0].h;
continueNum=0;
len=newPointArr.length-1;
for(let k=1;k<len;k++){
let item=newPointArr[k];
if(item&&item.h!=lastH){
lastH=item.h;
if(continueNum>0){
finalPointArr.push(newPointArr[k-1]);
}
finalPointArr.push(item);
continueNum=0;
}else {
continueNum++;
}
}
if(newPointArr[len]){
finalPointArr.push(newPointArr[len]);
}
return finalPointArr;
//生成时间戳 格式:"20170209"
static creatTimestampYMD() {
let curTime = new Date();
let year = "" + curTime.getFullYear();
let month = "" + (curTime.getMonth() + 1);
let day = "" + curTime.getDate();
if (month.length < 2) {
month = "0" + month;
}
//压缩数据,把坐标点数组转换为字符串,返回字符串
static optimizePoint(_pointGroup){
if(!_pointGroup){
return "";
}
let tempStr="";
try {
tempStr=JSON.stringify(_pointGroup);
}catch (err){
return "";
}
let regexp1=/},{"w":/g;
let regexp2=/,"h":/g;
tempStr=tempStr.replace(regexp1,"#");
tempStr=tempStr.replace(regexp2,"&");
//console.log("标注压缩后的字符长度->",tempStr.length);
return tempStr;
}
//把字符串坐标点集合转换为数组,返回数组的JSON
static unPackOptimizePoint(_str){
if(!_str){
return "";
}
let tempStr=_str;
let regexp1=/#/g;
let regexp2=/&/g;
tempStr=tempStr.replace(regexp1,'},{"w":');
tempStr=tempStr.replace(regexp2,',"h":');
if (day.length < 2) {
day = "0" + day;
}
return year + month + day;
}
let dataArr=[];
try {
dataArr=JSON.parse(tempStr);
}catch (err){
static objectToBase64(_object) {
try {
let _objectStr = JSON.stringify(_object);
//console.log("objectToBase64------1----------")
let byte = UTF8.setBytesFromString(_objectStr);
//console.log("objectToBase64------2----------")
let _objectBase64 = Base64.fromByteArray(byte);
return _objectBase64
} catch (err) {
console.log("objectToBase64 err:" + err.message);
return "";
}
return ""
}
static objectFromBase64(_objectBase64) {
try {
let byte = Base64.toByteArray(_objectBase64);
let _objectStr = UTF8.getStringFromBytes(byte);
let _object = JSON.parse(_objectStr);
return _object
} catch (err) {
console.log("objectFromBase64 err:" + err.message);
return null;
}
return null;
}
//优化压缩坐标点数组,去除一些连续重复坐标的点,返回一个数组
static compressPoint(_arr) {
if (!_arr) {
return [];
}
if (_arr.length < 5) {
//点,直线,矩形 坐标点小于5不需要处理
return _arr;
}
let tempPointArr = _arr;
let newPointArr = [];
newPointArr.push(tempPointArr[0]);
let lastW = tempPointArr[0].w;
let continueNum = 0;//坐标相同的连续次数
//先筛除水平方向的连续重复坐标点
let len = tempPointArr.length - 1;
for (let i = 1; i < len; i++) {
let item = tempPointArr[i];
if (item && item.w != lastW) {
lastW = item.w;
if (continueNum > 0) {
newPointArr.push(tempPointArr[i - 1]);
}
newPointArr.push(item);
continueNum = 0;
} else {
continueNum++;
}
}
//如果最终的坐标点数量小于2,需要把最后一个坐标点添加
if (tempPointArr[len]) {
newPointArr.push(tempPointArr[len]);
}
//如果坐标点已经小于等于2不需要继续检测
if (newPointArr.length <= 2) {
return newPointArr;
}
//筛除水垂直向的连续重复坐标点
let finalPointArr = [];
finalPointArr.push(newPointArr[0]);
let lastH = newPointArr[0].h;
continueNum = 0;
len = newPointArr.length - 1;
for (let k = 1; k < len; k++) {
let item = newPointArr[k];
if (item && item.h != lastH) {
lastH = item.h;
if (continueNum > 0) {
finalPointArr.push(newPointArr[k - 1]);
}
finalPointArr.push(item);
continueNum = 0;
} else {
continueNum++;
}
}
if (newPointArr[len]) {
finalPointArr.push(newPointArr[len]);
}
return finalPointArr;
}
//压缩数据,把坐标点数组转换为字符串,返回字符串
static optimizePoint(_pointGroup) {
if (!_pointGroup) {
return "";
}
let tempStr = "";
try {
tempStr = JSON.stringify(_pointGroup);
} catch (err) {
return "";
}
let regexp1 = /},{"w":/g;
let regexp2 = /,"h":/g;
tempStr = tempStr.replace(regexp1, "#");
tempStr = tempStr.replace(regexp2, "&");
//console.log("标注压缩后的字符长度->",tempStr.length);
return tempStr;
}
//把字符串坐标点集合转换为数组,返回数组的JSON
static unPackOptimizePoint(_str) {
if (!_str) {
return "";
}
let tempStr = _str;
let regexp1 = /#/g;
let regexp2 = /&/g;
tempStr = tempStr.replace(regexp1, '},{"w":');
tempStr = tempStr.replace(regexp2, ',"h":');
let dataArr = [];
try {
dataArr = JSON.parse(tempStr);
} catch (err) {
}
return dataArr;
}
return dataArr;
}
}
export default EngineUtils;
\ No newline at end of file
... ...
... ... @@ -111,6 +111,8 @@ MessageTypes.WEB_RTC_JOIN_FAILED = "web_rtc_join_failed";
MessageTypes.WEB_RTC_PUBLISH_FAILED = "web_rtc_publish_failed";
MessageTypes.GET_DEVICES_SUCCESS = "get_devices_success";
MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE = "media_publish_status_change";//音视频推流的状态发生改变
MessageTypes.MEDIA_ENABLED_CHANGE = "media_enabled_change";//媒体禁用或开启状态改变
MessageTypes.RECEIVE_MEDIA_ENABLED_CHANGE = "receive_media_enabled_change";//收到媒体禁用状态控制的消息
//MCU MS
MessageTypes.SWITCH_MCU_IP = "switch_mcu_ip"; //切换mcu 重新选点
... ...
... ... @@ -27,6 +27,8 @@ ApeConsts.USER_ACTION_SILENCE_STATUS_CHANGE = 3; //更改用户的禁言状态
ApeConsts.CLASS_ACTION_KICK_OUT_ROSTER=4; //指定的人踢出课堂
ApeConsts.STOP_ALL_PUBLISH=5; //所有人停止推流
ApeConsts.CLASS_ACTION_DRAW_STATUS_CHANGE = 6; //更改用户的画笔状态
ApeConsts.MEDIA_ENABLED_CHANGE = 7; //更改用户的音视频禁用状态
//课堂类型 1:1v1(2路流) 2:直播(1路流) 3:小班课(可以多路流)
ApeConsts.CLASS_TYPE_1v1 = 1; // 互动课堂,通过MS转发音视频,不能进行H5观看 1v1(2路流)
... ...
... ... @@ -855,6 +855,17 @@ class ConferApe extends Ape {
loger.warn('chatMsg->JSON数据解析失败');
}
break;
case ApeConsts.MEDIA_ENABLED_CHANGE:
let mediaMsgObj = null;
try {
mediaMsgObj = JSON.parse(chatMsg.message);
if (mediaMsgObj) {
this.receiveChangeUserMediaEnabledStatus(mediaMsgObj);
}
} catch (err) {
loger.warn('chatMsg->JSON数据解析失败',chatMsg.message);
}
break;
default:
break;
}
... ... @@ -1028,6 +1039,11 @@ class ConferApe extends Ape {
loger.log("监课进入或更新数据");
return;
}
if (nodeData.role == ApeConsts.NR_ASSISTANT && GlobalConfig.userRole != ApeConsts.invisible && GlobalConfig.userRole != ApeConsts.assistant) {
loger.log("助教进入或更新数据");
return;
}
if (!rosterExists) {
//this.rosterLen = Object.keys(this.rosters).length;
//GlobalConfig.rosterNum = this.rosterLen;//记录当前的总人数
... ... @@ -1091,11 +1107,36 @@ class ConferApe extends Ape {
}
}
//设备状态更新
/*
* 设备状态更新
* */
updaterUserDeviecStatusChange(_data) {
loger.log("音视频设备状态更新->", _data);
this.updateUserInfo();
}
/*
* 媒体开启或禁用
* */
sendMediaEnabledChange(_data){
if(!_data){
return;
}
try{
loger.log("发送->媒体开启或禁用",_data);
this.sendConferMsg({"to": 0, "message":JSON.stringify(_data), "actionType": ApeConsts.MEDIA_ENABLED_CHANGE});
}catch (err){
loger.warn("发送->媒体开启或禁用->失败",_data,err.message);
}
}
/*
* 收到媒体开启或禁用控制
* */
receiveChangeUserMediaEnabledStatus(_data){
this._emit(MessageTypes.RECEIVE_MEDIA_ENABLED_CHANGE,_data);
}
//删除用户
rosterDelHandler(nodeId) {
... ... @@ -1114,12 +1155,9 @@ class ConferApe extends Ape {
if(GlobalConfig.classType!= ApeConsts.CLASS_TYPE_ZHIBO){
loger.log(nodeId, "->离开课堂->身份->", user.userRole);
}
}
delete this.rosters[nodeId];
GlobalConfig.rosters = this.rosters;
//this.rosterLen = Object.keys(this.rosters).length;
//GlobalConfig.rosterNum = this.rosterLen;//记录当前的总人数
if(!GlobalConfig.isH5) {
this.emitRosterChange();
... ...
//*
// WebRtc
// */
require('../assets/css/mcuStyle.css');
import Emiter from 'Emiter';
import Loger from "Loger";
import $ from "jquery";
... ... @@ -10,12 +12,13 @@ import EngineUtils from 'EngineUtils';
import MessageTypes from 'MessageTypes';
var AgoraRTC = require('../AgoraRTCSDK-1.14.0');
let loger = Loger.getLoger('WebRtcApe');
const SIZE_480=480;
const SIZE_360=360;
const SIZE_320=320;
const SIZE_240=240;
const SIZE_160=160;
const SIZE_120=120;
const SIZE_480 = 480;
const SIZE_360 = 360;
const SIZE_320 = 320;
const SIZE_240 = 240;
const SIZE_160 = 160;
const SIZE_120 = 120;
class WebRtcApe extends Emiter {
constructor() {
super();
... ... @@ -24,10 +27,10 @@ class WebRtcApe extends Emiter {
this.appCertificate = "";
this.appRecordingKey = "";
this.setConfigTimestamp=0;//设置旁路地址的时间戳
this.setConfigTimestamp = 0;//设置旁路地址的时间戳
this.configPublisherUrl = "";//旁路地址;
this.m3u8Url="";//旁路拉流地址
this.rtmpUrl="";//旁路拉流地址
this.m3u8Url = "";//旁路拉流地址
this.rtmpUrl = "";//旁路拉流地址
this.channelKey = null;
this.channelId = "";
... ... @@ -47,10 +50,10 @@ class WebRtcApe extends Emiter {
this.remoteVideoList = {};//记录远程视频流
this.pWidth=SIZE_480;
this.pHeight=SIZE_360;
this.pFrameRate=30;
this.pBitrate=500;
this.pWidth = SIZE_480;
this.pHeight = SIZE_360;
this.pFrameRate = 30;
this.pBitrate = 500;
//120P 0 160x120 15 65
//240P 20 320x240 15 200
... ... @@ -58,10 +61,10 @@ class WebRtcApe extends Emiter {
this.videoResolution = "240P";
this.isOpenVideo = true;
this.firstPublishSuccess=false;//记录加入频道成功之后是否推流成功过,离开频道之后需要设置为false
this.firstPublishSuccess = false;//记录加入频道成功之后是否推流成功过,离开频道之后需要设置为false
this.isPublish = false;//当前是否正在推流
this.videoScale=1;//视图的缩放比例,默认为1;
this.videoScale = 1;//视图的缩放比例,默认为1;
this.normalRemoteViewId = "";
... ... @@ -85,10 +88,10 @@ class WebRtcApe extends Emiter {
this.invisibleVideoHeight = SIZE_360;
this.xdyRemote = "xdy_remote";
this.localWebRtcVideoClass='localWebRtcVideoClass';//本地视图统一的class名称
this.invisibleWebRtcVideoClass='invisibleWebRtcVideoClass';
this.normalWebRtcVideoClass='normalWebRtcVideoClass';
this.hostWebRtcVideoClass='hostWebRtcVideoClass';
this.localWebRtcVideoClass = 'localWebRtcVideoClass';//本地视图统一的class名称
this.invisibleWebRtcVideoClass = 'invisibleWebRtcVideoClass';
this.normalWebRtcVideoClass = 'normalWebRtcVideoClass';
this.hostWebRtcVideoClass = 'hostWebRtcVideoClass';
//webRtc sdk
this.client = AgoraRTC.createClient({mode: this.mode});
... ... @@ -146,7 +149,7 @@ class WebRtcApe extends Emiter {
this.client.on('stream-published', (evt)=> {
loger.log("webRtc->推流成功->", new Date().getTime());
this.isPublish = true;
this.firstPublishSuccess=true;
this.firstPublishSuccess = true;
GlobalConfig.openCamera = EngineUtils.creatTimestamp();
GlobalConfig.openMicrophones = GlobalConfig.openCamera;
this._emit(MessageTypes.USER_DEVICE_STATUS_CHAANGE, {
... ... @@ -208,41 +211,47 @@ class WebRtcApe extends Emiter {
}
//添加之前先删除之前存在的重复视图
let len=$("#"+this.xdyRemote + uid+" #player_" + uid).length;
if(len<1){
loger.log("添加之前先删除之前存在的重复视图",uid);
$("#"+this.xdyRemote + uid).remove();
let len = $("#" + this.xdyRemote + uid + " #player_" + uid).length;
if (len < 1) {
loger.log("添加之前先删除之前存在的重复视图", uid);
$("#" + this.xdyRemote + uid).remove();
}
let audioMutedDiv = "";
if (GlobalConfig.isTeachOrAssistant || GlobalConfig.isInvisible) {
audioMutedDiv = `<div class="audioMuted audioOpen" id=${"audioMuted_"+uid}></div>`;
}
if (userRole == ApeConsts.invisible) {
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>`;
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>`;
//把远程视频添加到监课列表
loger.log("获取远程视频流成功->监课:" + userName + "->" + uid, new Date().getTime());
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>`;
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>`;
$(this.invisibleViewId).append(viewDiv);
} else if (userRole == ApeConsts.host||userRole == ApeConsts.assistant||userRole == ApeConsts.presenter) {
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>`;
} else if (userRole == ApeConsts.host || userRole == ApeConsts.assistant || userRole == ApeConsts.presenter) {
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>`;
//把远程视图添加到老师列表
loger.log("获取远程视频流成功->userRole:"+userRole+":" + userName + "->" + uid, new Date().getTime());
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>`;
loger.log("获取远程视频流成功->userRole:" + userRole + ":" + userName + "->" + uid, new Date().getTime());
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>`;
$(this.hostRemoteViewId).prepend(viewDiv);
} else {
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>`;
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>`;
//把视图添加到学生列表
loger.log("获取远程视频流成功->学生:" + userName + "->" + uid, new Date().getTime());
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>`;
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>`;
$(this.normalRemoteViewId).append(viewDiv);
}
$("#audioMuted_" + uid).off("click", this._clickAudioMuted.bind(this));
$("#audioMuted_" + uid).on("click", this._clickAudioMuted.bind(this));
//播放视频,隐藏控制条
try {
$("bar_" + stream.getId()).hide();
$("#bar_" + stream.getId()).hide();
stream.play(this.xdyRemote + stream.getId());
} catch (err) {
//添加之前先删除之前存在的重复视图
let len=$("#"+this.xdyRemote + uid+" #player_" + uid).length;
if(len<1){
lloger.log("流播放失败->删除视图",uid);
$("#"+this.xdyRemote + uid).remove();
let len = $("#" + this.xdyRemote + uid + " #player_" + uid).length;
if (len < 1) {
loger.log("流播放失败->删除视图", uid);
$("#" + this.xdyRemote + uid).remove();
}
}
if (user && (user.deviceType == GlobalConfig.deviceIOS || user.deviceType == GlobalConfig.deviceAndroid)) {
... ... @@ -252,43 +261,44 @@ class WebRtcApe extends Emiter {
this.clearInvalidVideoView();
}
//清除无效的视图
clearInvalidVideoView(){
let normalList=document.getElementsByClassName(this.normalWebRtcVideoClass);
let hostList=document.getElementsByClassName(this.hostWebRtcVideoClass);
let localList=document.getElementsByClassName(this.localWebRtcVideoClass);
let divItem=null;
if(normalList){
for (let i=normalList.length-1;i>=0;i--){
divItem=normalList[i];
if(divItem&&divItem.children.length<2){
clearInvalidVideoView() {
let normalList = document.getElementsByClassName(this.normalWebRtcVideoClass);
let hostList = document.getElementsByClassName(this.hostWebRtcVideoClass);
let localList = document.getElementsByClassName(this.localWebRtcVideoClass);
let divItem = null;
if (normalList) {
for (let i = normalList.length - 1; i >= 0; i--) {
divItem = normalList[i];
if (divItem && divItem.children.length < 2) {
console.log("删除无效的学生视图");
divItem.remove();
}
}
}
divItem=null;
if(hostList){
for (let i=hostList.length-1;i>=0;i--){
divItem=hostList[i];
if(divItem&&divItem.children.length<2){
divItem = null;
if (hostList) {
for (let i = hostList.length - 1; i >= 0; i--) {
divItem = hostList[i];
if (divItem && divItem.children.length < 2) {
console.log("删除无效的老师视图");
divItem.remove();
}
}
}
divItem=null;
if(localList){
for (let i=localList.length-1;i>=0;i--){
divItem=localList[i];
if(divItem&&divItem.children.length<2){
divItem = null;
if (localList) {
for (let i = localList.length - 1; i >= 0; i--) {
divItem = localList[i];
if (divItem && divItem.children.length < 2) {
console.log("删除无效的本地视图");
divItem.remove();
}
}
}
divItem=null;
divItem = null;
}
... ... @@ -331,8 +341,8 @@ class WebRtcApe extends Emiter {
//console.log("remoteView->", remoteView)
if (remoteView) {
let player = document.getElementById("player_" + nodeId);
let len=$("#"+this.xdyRemote + nodeId+" #player_" + nodeId).length;
if (len>0) {
let len = $("#" + this.xdyRemote + nodeId + " #player_" + nodeId).length;
if (len > 0) {
loger.log(nodeId + " 流已经添加显示,不需要再处理");
return;
} else {
... ... @@ -358,29 +368,29 @@ class WebRtcApe extends Emiter {
//记录加入频道成功之后是否立即推流,默认false
//一般只有在刷新重进频道的时候会用到
this.immediatePublish=_params.immediatePublish||false;
this.immediatePublish = _params.immediatePublish || false;
//根据不同身份设置不同的分辨率
if(GlobalConfig.isTeachOrAssistant){
if(GlobalConfig.maxMediaChannels==1){
if (GlobalConfig.isTeachOrAssistant) {
if (GlobalConfig.maxMediaChannels == 1) {
//直播时使用标清最高档
this.videoResolution="360P_8";
}else {
this.videoResolution="240P";
this.videoResolution = "360P_8";
} else {
this.videoResolution = "240P";
}
}else if(GlobalConfig.isInvisible){
this.videoResolution="120P";
}else {
} else if (GlobalConfig.isInvisible) {
this.videoResolution = "120P";
} else {
//学生在两路视频的时候使用240P 其他多人课堂的时候使用低清的
if(GlobalConfig.maxMediaChannels==2||GlobalConfig.maxMediaChannels>3){
this.videoResolution="240P"
}else {
if (GlobalConfig.maxMediaChannels == 2 || GlobalConfig.maxMediaChannels > 3) {
this.videoResolution = "240P"
} else {
//180P_4 13 240x180 15 120
this.videoResolution="180P_4"
this.videoResolution = "180P_4"
}
}
loger.log("开始加入视频通话频道->channelId:" + this.channelId, "uid:" + this.uid,"videoResolution:"+this.videoResolution);
loger.log("开始加入视频通话频道->channelId:" + this.channelId, "uid:" + this.uid, "videoResolution:" + this.videoResolution);
this.client.join(this.channelKey, "" + this.channelId, this.uid, (uid)=> {
this.uid = uid;
loger.log("加入视频通话频道->成功->channelId:" + this.channelId, "uid:" + this.uid);
... ... @@ -388,12 +398,12 @@ class WebRtcApe extends Emiter {
this.openLoaclStream();
//加入频道成功之后需要判断是否立即开启推流
if(this.immediatePublish==true){
loger.log("加入音视频频道成功->立刻开始推流->"+this.immediatePublish);
if (this.immediatePublish == true) {
loger.log("加入音视频频道成功->立刻开始推流->" + this.immediatePublish);
clearTimeout(this.rePublishDelay);
this.rePublishDelay=setTimeout(()=>{
this.rePublishDelay = setTimeout(()=> {
this.publish();
},200);
}, 200);
}
}, (err)=> {
loger.error("加入视频通话频道->失败->", err);
... ... @@ -439,11 +449,11 @@ class WebRtcApe extends Emiter {
}
leaveChannel() {
loger.log("调用离开视频通话频道->isPublish"+this.isPublish);
loger.log("调用离开视频通话频道->isPublish" + this.isPublish);
if (!this.client) {
return;
}
this.firstPublishSuccess=false;
this.firstPublishSuccess = false;
this.unpublish();
this.client.leave(() => {
loger.log("离开视频通话频道->成功");
... ... @@ -469,31 +479,39 @@ class WebRtcApe extends Emiter {
/*
* 设置旁录地址
* */
setConfigPublisherUrl(_publishUrl){
this.firstPublishSuccess=false;
this.setConfigTimestamp=new Date().getTime()/1000;
this.configPublisherUrl=_publishUrl;
if(this.client&& this.configPublisherUrl){
let configObj={width: parseInt(this.pWidth), height: parseInt(this.pHeight), framerate: parseInt(this.pFrameRate), bitrate: parseInt(this.pBitrate), publishUrl:""+this.configPublisherUrl};
setConfigPublisherUrl(_publishUrl) {
this.firstPublishSuccess = false;
this.setConfigTimestamp = new Date().getTime() / 1000;
this.configPublisherUrl = _publishUrl;
if (this.client && this.configPublisherUrl) {
let configObj = {
width: parseInt(this.pWidth),
height: parseInt(this.pHeight),
framerate: parseInt(this.pFrameRate),
bitrate: parseInt(this.pBitrate),
publishUrl: "" + this.configPublisherUrl
};
//let configObj={width: 480, height:360, framerate:30, bitrate:500, publishUrl:_publishUrl};
//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'};
loger.warn("设置旁路地址->",configObj);
loger.warn("设置旁路地址->", configObj);
this.client.configPublisher(configObj);
}else {
loger.warn("设置旁路地址->失败->为初始化或旁路地址无效",_publishUrl);
} else {
loger.warn("设置旁路地址->失败->为初始化或旁路地址无效", _publishUrl);
}
}
/*
* 设置旁录拉流地址
* */
setRtmpM3u8Path(_param){
setRtmpM3u8Path(_param) {
//_webRtc.setRtmpM3u8Path({m3u8Url:m3u8Stream,rtmpUrl:rtmpStream});
loger.log("设置旁录拉流地址",_param);
if(_param){
this.m3u8Url=_param.m3u8Url||"";
this.rtmpUrl=_param.rtmpUrl||"";
loger.log("设置旁录拉流地址", _param);
if (_param) {
this.m3u8Url = _param.m3u8Url || "";
this.rtmpUrl = _param.rtmpUrl || "";
}
}
publish(_params) {
if (!this.client || !this.localStream) {
loger.warn("推流失败->未加入频道!");
... ... @@ -504,13 +522,13 @@ class WebRtcApe extends Emiter {
return;
}
//老师-助教-主讲人-->设置旁路大于30秒没有推流,推流服务会停止,需要重设旁录和重加频道;
if(this.setConfigTimestamp>0&&GlobalConfig.isTeachOrAssistant){
if (this.setConfigTimestamp > 0 && GlobalConfig.isTeachOrAssistant) {
//如果间隔大于28秒并且没有推过流需要重新加入频道,推成功一次之后就不需要
let interval=parseInt(new Date().getTime()/1000-this.setConfigTimestamp);
loger.log("设置旁路的时间和推流时间的间隔->"+interval+" firstPublishSuccess:"+ this.firstPublishSuccess);
if(interval>=28&&!this.firstPublishSuccess){
let interval = parseInt(new Date().getTime() / 1000 - this.setConfigTimestamp);
loger.log("设置旁路的时间和推流时间的间隔->" + interval + " firstPublishSuccess:" + this.firstPublishSuccess);
if (interval >= 28 && !this.firstPublishSuccess) {
loger.warn("设置旁路大于30秒没有推流,推流服务会停止,需要重设旁录和重加频道");
this._emit(WebRtcApe.RE_JOIN_CHANNEL,{publish:true});
this._emit(WebRtcApe.RE_JOIN_CHANNEL, {publish: true});
return;
}
}
... ... @@ -520,9 +538,9 @@ class WebRtcApe extends Emiter {
let viewName = 'localVideoBox_' + this.uid;
let videoBox = document.createElement("div");
videoBox.id = viewName;
videoBox.className=this.localWebRtcVideoClass;
videoBox.style.width = (this.localVideoWidth*this.videoScale) + 'px';
videoBox.style.height = (this.localVideoHeight*this.videoScale) + 'px';
videoBox.className = this.localWebRtcVideoClass;
videoBox.style.width = (this.localVideoWidth * this.videoScale) + 'px';
videoBox.style.height = (this.localVideoHeight * this.videoScale) + 'px';
videoBox.style.float = 'left';
videoBox.style.marginRight = "1px";
videoBox.style.pointerEvents = 'none';
... ... @@ -536,8 +554,14 @@ class WebRtcApe extends Emiter {
if (user) {
userName = user.name || "";
}
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>`;
let audioMutedDiv = "";
if (GlobalConfig.isTeachOrAssistant) {
audioMutedDiv = `<div class="audioMuted audioOpen" id=${"audioMuted_"+this.uid}></div>`;
}
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>`;
$(this.localViewId).prepend(nameDiv);
$(".audioMuted").off("click", this._clickAudioMuted.bind(this));
$(".audioMuted").on("click", this._clickAudioMuted.bind(this));
loger.log("webRtc->推流->", viewName, new Date().getTime());
this.localStream.play(viewName);
... ... @@ -553,31 +577,31 @@ class WebRtcApe extends Emiter {
this.isPublish = false;
this.clearLocalView();
this._emit(MessageTypes.WEB_RTC_PUBLISH_FAILED, err);
if(err) {
if (err) {
switch (err.msg) {
case "DEVICES_NOT_FOUND":
this.curCameraId="";
this.curMicrophoneId="";
this.curCameraId = "";
this.curMicrophoneId = "";
this.unpublish();
break;
case "NOT_SUPPORTED":
this.curCameraId="";
this.curMicrophoneId="";
this.curCameraId = "";
this.curMicrophoneId = "";
this.unpublish();
break;
case "PERMISSION_DENIED":
this.curCameraId="";
this.curMicrophoneId="";
this.curCameraId = "";
this.curMicrophoneId = "";
this.unpublish();
break;
case "CONSTRAINT_NOT_SATISFIED":
this.curCameraId="";
this.curMicrophoneId="";
this.curCameraId = "";
this.curMicrophoneId = "";
this.unpublish();
break;
case "STREAM_ALREADY_INITIALIZED":
this.curCameraId="";
this.curMicrophoneId="";
this.curCameraId = "";
this.curMicrophoneId = "";
this.unpublish();
break;
default:
... ... @@ -617,38 +641,38 @@ class WebRtcApe extends Emiter {
$('#localVideoBox_' + this.uid).remove();
$("#videoOwnerName_" + this.uid).remove();
$(".localVideoOwnerName").remove();
$("."+this.localWebRtcVideoClass).remove();
$("." + this.localWebRtcVideoClass).remove();
}
/*
* 更新所有视频的尺寸大小
* */
updateAllVideoSize(){
$("."+this.localWebRtcVideoClass).css("width",this.localVideoWidth*this.videoScale);
$("."+this.localWebRtcVideoClass).css("height",this.localVideoHeight*this.videoScale);
updateAllVideoSize() {
$("." + this.localWebRtcVideoClass).css("width", this.localVideoWidth * this.videoScale);
$("." + this.localWebRtcVideoClass).css("height", this.localVideoHeight * this.videoScale);
$("."+this.hostWebRtcVideoClass).css("width",this.hostRemoteVideoWidth*this.videoScale);
$("."+this.hostWebRtcVideoClass).css("height",this.hostRemoteVideoHeight*this.videoScale);
$("." + this.hostWebRtcVideoClass).css("width", this.hostRemoteVideoWidth * this.videoScale);
$("." + this.hostWebRtcVideoClass).css("height", this.hostRemoteVideoHeight * this.videoScale);
$("."+this.normalWebRtcVideoClass).css("width",this.normalRemoteVideoWidth*this.videoScale);
$("."+this.normalWebRtcVideoClass).css("height",this.normalRemoteVideoHeight*this.videoScale);
$("." + this.normalWebRtcVideoClass).css("width", this.normalRemoteVideoWidth * this.videoScale);
$("." + this.normalWebRtcVideoClass).css("height", this.normalRemoteVideoHeight * this.videoScale);
}
/*
* 设置rtc视频的属性
* */
changeRtcVideoConfig(_params){
* 设置rtc视频的属性
* */
changeRtcVideoConfig(_params) {
//{videoScale:1}
if(!_params){
if (!_params) {
return;
}
let scale=parseInt(_params.videoScale)||1;//最小值只能为1,这个是按倍数缩放视频
if(this.videoScale==scale){
let scale = parseInt(_params.videoScale) || 1;//最小值只能为1,这个是按倍数缩放视频
if (this.videoScale == scale) {
return;
}
this.videoScale=scale;
loger.log("更新视频视图大小->videoScale:"+this.videoScale);
this.videoScale = scale;
loger.log("更新视频视图大小->videoScale:" + this.videoScale);
this.updateAllVideoSize();
}
... ... @@ -663,8 +687,8 @@ class WebRtcApe extends Emiter {
this.localVideoHeight = parseInt(_params.height) || SIZE_360;
this.nameDisplay = _params.nameDisplay || "block";
this.localVideoWidth=this.localVideoWidth;
this.localVideoHeight=this.localVideoHeight;
this.localVideoWidth = this.localVideoWidth;
this.localVideoHeight = this.localVideoHeight;
}
/*
... ... @@ -676,8 +700,8 @@ class WebRtcApe extends Emiter {
this.hostRemoteStyle = _params.styleStr || "";
this.hostRemoteVideoWidth = parseInt(_params.width) || SIZE_480;
this.hostRemoteVideoHeight = parseInt(_params.height) || SIZE_360;
this.hostRemoteVideoWidth=this.hostRemoteVideoWidth;
this.hostRemoteVideoHeight=this.hostRemoteVideoHeight;
this.hostRemoteVideoWidth = this.hostRemoteVideoWidth;
this.hostRemoteVideoHeight = this.hostRemoteVideoHeight;
}
/*
... ... @@ -690,8 +714,8 @@ class WebRtcApe extends Emiter {
this.normalRemoteVideoWidth = parseInt(_params.width) || SIZE_480;
this.normalRemoteVideoHeight = parseInt(_params.height) || SIZE_360;
this.normalRemoteVideoWidth=this.normalRemoteVideoWidth;
this.normalRemoteVideoHeight=this.normalRemoteVideoHeight;
this.normalRemoteVideoWidth = this.normalRemoteVideoWidth;
this.normalRemoteVideoHeight = this.normalRemoteVideoHeight;
}
/*
... ... @@ -708,12 +732,12 @@ class WebRtcApe extends Emiter {
/*
* 设置旁录推流的参数
* */
setConfigPublisher(_params){
loger.log("设置旁录推流的参数",_params);
this.pWidth=_params.width||SIZE_480;
this.pHeight=_params.height||SIZE_360;
this.pFrameRate=_params.frameRate||30;
this.pBitrate=_params.bitrate||500;
setConfigPublisher(_params) {
loger.log("设置旁录推流的参数", _params);
this.pWidth = _params.width || SIZE_480;
this.pHeight = _params.height || SIZE_360;
this.pFrameRate = _params.frameRate || 30;
this.pBitrate = _params.bitrate || 500;
}
/*
... ... @@ -776,7 +800,7 @@ class WebRtcApe extends Emiter {
for (let i = 0; i < devices.length; i++) {
let device = devices[i];
//{"deviceId":"default","kind":"audiooutput","label":"默认","groupId":"cf49a03ca26700235629fc13d3e6630bd34407c66438d157056a34dd3ae03ef5"}
if(device){
if (device) {
if (device.kind == 'audioinput') {
this.microphones.push(device);
GlobalConfig.microphones.push(device.label);
... ... @@ -796,13 +820,107 @@ class WebRtcApe extends Emiter {
});
}
_clickAudioMuted(evt) {
let className = evt.currentTarget.className;
console.log("点击禁音",evt.currentTarget.id);
let idArr = (evt.currentTarget.id).split("_");
let uid = 10000000;//默认设置一个不存在的uid
if (idArr && idArr.length > 1) {
uid = parseInt(idArr[1]);
}
if (className.indexOf("audioOpen") > 0) {
loger.log("点击禁音->"+uid);
// evt.currentTarget.className="audioMuted audioClose";
if (uid != GlobalConfig.nodeId) {
this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: false});
$("#audioMuted_" + uid).removeClass();
$("#audioMuted_" + uid).addClass("audioMuted audioClose");
} else {
this.disableAudio(uid);
}
} else {
loger.log("点击开启声音");
//evt.currentTarget.className="audioMuted audioOpen";
if (uid != GlobalConfig.nodeId) {
this.sendChangeUserMediaEnabled({nodeId: uid, video: true, audio: true});
$("#audioMuted_" + uid).removeClass();
$("#audioMuted_" + uid).addClass("audioMuted audioOpen");
} else {
this.enableAudio(uid);
}
}
}
/*
* 发送控制音视频禁用消息
* */
sendChangeUserMediaEnabled(_param) {
this._emit(MessageTypes.MEDIA_ENABLED_CHANGE, _param);
}
/*
* 收到控制音视频禁用消息
* */
webRtcMeiaEnabledChange(_data) {
loger.log("收到控制音视频禁用消息",_data);
// {nodeId: uid, video: true, audio: false}
if(!_data){
return;
}
if(_data.nodeId!=GlobalConfig.nodeId){
if(_data.audio==false){
$("#audioMuted_" + _data.nodeId).removeClass();
$("#audioMuted_" + _data.nodeId).addClass("audioMuted audioClose");
}else {
$("#audioMuted_" + _data.nodeId).removeClass();
$("#audioMuted_" + _data.nodeId).addClass("audioMuted audioOpen");
}
}else{
if(_data.audio==false){
this.disableAudio(_data.nodeId);
}else {
this.enableAudio(_data.nodeId);
}
}
}
/*
* 开启禁音
* */
disableAudio(uid) {
loger.log("开启禁音:" + uid);
if (parseInt(uid) == GlobalConfig.nodeId) {
if (this.localStream) {
$("#audioMuted_" + uid).removeClass();
$("#audioMuted_" + uid).addClass("audioMuted audioClose");
this.localStream.disableAudio();
}
}
}
/*
* 开启音频
* */
enableAudio(_uid) {
loger.log("开启音频:" + _uid);
if (parseInt(_uid) == GlobalConfig.nodeId) {
if (this.localStream) {
this.localStream.enableAudio();
$("#audioMuted_" + _uid).removeClass();
$("#audioMuted_" + _uid).addClass("audioMuted audioOpen");
}
}
}
//组织数据,发送给服务器,控制录制和开启录制-推流和停止推流 status:0 停止推流 1:开始推流(同时开启录制),2:停止录制(同时停止推流)
packMediaInfoData(_status) {
let curTimestamp = new Date().getTime();
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}`;
//markettest_623790840_T9540_1508207080
let streamId=GlobalConfig.siteId+"_"+GlobalConfig.classId+"_"+GlobalConfig.userId+"_"+curTimestamp;
let streamId = GlobalConfig.siteId + "_" + GlobalConfig.classId + "_" + GlobalConfig.userId + "_" + curTimestamp;
//mcu记录一份数据
this._emit(MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE, {
appId: GlobalConfig.appId,
... ... @@ -815,10 +933,10 @@ class WebRtcApe extends Emiter {
userRole: GlobalConfig.userRole,
timestamp: curTimestamp,
recordTimestamp: GlobalConfig.recordTimestamp,
streamId:streamId,
publishUrl:this.configPublisherUrl,
m3u8Url:this.m3u8Url,
rtmpUrl:this.rtmpUrl
streamId: streamId,
publishUrl: this.configPublisherUrl,
m3u8Url: this.m3u8Url,
rtmpUrl: this.rtmpUrl
});
return data;
}
... ... @@ -833,7 +951,7 @@ class WebRtcApe extends Emiter {
}
let url = GlobalConfig.locationProtocol + GlobalConfig.recordInterfaces;
let data = this.packMediaInfoData(_status);
loger.log("调用服务器端更新视频录制状态->status",_status);
loger.log("调用服务器端更新视频录制状态->status", _status);
fetch(encodeURI(url), {
method: 'POST',
headers: {
... ... @@ -863,14 +981,14 @@ class WebRtcApe extends Emiter {
}
/*
* 切换音视频的录制状态
* */
* 切换音视频的录制状态
* */
changeMediaRecordStatus(_params) {
if (!GlobalConfig.recordInterfaces||!_params) {
loger.warn("切换音视频的录制状态->失败->接口地址无效",_params);
if (!GlobalConfig.recordInterfaces || !_params) {
loger.warn("切换音视频的录制状态->失败->接口地址无效", _params);
return;
}
loger.warn("切换音视频的录制状态->"+_params);
loger.warn("切换音视频的录制状态->" + _params);
let url = GlobalConfig.locationProtocol + GlobalConfig.recordInterfaces;
let curTimestamp = new Date().getTime();
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}`;
... ...
@charset "utf-8";
/*禁音按钮*/
.audioMuted{
margin-left: 6px;
float: right;
width: 20px;
height: 20px;
cursor: pointer;
background-size: auto;
background-repeat: no-repeat;
}
.audioClose {
background-image: url(../../assets/img/audioClose.png);
}
.audioOpen {
background-image: url(../../assets/img/audioOpen.png);
}
\ No newline at end of file
... ...