正在显示
8 个修改的文件
包含
160 行增加
和
60 行删除
| @@ -549,10 +549,12 @@ export default class MessageEntrance extends Emiter { | @@ -549,10 +549,12 @@ export default class MessageEntrance extends Emiter { | ||
| 549 | 549 | ||
| 550 | //保存会态信息成功 | 550 | //保存会态信息成功 |
| 551 | _sassSaveClassStatusInfoSuccessHandler(_data) { | 551 | _sassSaveClassStatusInfoSuccessHandler(_data) { |
| 552 | - loger.log('保存会议状态信息成功.', _data); | 552 | + loger.log('保存会议状态信息成功.'); |
| 553 | + console.log(_data); | ||
| 553 | } | 554 | } |
| 554 | _sassSaveClassRecordInfoSuccessHandler(_data){ | 555 | _sassSaveClassRecordInfoSuccessHandler(_data){ |
| 555 | - loger.log('保存会议录制信息成功.', _data); | 556 | + loger.log('保存会议录制信息成功.'); |
| 557 | + console.log(_data); | ||
| 556 | } | 558 | } |
| 557 | 559 | ||
| 558 | //Sass校验流程结束之后,开始加入MCU | 560 | //Sass校验流程结束之后,开始加入MCU |
| @@ -42,7 +42,11 @@ class EverSocket extends Emiter { | @@ -42,7 +42,11 @@ class EverSocket extends Emiter { | ||
| 42 | 42 | ||
| 43 | send(data) { | 43 | send(data) { |
| 44 | if (this._connected) { | 44 | if (this._connected) { |
| 45 | - loger.log('SEND MESSAGE---->'); | 45 | + if(data){ |
| 46 | + loger.log('SEND MESSAGE,byteLength---->',data.byteLength); | ||
| 47 | + }else { | ||
| 48 | + loger.log('SEND MESSAGE---->'); | ||
| 49 | + } | ||
| 46 | this.websocket.send(data); | 50 | this.websocket.send(data); |
| 47 | } else { | 51 | } else { |
| 48 | loger.warn('WebSocket未建立连接.消息忽略'); | 52 | loger.warn('WebSocket未建立连接.消息忽略'); |
| @@ -34,10 +34,14 @@ MessageTypes.CLASS_RECORD_START='class.record.start';//开始录制 | @@ -34,10 +34,14 @@ MessageTypes.CLASS_RECORD_START='class.record.start';//开始录制 | ||
| 34 | MessageTypes.CHAT_RECEIVE = 'chat.receive'; | 34 | MessageTypes.CHAT_RECEIVE = 'chat.receive'; |
| 35 | 35 | ||
| 36 | //视频模块事件定义 | 36 | //视频模块事件定义 |
| 37 | +MessageTypes.VIDEO_PLAY = 'video.play';//播放视频 | ||
| 38 | +MessageTypes.VIDEO_STOP = 'video.stop';//停止视频 | ||
| 37 | MessageTypes.VIDEO_UPDATE = 'video.update'; | 39 | MessageTypes.VIDEO_UPDATE = 'video.update'; |
| 38 | MessageTypes.VIDEO_BROADCAST= 'video.broadcast'; | 40 | MessageTypes.VIDEO_BROADCAST= 'video.broadcast'; |
| 39 | 41 | ||
| 40 | //音频模块事件定义 | 42 | //音频模块事件定义 |
| 43 | +MessageTypes.AUDIO_PLAY = 'audio.play';//播放 | ||
| 44 | +MessageTypes.AUDIO_STOP = 'audio.stop';//停止 | ||
| 41 | MessageTypes.AUDIO_UPDATE = 'audio.update'; | 45 | MessageTypes.AUDIO_UPDATE = 'audio.update'; |
| 42 | MessageTypes.AUDIO_BROADCAST= 'audio.broadcast'; | 46 | MessageTypes.AUDIO_BROADCAST= 'audio.broadcast'; |
| 43 | 47 |
| @@ -57,15 +57,21 @@ class AudioApe extends Ape { | @@ -57,15 +57,21 @@ class AudioApe extends Ape { | ||
| 57 | return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; | 57 | return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | - if (_param == null||_param.channelId == null|| | ||
| 61 | - _param.classId == null||_param.userId == null|| | ||
| 62 | - _param.siteId == null|| _param.timestamp==null) | 60 | + if (_param == null||_param.publishUrl == null) |
| 63 | { | 61 | { |
| 64 | loger.warn('publishAudio,参数错误', _param); | 62 | loger.warn('publishAudio,参数错误', _param); |
| 65 | this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); | 63 | this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); |
| 66 | return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"}; | 64 | return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"}; |
| 67 | } | 65 | } |
| 68 | 66 | ||
| 67 | + //根据推流的地址获取对应的频道信息 | ||
| 68 | + let needPublishChannelInfo=this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl); | ||
| 69 | + if(needPublishChannelInfo==null){ | ||
| 70 | + loger.warn('publishVideo,推流数据已经无效', _param); | ||
| 71 | + return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"}; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + | ||
| 69 | //同一个nodeId只允许推一个流,如果已经推了就不能再推 | 75 | //同一个nodeId只允许推一个流,如果已经推了就不能再推 |
| 70 | if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){ | 76 | if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){ |
| 71 | loger.warn("publishAudio,已经存在一个流,不能再推"); | 77 | loger.warn("publishAudio,已经存在一个流,不能再推"); |
| @@ -80,18 +86,19 @@ class AudioApe extends Ape { | @@ -80,18 +86,19 @@ class AudioApe extends Ape { | ||
| 80 | } | 86 | } |
| 81 | 87 | ||
| 82 | //判断当前的频道是否已经占用 | 88 | //判断当前的频道是否已经占用 |
| 83 | - if(this.mediaModule.checkChannelIsOpening(_param.channelId)){ | ||
| 84 | - loger.warn(_param.channelId,"频道已经被占用"); | 89 | + if(this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)){ |
| 90 | + loger.warn(needPublishChannelInfo.channelId,"频道已经被占用"); | ||
| 85 | return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"}; | 91 | return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"}; |
| 86 | } | 92 | } |
| 87 | 93 | ||
| 88 | let channelInfo={}; | 94 | let channelInfo={}; |
| 89 | channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING; | 95 | channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING; |
| 90 | channelInfo.fromNodeId=GlobalConfig.nodeId; | 96 | channelInfo.fromNodeId=GlobalConfig.nodeId; |
| 91 | - channelInfo.channelId=_param.channelId;//freeChannel | ||
| 92 | - channelInfo.timestamp=_param.timestamp;//EngineUtils.creatTimestamp(); | ||
| 93 | - channelInfo.classId=_param.classId;//GlobalConfig.classId; | ||
| 94 | - channelInfo.siteId=_param.siteId;//GlobalConfig.siteId; | 97 | + channelInfo.channelId=needPublishChannelInfo.channelId;//freeChannel |
| 98 | + channelInfo.streamId=needPublishChannelInfo.streamId;//按规则拼接的流名称 | ||
| 99 | + channelInfo.timestamp=needPublishChannelInfo.timestamp;//EngineUtils.creatTimestamp(); | ||
| 100 | + channelInfo.classId=GlobalConfig.classId;//GlobalConfig.classId; | ||
| 101 | + channelInfo.siteId=GlobalConfig.siteId;//GlobalConfig.siteId; | ||
| 95 | channelInfo.toNodeId=0; | 102 | channelInfo.toNodeId=0; |
| 96 | channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO; | 103 | channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO; |
| 97 | this.sendTableUpdateHandler(channelInfo); | 104 | this.sendTableUpdateHandler(channelInfo); |
| @@ -105,9 +112,9 @@ class AudioApe extends Ape { | @@ -105,9 +112,9 @@ class AudioApe extends Ape { | ||
| 105 | loger.warn(GlobalConfig.getCurrentStatus()); | 112 | loger.warn(GlobalConfig.getCurrentStatus()); |
| 106 | return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; | 113 | return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; |
| 107 | } | 114 | } |
| 108 | - //_param如果为空,那么默认就是当前自己的nodeId,否则用_param | 115 | + //_param如果为空或者0,那么默认就是当前自己的nodeId,否则用_param |
| 109 | let nodeId; | 116 | let nodeId; |
| 110 | - if(_param&&parseInt(_param.nodeId)>=0){ | 117 | + if(_param&&parseInt(_param.nodeId)>0){ |
| 111 | nodeId=parseInt(_param.nodeId); | 118 | nodeId=parseInt(_param.nodeId); |
| 112 | }else { | 119 | }else { |
| 113 | nodeId=GlobalConfig.nodeId; | 120 | nodeId=GlobalConfig.nodeId; |
| @@ -115,8 +122,8 @@ class AudioApe extends Ape { | @@ -115,8 +122,8 @@ class AudioApe extends Ape { | ||
| 115 | 122 | ||
| 116 | let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); | 123 | let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); |
| 117 | if (openingChannel == 0) { | 124 | if (openingChannel == 0) { |
| 118 | - loger.warn(nodeId,"stopPublishAudio,没有占用channel,不需要关闭"); | ||
| 119 | - return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel,不需要关闭"}; | 125 | + loger.warn(nodeId,"没有占用channel不需要处理"); |
| 126 | + return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"}; | ||
| 120 | } | 127 | } |
| 121 | 128 | ||
| 122 | let channelInfo={}; | 129 | let channelInfo={}; |
| @@ -243,11 +250,47 @@ class AudioApe extends Ape { | @@ -243,11 +250,47 @@ class AudioApe extends Ape { | ||
| 243 | 250 | ||
| 244 | tableUpdateHandler(owner, itemIdx, itemData) { | 251 | tableUpdateHandler(owner, itemIdx, itemData) { |
| 245 | // debugger; | 252 | // debugger; |
| 246 | - let updateChannelInfo = this.unPackPdu(owner, itemIdx, itemData); | ||
| 247 | - | ||
| 248 | - this.mediaModule.mediaChannels[itemIdx] = updateChannelInfo; | 253 | + /* let updateChannelInfo = this.unPackPdu(owner, itemIdx, itemData); |
| 254 | + | ||
| 255 | + this.mediaModule.mediaChannels[itemIdx] = updateChannelInfo; | ||
| 256 | + | ||
| 257 | + this._emit(MessageTypes.AUDIO_UPDATE, updateChannelInfo);*/ | ||
| 258 | + let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData); | ||
| 259 | + this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo; | ||
| 260 | + | ||
| 261 | + if(unpackChannelInfo&&unpackChannelInfo.fromNodeId!=GlobalConfig.nodeId){ | ||
| 262 | + let receiveChannelInfo={}; | ||
| 263 | + receiveChannelInfo.mediaId=unpackChannelInfo.channelId; | ||
| 264 | + | ||
| 265 | + //消息不是自己同步的,需要处理 | ||
| 266 | + if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){ | ||
| 267 | + //正在推流 | ||
| 268 | + receiveChannelInfo.m3u8Url=""; | ||
| 269 | + receiveChannelInfo.rtmpUrl=""; | ||
| 270 | + let m3u8Stream=this.mediaModule.getMediaPlayPath({"type":"m3u8","streamId": unpackChannelInfo.streamId}); | ||
| 271 | + let rtmpStream=this.mediaModule.getMediaPlayPath({"type":"rtmp","streamId": unpackChannelInfo.streamId}); | ||
| 272 | + | ||
| 273 | + if(m3u8Stream.code==0){ | ||
| 274 | + receiveChannelInfo.m3u8Url=m3u8Stream.playUrl; | ||
| 275 | + } | ||
| 276 | + if(rtmpStream.code==0){ | ||
| 277 | + receiveChannelInfo.rtmpUrl=rtmpStream.playUrl; | ||
| 278 | + } | ||
| 279 | + loger.log("AUDIO_PLAY"); | ||
| 280 | + console.log(receiveChannelInfo); | ||
| 281 | + //广播播放视频的消息 | ||
| 282 | + this._emit(MessageTypes.AUDIO_PLAY, receiveChannelInfo); | ||
| 283 | + }else { | ||
| 284 | + loger.log("AUDIO_STOP"); | ||
| 285 | + console.log(receiveChannelInfo); | ||
| 286 | + //流已经停止 | ||
| 287 | + this._emit(MessageTypes.AUDIO_STOP, receiveChannelInfo); | ||
| 288 | + } | ||
| 289 | + }else { | ||
| 290 | + loger.warn("消息是自己发送的或者是消息无效,不需要处理,消息内容如下:"); | ||
| 291 | + console.log(unpackChannelInfo); | ||
| 249 | 292 | ||
| 250 | - this._emit(MessageTypes.AUDIO_UPDATE, updateChannelInfo); | 293 | + } |
| 251 | } | 294 | } |
| 252 | 295 | ||
| 253 | ///////数据的封包和解包///////////////////////////////////////// | 296 | ///////数据的封包和解包///////////////////////////////////////// |
| @@ -263,6 +306,7 @@ class AudioApe extends Ape { | @@ -263,6 +306,7 @@ class AudioApe extends Ape { | ||
| 263 | let packPduModel = new pdu['RCAudioChannelInfoPdu']; | 306 | let packPduModel = new pdu['RCAudioChannelInfoPdu']; |
| 264 | packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED; | 307 | packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED; |
| 265 | packPduModel.channelId = _itemIdx; | 308 | packPduModel.channelId = _itemIdx; |
| 309 | + packPduModel.streamId = _param.streamId||""; | ||
| 266 | packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId; | 310 | packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId; |
| 267 | packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId); | 311 | packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId); |
| 268 | packPduModel.userId =_param.userId||"0"; | 312 | packPduModel.userId =_param.userId||"0"; |
| @@ -282,7 +326,7 @@ class AudioApe extends Ape { | @@ -282,7 +326,7 @@ class AudioApe extends Ape { | ||
| 282 | } | 326 | } |
| 283 | try { | 327 | try { |
| 284 | let packChannelInfo = pdu['RCAudioChannelInfoPdu'].decode(itemData); | 328 | let packChannelInfo = pdu['RCAudioChannelInfoPdu'].decode(itemData); |
| 285 | - loger.log("unPackPdu",packChannelInfo); | 329 | + console.log(packChannelInfo); |
| 286 | return packChannelInfo; | 330 | return packChannelInfo; |
| 287 | } catch (err) { | 331 | } catch (err) { |
| 288 | loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message); | 332 | loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message); |
| @@ -171,7 +171,8 @@ class DocApe extends Ape { | @@ -171,7 +171,8 @@ class DocApe extends Ape { | ||
| 171 | if(lastIndex>0){ | 171 | if(lastIndex>0){ |
| 172 | let newPath=fullPath.substr(0,lastIndex); | 172 | let newPath=fullPath.substr(0,lastIndex); |
| 173 | let pathArr=[]; | 173 | let pathArr=[]; |
| 174 | - for(let i=1;i<_param.pageNum;i++){ | 174 | + //页数从1开始 |
| 175 | + for(let i=1;i<=_param.pageNum;i++){ | ||
| 175 | pathArr.push(newPath+"/"+i+"."+fileType); | 176 | pathArr.push(newPath+"/"+i+"."+fileType); |
| 176 | } | 177 | } |
| 177 | return pathArr; | 178 | return pathArr; |
| @@ -210,6 +211,8 @@ class DocApe extends Ape { | @@ -210,6 +211,8 @@ class DocApe extends Ape { | ||
| 210 | 211 | ||
| 211 | //切换文档 | 212 | //切换文档 |
| 212 | documentSwitchDoc(paramInfo){ | 213 | documentSwitchDoc(paramInfo){ |
| 214 | + loger.log('切换文档,documentSwitchDoc'); | ||
| 215 | + console.log(paramInfo); | ||
| 213 | if(paramInfo==null||paramInfo.itemIdx==null){ | 216 | if(paramInfo==null||paramInfo.itemIdx==null){ |
| 214 | loger.warn('documentSwitch失败,参数错误',paramInfo); | 217 | loger.warn('documentSwitch失败,参数错误',paramInfo); |
| 215 | this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); | 218 | this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); |
| @@ -257,6 +260,8 @@ class DocApe extends Ape { | @@ -257,6 +260,8 @@ class DocApe extends Ape { | ||
| 257 | 260 | ||
| 258 | //文档翻页 | 261 | //文档翻页 |
| 259 | documentSwitchPage(paramInfo){ | 262 | documentSwitchPage(paramInfo){ |
| 263 | + loger.log('文档翻页,documentSwitchPage'); | ||
| 264 | + console.log(paramInfo); | ||
| 260 | //console.log(this.docList); | 265 | //console.log(this.docList); |
| 261 | //获取已经存在的数据 | 266 | //获取已经存在的数据 |
| 262 | let docDataModel= this.docList[paramInfo.itemIdx]; | 267 | let docDataModel= this.docList[paramInfo.itemIdx]; |
| @@ -12,6 +12,7 @@ let loger = Loger.getLoger('MediaModule'); | @@ -12,6 +12,7 @@ let loger = Loger.getLoger('MediaModule'); | ||
| 12 | 12 | ||
| 13 | class MediaModule { | 13 | class MediaModule { |
| 14 | constructor() { | 14 | constructor() { |
| 15 | + this.needPublishMediaChannel={};//记录准备推流的频道信息 | ||
| 15 | this.mediaChannels = {}; | 16 | this.mediaChannels = {}; |
| 16 | this.maxMediaChannel=0; | 17 | this.maxMediaChannel=0; |
| 17 | this.MEDIA_OBJ_TABLE_ID=0; | 18 | this.MEDIA_OBJ_TABLE_ID=0; |
| @@ -20,9 +21,7 @@ class MediaModule { | @@ -20,9 +21,7 @@ class MediaModule { | ||
| 20 | //获取播流地址 | 21 | //获取播流地址 |
| 21 | getMediaPlayPath(_param) { | 22 | getMediaPlayPath(_param) { |
| 22 | loger.log('getMediaPlayPath'); | 23 | loger.log('getMediaPlayPath'); |
| 23 | - if (_param == null||_param.siteId == null|| | ||
| 24 | - _param.classId == null||_param.userId == null|| | ||
| 25 | - _param.channelId == null|| _param.timestamp==null) | 24 | + if (_param == null||_param.streamId == null) |
| 26 | { | 25 | { |
| 27 | loger.warn('getMediaPlayPath,参数错误', _param); | 26 | loger.warn('getMediaPlayPath,参数错误', _param); |
| 28 | //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); | 27 | //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); |
| @@ -37,21 +36,13 @@ class MediaModule { | @@ -37,21 +36,13 @@ class MediaModule { | ||
| 37 | port = (GlobalConfig.RSServerPort == "" || GlobalConfig.RSServerPort == null) ? "":":" + GlobalConfig.RSServerPort; | 36 | port = (GlobalConfig.RSServerPort == "" || GlobalConfig.RSServerPort == null) ? "":":" + GlobalConfig.RSServerPort; |
| 38 | path = "http://" + GlobalConfig.RSServerIP | 37 | path = "http://" + GlobalConfig.RSServerIP |
| 39 | + port + "/live/" | 38 | + port + "/live/" |
| 40 | - + _param.siteId | ||
| 41 | - + "_" + _param.classId | ||
| 42 | - + "_" + _param.userId | ||
| 43 | - + "_" + _param.channelId | ||
| 44 | - + "_" + _param.timestamp | 39 | + + _param.streamId |
| 45 | + "/index.m3u8"; | 40 | + "/index.m3u8"; |
| 46 | } else { | 41 | } else { |
| 47 | port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort; | 42 | port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort; |
| 48 | path = "rtmp://" + GlobalConfig.MSServerIP | 43 | path = "rtmp://" + GlobalConfig.MSServerIP |
| 49 | + port + "/live/" | 44 | + port + "/live/" |
| 50 | - + _param.siteId | ||
| 51 | - + "_" + _param.classId | ||
| 52 | - + "_" + _param.userId | ||
| 53 | - + "_" + _param.channelId | ||
| 54 | - + "_" + _param.timestamp; | 45 | + + _param.streamId; |
| 55 | } | 46 | } |
| 56 | return {"code": ApeConsts.RETURN_SUCCESS, "data": "","playUrl": path}; | 47 | return {"code": ApeConsts.RETURN_SUCCESS, "data": "","playUrl": path}; |
| 57 | } | 48 | } |
| @@ -77,18 +68,21 @@ class MediaModule { | @@ -77,18 +68,21 @@ class MediaModule { | ||
| 77 | //时间戳 | 68 | //时间戳 |
| 78 | let timestamp = EngineUtils.creatTimestamp(); | 69 | let timestamp = EngineUtils.creatTimestamp(); |
| 79 | 70 | ||
| 80 | - //生成推流地址和推流数据(同步数据的时候用) | ||
| 81 | - let publishUrl = "rtmp://" + GlobalConfig.MSServerIP | ||
| 82 | - + port + "/"+pubType+"/" +GlobalConfig.siteId+"_" | 71 | + let streamId=GlobalConfig.siteId+"_" |
| 83 | + GlobalConfig.classId + "_"+GlobalConfig.userId | 72 | + GlobalConfig.classId + "_"+GlobalConfig.userId |
| 84 | +"_" + freeChannel + "_" + timestamp; | 73 | +"_" + freeChannel + "_" + timestamp; |
| 74 | + | ||
| 75 | + //生成推流地址和推流数据(同步数据的时候用) | ||
| 76 | + let publishUrl = "rtmp://" + GlobalConfig.MSServerIP | ||
| 77 | + + port + "/"+pubType+"/" +streamId; | ||
| 78 | + | ||
| 79 | + this.needPublishMediaChannel[publishUrl]={ | ||
| 80 | + "channelId":freeChannel, | ||
| 81 | + "publishUrl":publishUrl, | ||
| 82 | + "streamId":streamId | ||
| 83 | + }; | ||
| 85 | return {"code": ApeConsts.RETURN_SUCCESS, | 84 | return {"code": ApeConsts.RETURN_SUCCESS, |
| 86 | "data":"", | 85 | "data":"", |
| 87 | - "siteId":GlobalConfig.siteId, | ||
| 88 | - "classId":GlobalConfig.classId, | ||
| 89 | - "userId":GlobalConfig.userId, | ||
| 90 | - "channelId": freeChannel, | ||
| 91 | - "timestamp": timestamp, | ||
| 92 | "publishUrl": publishUrl | 86 | "publishUrl": publishUrl |
| 93 | }; | 87 | }; |
| 94 | } | 88 | } |
| @@ -111,6 +105,11 @@ class MediaModule { | @@ -111,6 +105,11 @@ class MediaModule { | ||
| 111 | return 0;//没有空闲的 | 105 | return 0;//没有空闲的 |
| 112 | } | 106 | } |
| 113 | 107 | ||
| 108 | + //获取准备推流的频道信息 | ||
| 109 | + getNeedPublishMediaChannel(_publishUrl){ | ||
| 110 | + return this.needPublishMediaChannel[_publishUrl]; | ||
| 111 | + } | ||
| 112 | + | ||
| 114 | //获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId | 113 | //获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId |
| 115 | getOpeningMediaChannel(_nodeId){ | 114 | getOpeningMediaChannel(_nodeId){ |
| 116 | if(_nodeId==null||_nodeId==0){ | 115 | if(_nodeId==null||_nodeId==0){ |
| @@ -58,16 +58,19 @@ class VideoApe extends Ape { | @@ -58,16 +58,19 @@ class VideoApe extends Ape { | ||
| 58 | return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; | 58 | return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | - if (_param == null||_param.channelId == null|| | ||
| 62 | - _param.classId == null||_param.userId == null|| | ||
| 63 | - _param.siteId == null|| _param.timestamp==null) | 61 | + if (_param == null||_param.publishUrl == null) |
| 64 | { | 62 | { |
| 65 | loger.warn('publishVideo,参数错误', _param); | 63 | loger.warn('publishVideo,参数错误', _param); |
| 66 | this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); | 64 | this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); |
| 67 | return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"}; | 65 | return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"}; |
| 68 | } | 66 | } |
| 69 | 67 | ||
| 70 | - loger.log('publishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels); | 68 | + //根据推流的地址获取对应的频道信息 |
| 69 | + let needPublishChannelInfo=this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl); | ||
| 70 | + if(needPublishChannelInfo==null){ | ||
| 71 | + loger.warn('publishVideo,推流数据已经无效', _param); | ||
| 72 | + return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"}; | ||
| 73 | + } | ||
| 71 | 74 | ||
| 72 | //同一个nodeId只允许推一个流,如果已经推了就不能再推 | 75 | //同一个nodeId只允许推一个流,如果已经推了就不能再推 |
| 73 | if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){ | 76 | if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){ |
| @@ -82,19 +85,20 @@ class VideoApe extends Ape { | @@ -82,19 +85,20 @@ class VideoApe extends Ape { | ||
| 82 | return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"}; | 85 | return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"}; |
| 83 | } | 86 | } |
| 84 | 87 | ||
| 88 | + | ||
| 85 | //判断当前的频道是否已经占用 | 89 | //判断当前的频道是否已经占用 |
| 86 | - if(this.mediaModule.checkChannelIsOpening(_param.channelId)){ | ||
| 87 | - loger.warn(_param.channelId,"频道已经被占用"); | 90 | + if(this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)){ |
| 91 | + loger.warn(needPublishChannelInfo.channelId,"频道已经被占用"); | ||
| 88 | return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"}; | 92 | return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"}; |
| 89 | } | 93 | } |
| 90 | 94 | ||
| 91 | let channelInfo={}; | 95 | let channelInfo={}; |
| 92 | channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING; | 96 | channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING; |
| 93 | channelInfo.fromNodeId=GlobalConfig.nodeId; | 97 | channelInfo.fromNodeId=GlobalConfig.nodeId; |
| 94 | - channelInfo.channelId=_param.channelId;//freeChannel | ||
| 95 | - channelInfo.timestamp=_param.timestamp;//EngineUtils.creatTimestamp(); | ||
| 96 | - channelInfo.classId=_param.classId;//GlobalConfig.classId; | ||
| 97 | - channelInfo.siteId=_param.siteId;//GlobalConfig.siteId; | 98 | + channelInfo.channelId=needPublishChannelInfo.channelId; |
| 99 | + channelInfo.streamId=needPublishChannelInfo.streamId;//按规则拼接的流名称 | ||
| 100 | + channelInfo.classId=GlobalConfig.classId; | ||
| 101 | + channelInfo.siteId=GlobalConfig.siteId; | ||
| 98 | channelInfo.toNodeId=0; | 102 | channelInfo.toNodeId=0; |
| 99 | channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO; | 103 | channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO; |
| 100 | this.sendTableUpdateHandler(channelInfo); | 104 | this.sendTableUpdateHandler(channelInfo); |
| @@ -111,7 +115,7 @@ class VideoApe extends Ape { | @@ -111,7 +115,7 @@ class VideoApe extends Ape { | ||
| 111 | loger.log('stopPublishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels); | 115 | loger.log('stopPublishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels); |
| 112 | //_param如果为空,那么默认就是当前自己的nodeId,否则用_param | 116 | //_param如果为空,那么默认就是当前自己的nodeId,否则用_param |
| 113 | let nodeId; | 117 | let nodeId; |
| 114 | - if(_param&&parseInt(_param.nodeId)>=0){ | 118 | + if(_param&&parseInt(_param.nodeId)>0){ |
| 115 | nodeId=parseInt(_param.nodeId); | 119 | nodeId=parseInt(_param.nodeId); |
| 116 | }else { | 120 | }else { |
| 117 | nodeId=GlobalConfig.nodeId; | 121 | nodeId=GlobalConfig.nodeId; |
| @@ -119,8 +123,8 @@ class VideoApe extends Ape { | @@ -119,8 +123,8 @@ class VideoApe extends Ape { | ||
| 119 | 123 | ||
| 120 | let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); | 124 | let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); |
| 121 | if (openingChannel == 0) { | 125 | if (openingChannel == 0) { |
| 122 | - loger.warn(nodeId,"stopPublishVideo,没有占用channel,不需要关闭"); | ||
| 123 | - return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel,不需要关闭"}; | 126 | + loger.warn(nodeId,"没有占用channel不需要处理"); |
| 127 | + return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"}; | ||
| 124 | } | 128 | } |
| 125 | 129 | ||
| 126 | let channelInfo={}; | 130 | let channelInfo={}; |
| @@ -265,9 +269,44 @@ class VideoApe extends Ape { | @@ -265,9 +269,44 @@ class VideoApe extends Ape { | ||
| 265 | 269 | ||
| 266 | tableUpdateHandler(owner, itemIdx, itemData) { | 270 | tableUpdateHandler(owner, itemIdx, itemData) { |
| 267 | // debugger; | 271 | // debugger; |
| 268 | - let videoChannelInfo = this.unPackPdu(owner, itemIdx, itemData); | ||
| 269 | - this.mediaModule.mediaChannels[itemIdx] = videoChannelInfo; | ||
| 270 | - this._emit(MessageTypes.VIDEO_UPDATE, videoChannelInfo); | 272 | + let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData); |
| 273 | + this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo; | ||
| 274 | + | ||
| 275 | + if(unpackChannelInfo&&unpackChannelInfo.fromNodeId!=GlobalConfig.nodeId){ | ||
| 276 | + let receiveChannelInfo={}; | ||
| 277 | + receiveChannelInfo.mediaId=unpackChannelInfo.channelId; | ||
| 278 | + | ||
| 279 | + //消息不是自己同步的,需要处理 | ||
| 280 | + if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){ | ||
| 281 | + //正在推流 | ||
| 282 | + receiveChannelInfo.m3u8Url=""; | ||
| 283 | + receiveChannelInfo.rtmpUrl=""; | ||
| 284 | + let m3u8Stream=this.mediaModule.getMediaPlayPath({"type":"m3u8","streamId": unpackChannelInfo.streamId}); | ||
| 285 | + let rtmpStream=this.mediaModule.getMediaPlayPath({"type":"rtmp","streamId": unpackChannelInfo.streamId}); | ||
| 286 | + | ||
| 287 | + if(m3u8Stream.code==0){ | ||
| 288 | + receiveChannelInfo.m3u8Url=m3u8Stream.playUrl; | ||
| 289 | + } | ||
| 290 | + if(rtmpStream.code==0){ | ||
| 291 | + receiveChannelInfo.rtmpUrl=rtmpStream.playUrl; | ||
| 292 | + } | ||
| 293 | + loger.log("VIDEO_PLAY"); | ||
| 294 | + console.log(receiveChannelInfo); | ||
| 295 | + //广播播放视频的消息 | ||
| 296 | + this._emit(MessageTypes.VIDEO_PLAY, receiveChannelInfo); | ||
| 297 | + }else { | ||
| 298 | + loger.log("VIDEO_STOP"); | ||
| 299 | + console.log(receiveChannelInfo); | ||
| 300 | + //流已经停止 | ||
| 301 | + this._emit(MessageTypes.VIDEO_STOP, receiveChannelInfo); | ||
| 302 | + } | ||
| 303 | + }else { | ||
| 304 | + loger.warn("视频消息是自己发送的或者是视频消息无效,不需要处理,消息内容如下:"); | ||
| 305 | + console.log(unpackChannelInfo); | ||
| 306 | + | ||
| 307 | + } | ||
| 308 | + | ||
| 309 | + //this._emit(MessageTypes.VIDEO_UPDATE, videoChannelInfo); | ||
| 271 | } | 310 | } |
| 272 | 311 | ||
| 273 | ///////数据的封包和解包///////////////////////////////////////// | 312 | ///////数据的封包和解包///////////////////////////////////////// |
| @@ -283,6 +322,7 @@ class VideoApe extends Ape { | @@ -283,6 +322,7 @@ class VideoApe extends Ape { | ||
| 283 | let packPduModel = new pdu['RCVideoChannelInfoPdu']; | 322 | let packPduModel = new pdu['RCVideoChannelInfoPdu']; |
| 284 | packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED; | 323 | packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED; |
| 285 | packPduModel.channelId = _itemIdx; | 324 | packPduModel.channelId = _itemIdx; |
| 325 | + packPduModel.streamId = _param.streamId||""; | ||
| 286 | packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId; | 326 | packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId; |
| 287 | packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId); | 327 | packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId); |
| 288 | packPduModel.userId =_param.userId||"0"; | 328 | packPduModel.userId =_param.userId||"0"; |
| @@ -303,7 +343,7 @@ class VideoApe extends Ape { | @@ -303,7 +343,7 @@ class VideoApe extends Ape { | ||
| 303 | try { | 343 | try { |
| 304 | 344 | ||
| 305 | let videoChannelInfo = pdu['RCVideoChannelInfoPdu'].decode(itemData); | 345 | let videoChannelInfo = pdu['RCVideoChannelInfoPdu'].decode(itemData); |
| 306 | - loger.log("unPackPdu",videoChannelInfo); | 346 | + console.log(videoChannelInfo); |
| 307 | return videoChannelInfo; | 347 | return videoChannelInfo; |
| 308 | } catch (err) { | 348 | } catch (err) { |
| 309 | loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message); | 349 | loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message); |
| @@ -776,6 +776,7 @@ message RCAudioChannelInfoPdu { | @@ -776,6 +776,7 @@ message RCAudioChannelInfoPdu { | ||
| 776 | optional uint32 class_id = 7;//课堂号 | 776 | optional uint32 class_id = 7;//课堂号 |
| 777 | optional string site_id = 8;//站点号 | 777 | optional string site_id = 8;//站点号 |
| 778 | optional string user_id = 9;//用户的userId | 778 | optional string user_id = 9;//用户的userId |
| 779 | + optional string stream_id = 10;//流名称 | ||
| 779 | } | 780 | } |
| 780 | 781 | ||
| 781 | message RCVideoChannelInfoPdu { | 782 | message RCVideoChannelInfoPdu { |
| @@ -788,6 +789,7 @@ message RCVideoChannelInfoPdu { | @@ -788,6 +789,7 @@ message RCVideoChannelInfoPdu { | ||
| 788 | optional uint32 class_id = 7;//课堂号 | 789 | optional uint32 class_id = 7;//课堂号 |
| 789 | optional string site_id = 8;//站点号 | 790 | optional string site_id = 8;//站点号 |
| 790 | optional string user_id = 9;//用户的userId | 791 | optional string user_id = 9;//用户的userId |
| 792 | + optional string stream_id = 10;//流名称 | ||
| 791 | } | 793 | } |
| 792 | 794 | ||
| 793 | message RCVideoChannelInfoRecordPdu { | 795 | message RCVideoChannelInfoRecordPdu { |
-
请 注册 或 登录 后发表评论