1.修改视频模块数据的PDU
2.推流和播流地址根据类型拼接 3.在会议模块增加对视频模块的无效的占用channel的释放
正在显示
6 个修改的文件
包含
88 行增加
和
35 行删除
| @@ -77,6 +77,8 @@ export default class MessageEntrance extends Emiter { | @@ -77,6 +77,8 @@ export default class MessageEntrance extends Emiter { | ||
| 77 | _confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件 | 77 | _confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件 |
| 78 | _confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this));//当前会议状态信息发生改变 | 78 | _confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this));//当前会议状态信息发生改变 |
| 79 | _confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this));//当前会议人员离开 | 79 | _confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this));//当前会议人员离开 |
| 80 | + _confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER,this._onClassNonentityRoster.bind(this));//当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在 | ||
| 81 | + | ||
| 80 | 82 | ||
| 81 | _chat_ape = new ChatApe(); | 83 | _chat_ape = new ChatApe(); |
| 82 | _chat_ape.on('*', (type, data) => this._emit(type, data)); | 84 | _chat_ape.on('*', (type, data) => this._emit(type, data)); |
| @@ -180,11 +182,24 @@ export default class MessageEntrance extends Emiter { | @@ -180,11 +182,24 @@ export default class MessageEntrance extends Emiter { | ||
| 180 | if(_data!=null&&_data.nodeId!=null&&GlobalConfig.isHost){ | 182 | if(_data!=null&&_data.nodeId!=null&&GlobalConfig.isHost){ |
| 181 | loger.log("有人员离开,检查一下离开的人员是否关闭推流"); | 183 | loger.log("有人员离开,检查一下离开的人员是否关闭推流"); |
| 182 | if(_video_ape){ | 184 | if(_video_ape){ |
| 183 | - _video_ape.stopPublishVideo(_data.nodeId); | 185 | + _video_ape.stopPublishVideo(_data); |
| 184 | } | 186 | } |
| 185 | } | 187 | } |
| 186 | } | 188 | } |
| 187 | 189 | ||
| 190 | + //当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel | ||
| 191 | + //的占用状态导致,对于这种情况,需要释放掉 | ||
| 192 | + _onClassNonentityRoster(_param){ | ||
| 193 | + if(_param==null||_param.fromNodeId==null){ | ||
| 194 | + loger.warn("onClassNonentityRoster.参数错误") | ||
| 195 | + return; | ||
| 196 | + } | ||
| 197 | + if(_video_ape){ | ||
| 198 | + _video_ape.stopPublishVideo({"nodeId":_param.fromNodeId}); | ||
| 199 | + } | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + | ||
| 188 | //Sass | 203 | //Sass |
| 189 | //初始化 | 204 | //初始化 |
| 190 | _init(_param, _onSuccess, _mcuErrorCallBack) { | 205 | _init(_param, _onSuccess, _mcuErrorCallBack) { |
| @@ -397,13 +412,14 @@ export default class MessageEntrance extends Emiter { | @@ -397,13 +412,14 @@ export default class MessageEntrance extends Emiter { | ||
| 397 | //包含整个会议最全的信息,储存数据 | 412 | //包含整个会议最全的信息,储存数据 |
| 398 | if (_data) { | 413 | if (_data) { |
| 399 | GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表 | 414 | GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表 |
| 400 | - GlobalConfig.setDocRecordList(_data.docRecordList);// | ||
| 401 | - GlobalConfig.setDocList(_data.docList);// | ||
| 402 | - GlobalConfig.setMsList(_data.msList);// | ||
| 403 | - GlobalConfig.setMcuList(_data.mcuList);// | 415 | + GlobalConfig.setDocRecordList(_data.docRecordList);//录制回放地址?? |
| 416 | + GlobalConfig.setDocList(_data.docList);//文档地址 | ||
| 417 | + GlobalConfig.setMsList(_data.msList);//推流播流服务器地址 | ||
| 418 | + GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址 | ||
| 419 | + GlobalConfig.setMcuList(_data.mcuList);//mcu | ||
| 404 | GlobalConfig.setMusicList(_data.musicList);// | 420 | GlobalConfig.setMusicList(_data.musicList);// |
| 405 | - GlobalConfig.setMusicListPrepare(_data.musicListPrepare);// | ||
| 406 | - GlobalConfig.setRsList(_data.rsList);// | 421 | + GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表 |
| 422 | + | ||
| 407 | 423 | ||
| 408 | } | 424 | } |
| 409 | if (_data.currentInfo) { | 425 | if (_data.currentInfo) { |
| @@ -16,8 +16,10 @@ MessageTypes.CLASS_JOIN_SUCCESS = 'join.class.success'; | @@ -16,8 +16,10 @@ MessageTypes.CLASS_JOIN_SUCCESS = 'join.class.success'; | ||
| 16 | //会议信息和操作事件定义 | 16 | //会议信息和操作事件定义 |
| 17 | //MessageTypes.CLASS_SHOW_DETAIL = 'class_detail.message'; | 17 | //MessageTypes.CLASS_SHOW_DETAIL = 'class_detail.message'; |
| 18 | MessageTypes.CLASS_SHOW_ROSTER_NUM = 'roster_num.message'; | 18 | MessageTypes.CLASS_SHOW_ROSTER_NUM = 'roster_num.message'; |
| 19 | -MessageTypes.CLASS_INSERT_ROSTER = 'roster_insert.message'; | ||
| 20 | -MessageTypes.CLASS_DELETE_ROSTER = 'roster_delete.message'; | 19 | +MessageTypes.CLASS_INSERT_ROSTER = 'roster.insert.message'; |
| 20 | +MessageTypes.CLASS_DELETE_ROSTER = 'roster.delete.message'; | ||
| 21 | +MessageTypes.CLASS_NONENTITY_ROSTER = 'roster.nonentity.message'; | ||
| 22 | + | ||
| 21 | MessageTypes.CLASS_EXIT = 'class.exit';//退出 关闭会议 | 23 | MessageTypes.CLASS_EXIT = 'class.exit';//退出 关闭会议 |
| 22 | MessageTypes.CLASS_UPTATE_STATUS = 'class.update.status';//更新会议状态信息 | 24 | MessageTypes.CLASS_UPTATE_STATUS = 'class.update.status';//更新会议状态信息 |
| 23 | MessageTypes.CLASS_STATUS_INFO_CHANGE= 'class.status.info.change';//会议状态信息发生改变,需要保存数据到sass和同步MCU | 25 | MessageTypes.CLASS_STATUS_INFO_CHANGE= 'class.status.info.change';//会议状态信息发生改变,需要保存数据到sass和同步MCU |
| @@ -97,7 +97,7 @@ ApeConsts.CHANNEL_STATUS_OPENING = 1;///< 已经占用成功 | @@ -97,7 +97,7 @@ ApeConsts.CHANNEL_STATUS_OPENING = 1;///< 已经占用成功 | ||
| 97 | //媒体类型 | 97 | //媒体类型 |
| 98 | ApeConsts.MEDIA_TYPE_DEFAULT=0;//没有类型 | 98 | ApeConsts.MEDIA_TYPE_DEFAULT=0;//没有类型 |
| 99 | ApeConsts.MEDIA_TYPE_VIDEO=1;//视频流(包含音频) | 99 | ApeConsts.MEDIA_TYPE_VIDEO=1;//视频流(包含音频) |
| 100 | -ApeConsts.MEDIA_TYPE_VIDEO=2;//音频流 | 100 | +ApeConsts.MEDIA_TYPE_AUDIO=2;//音频流 |
| 101 | 101 | ||
| 102 | //FLASH中使用下面4个 | 102 | //FLASH中使用下面4个 |
| 103 | ApeConsts.CGS_RELEASED = 0;///< 无人占用状态 | 103 | ApeConsts.CGS_RELEASED = 0;///< 无人占用状态 |
| @@ -12,16 +12,9 @@ import Loger from 'Loger'; | @@ -12,16 +12,9 @@ import Loger from 'Loger'; | ||
| 12 | import GlobalConfig from 'GlobalConfig'; | 12 | import GlobalConfig from 'GlobalConfig'; |
| 13 | import EngineUtils from 'EngineUtils'; | 13 | import EngineUtils from 'EngineUtils'; |
| 14 | 14 | ||
| 15 | - | ||
| 16 | let loger = Loger.getLoger('ConferApe'); | 15 | let loger = Loger.getLoger('ConferApe'); |
| 17 | let itemIdx=0;//table插入新数据的计数id,目前用时间戳 | 16 | let itemIdx=0;//table插入新数据的计数id,目前用时间戳 |
| 18 | -let timerCounter; | ||
| 19 | 17 | ||
| 20 | -//const ACTION_TYPE_0=0; | ||
| 21 | -//const ACTION_TYPE_1=1; | ||
| 22 | -//const ACTION_TYPE_2=2; | ||
| 23 | -//const ACTION_TYPE_3=3; | ||
| 24 | -//const ACTION_TYPE_4=4; | ||
| 25 | class ConferApe extends Ape { | 18 | class ConferApe extends Ape { |
| 26 | constructor() { | 19 | constructor() { |
| 27 | super( | 20 | super( |
| @@ -460,9 +453,22 @@ class ConferApe extends Ape { | @@ -460,9 +453,22 @@ class ConferApe extends Ape { | ||
| 460 | 453 | ||
| 461 | //视频模块发生更新,人员状态需要更新 | 454 | //视频模块发生更新,人员状态需要更新 |
| 462 | updaterRosterStatus(_param){ | 455 | updaterRosterStatus(_param){ |
| 463 | - loger.log("视频模块发生更新,人员状态需要更新"); | ||
| 464 | - console.log(_param); | ||
| 465 | - //如果是自己。改变自己的状态同步到MCU | 456 | + if(_param){ |
| 457 | + loger.log("视频模块发生更新,人员状态需要更新,fromNodeId->",_param.fromNodeId); | ||
| 458 | + loger.log(_param.status,_param.fromNodeId,this.rosters[_param.fromNodeId]); | ||
| 459 | + //console.log(_param.fromNodeId); | ||
| 460 | + //如果是自己。改变自己的状态同步到MCU | ||
| 461 | + //if(_param.fromNodeId==GlobalConfig.nodeId){ | ||
| 462 | + // | ||
| 463 | + //} | ||
| 464 | + | ||
| 465 | + | ||
| 466 | + //如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的 | ||
| 467 | + if(_param.status==ApeConsts.CHANNEL_STATUS_OPENING&&this.rosters[_param.fromNodeId]==null){ | ||
| 468 | + loger.log("视频模块被占用,占有人已经不存在课堂中,释放Channel,_param->",_param); | ||
| 469 | + this._emit(MessageTypes.CLASS_NONENTITY_ROSTER,_param.fromNodeId); | ||
| 470 | + } | ||
| 471 | + } | ||
| 466 | } | 472 | } |
| 467 | //删除用户 | 473 | //删除用户 |
| 468 | rosterDelHandler(nodeId) { | 474 | rosterDelHandler(nodeId) { |
| @@ -570,7 +576,6 @@ class ConferApe extends Ape { | @@ -570,7 +576,6 @@ class ConferApe extends Ape { | ||
| 570 | return null; | 576 | return null; |
| 571 | } | 577 | } |
| 572 | 578 | ||
| 573 | - | ||
| 574 | } | 579 | } |
| 575 | 580 | ||
| 576 | export default ConferApe; | 581 | export default ConferApe; |
| @@ -56,18 +56,21 @@ class VideoChat extends Ape { | @@ -56,18 +56,21 @@ class VideoChat extends Ape { | ||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | let path = ""; | 58 | let path = ""; |
| 59 | + let port=""; | ||
| 59 | if (_param.type == "m3u8") { | 60 | if (_param.type == "m3u8") { |
| 60 | - //M3U8 默认用80端口 | ||
| 61 | - //http://123.56.73.119/hls/h5dev_403074980_0_983042_1487641745/index.m3u8 | 61 | + //M3U8 |
| 62 | + //http://123.56.73.119:6001/hls/h5dev_403074980_0_983041_1487663265/index.m3u8 | ||
| 63 | + port = (GlobalConfig.RSServerPort == "" || GlobalConfig.RSServerPort == null) ? "":":" + GlobalConfig.RSServerPort; | ||
| 62 | path = "http://" + GlobalConfig.RSServerIP | 64 | path = "http://" + GlobalConfig.RSServerIP |
| 63 | - +"/hls/" + _param.siteId | 65 | + + port + "/live/" |
| 66 | + + _param.siteId | ||
| 64 | + "_" + _param.classId | 67 | + "_" + _param.classId |
| 65 | + "_" + _param.userId | 68 | + "_" + _param.userId |
| 66 | + "_" + _param.channelId | 69 | + "_" + _param.channelId |
| 67 | + "_" + _param.timestamp | 70 | + "_" + _param.timestamp |
| 68 | + "/index.m3u8"; | 71 | + "/index.m3u8"; |
| 69 | } else { | 72 | } else { |
| 70 | - let port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "" : ":" + GlobalConfig.MSServerPort; | 73 | + port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort; |
| 71 | path = "rtmp://" + GlobalConfig.MSServerIP | 74 | path = "rtmp://" + GlobalConfig.MSServerIP |
| 72 | + port + "/live/" | 75 | + port + "/live/" |
| 73 | + _param.siteId | 76 | + _param.siteId |
| @@ -82,21 +85,40 @@ class VideoChat extends Ape { | @@ -82,21 +85,40 @@ class VideoChat extends Ape { | ||
| 82 | //获取推流地址 | 85 | //获取推流地址 |
| 83 | getPublishVideoPath(_param) { | 86 | getPublishVideoPath(_param) { |
| 84 | loger.log('getPublishVideoPath'); | 87 | loger.log('getPublishVideoPath'); |
| 85 | - //if(_param==null){ | ||
| 86 | - // loger.warn('getPublishVideoPath,参数错误',_param); | ||
| 87 | - // this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); | ||
| 88 | - // return {"code":1,"data":"getPublishVideoPath,参数错误"};; | ||
| 89 | - //} | 88 | + |
| 90 | //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启 | 89 | //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启 |
| 91 | let freeChannel = this.getFreeVideoChannel(); | 90 | let freeChannel = this.getFreeVideoChannel(); |
| 92 | if (freeChannel == 0) { | 91 | if (freeChannel == 0) { |
| 93 | return {"code": 1, "data": "不能再打开更多的设备"}; | 92 | return {"code": 1, "data": "不能再打开更多的设备"}; |
| 94 | } | 93 | } |
| 95 | 94 | ||
| 96 | - let port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "" : ":" + GlobalConfig.MSServerPort; | 95 | + //默认方式推流 |
| 96 | + let pubType="live"; | ||
| 97 | + //flash推流 | ||
| 98 | + if(_param&&_param.type=="flash"){ | ||
| 99 | + pubType ="flash"; | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + //端口,有端口就显示 ":xxx",没有端口就是"" | ||
| 103 | + let port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort; | ||
| 104 | + //时间戳 | ||
| 97 | let timestamp = EngineUtils.creatTimestamp(); | 105 | let timestamp = EngineUtils.creatTimestamp(); |
| 98 | - let publishUrl = "rtmp://" + GlobalConfig.MSServerIP + port + "/flash/" +GlobalConfig.siteId+"_"+ GlobalConfig.classId + "_"+GlobalConfig.userId+"_" + freeChannel + "_" + timestamp; | ||
| 99 | - return {"code": 0, "data": {"siteId":GlobalConfig.siteId,"classId":GlobalConfig.classId,"userId":GlobalConfig.userId,"channelId": freeChannel, "timestamp": timestamp, "publishUrl": publishUrl}}; | 106 | + |
| 107 | + //生成推流地址和推流数据(同步数据的时候用) | ||
| 108 | + let publishUrl = "rtmp://" + GlobalConfig.MSServerIP | ||
| 109 | + + port + "/"+pubType+"/" +GlobalConfig.siteId+"_" | ||
| 110 | + + GlobalConfig.classId + "_"+GlobalConfig.userId | ||
| 111 | + +"_" + freeChannel + "_" + timestamp; | ||
| 112 | + return {"code": 0, | ||
| 113 | + "data": | ||
| 114 | + { "siteId":GlobalConfig.siteId, | ||
| 115 | + "classId":GlobalConfig.classId, | ||
| 116 | + "userId":GlobalConfig.userId, | ||
| 117 | + "channelId": freeChannel, | ||
| 118 | + "timestamp": timestamp, | ||
| 119 | + "publishUrl": publishUrl | ||
| 120 | + } | ||
| 121 | + }; | ||
| 100 | } | 122 | } |
| 101 | 123 | ||
| 102 | //推流 | 124 | //推流 |
| @@ -148,7 +170,12 @@ class VideoChat extends Ape { | @@ -148,7 +170,12 @@ class VideoChat extends Ape { | ||
| 148 | stopPublishVideo(_param) { | 170 | stopPublishVideo(_param) { |
| 149 | loger.log('stopPublishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels); | 171 | loger.log('stopPublishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels); |
| 150 | //_param如果为空,那么默认就是当前自己的nodeId,否则用_param | 172 | //_param如果为空,那么默认就是当前自己的nodeId,否则用_param |
| 151 | - let nodeId=_param||GlobalConfig.nodeId; | 173 | + let nodeId; |
| 174 | + if(_param&&parseInt(_param.nodeId)>=0){ | ||
| 175 | + nodeId=parseInt(_param.nodeId); | ||
| 176 | + }else { | ||
| 177 | + nodeId=GlobalConfig.nodeId; | ||
| 178 | + } | ||
| 152 | 179 | ||
| 153 | let openingChannel = this.getOpeningVideoChannel(nodeId); | 180 | let openingChannel = this.getOpeningVideoChannel(nodeId); |
| 154 | if (openingChannel == 0) { | 181 | if (openingChannel == 0) { |
| @@ -351,11 +378,12 @@ class VideoChat extends Ape { | @@ -351,11 +378,12 @@ class VideoChat extends Ape { | ||
| 351 | packPduModel.channelId = _itemIdx; | 378 | packPduModel.channelId = _itemIdx; |
| 352 | packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId; | 379 | packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId; |
| 353 | packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId); | 380 | packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId); |
| 381 | + packPduModel.userId =_param.userId||"0"; | ||
| 354 | packPduModel.mediaType =_param.mediaType|| ApeConsts.MEDIA_TYPE_VIDEO; | 382 | packPduModel.mediaType =_param.mediaType|| ApeConsts.MEDIA_TYPE_VIDEO; |
| 355 | packPduModel.timestamp =_param.timestamp||EngineUtils.creatTimestamp(); | 383 | packPduModel.timestamp =_param.timestamp||EngineUtils.creatTimestamp(); |
| 356 | packPduModel.fromNodeId = GlobalConfig.nodeId; | 384 | packPduModel.fromNodeId = GlobalConfig.nodeId; |
| 357 | packPduModel.toNodeId = 0; | 385 | packPduModel.toNodeId = 0; |
| 358 | - console.log(packPduModel); | 386 | + console.log("packPdu",packPduModel); |
| 359 | return packPduModel; | 387 | return packPduModel; |
| 360 | } | 388 | } |
| 361 | 389 |
| @@ -768,6 +768,8 @@ message RCVideoChannelInfoPdu { | @@ -768,6 +768,8 @@ message RCVideoChannelInfoPdu { | ||
| 768 | optional uint32 to_node_id = 5;//接收者的id,(如果是0,所有人都接收) | 768 | optional uint32 to_node_id = 5;//接收者的id,(如果是0,所有人都接收) |
| 769 | optional uint32 media_type = 6;//媒体类型:视频(包含音频)或音频 | 769 | optional uint32 media_type = 6;//媒体类型:视频(包含音频)或音频 |
| 770 | optional uint32 class_id = 7;//课堂号 | 770 | optional uint32 class_id = 7;//课堂号 |
| 771 | + optional string site_id = 8;//站点号 | ||
| 772 | + optional string user_id = 9;//用户的userId | ||
| 771 | } | 773 | } |
| 772 | 774 | ||
| 773 | message RCVideoChannelInfoRecordPdu { | 775 | message RCVideoChannelInfoRecordPdu { |
-
请 注册 或 登录 后发表评论