From a7a75ace3469c14b5f27898b5f3e650699c76fe9 Mon Sep 17 00:00:00 2001
From: liyong <liyong@3mang.com>
Date: Mon, 25 Sep 2017 16:44:08 +0800
Subject: [PATCH] 1.修改FLASH推流拉流的规则-使用腾讯云

---
 doc/nodeJs调用接口数据.txt                |  38 ++++++++++++++++++++++++++++++++++++++
 doc/录制.txt                                  |  19 +++++++++++++++++++
 doc/日志上传.txt                            |  11 +++++++++++
 doc/腾讯云视频录制回调数据结构.txt |  60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/EngineEntrance.js                           |  35 +++++++++++++++++++++++------------
 src/GlobalConfig.js                             |  15 ++++++++++++++-
 src/RecordPlayBackParse.js                      |  77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
 src/SystemConfig.js                             |  24 +-----------------------
 src/apes/MediaModule.js                         | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 9 files changed, 325 insertions(+), 62 deletions(-)
 create mode 100644 doc/nodeJs调用接口数据.txt
 create mode 100644 doc/录制.txt
 create mode 100644 doc/日志上传.txt
 create mode 100644 doc/腾讯云视频录制回调数据结构.txt

diff --git a/doc/nodeJs调用接口数据.txt b/doc/nodeJs调用接口数据.txt
new file mode 100644
index 0000000..ca8e183
--- /dev/null
+++ b/doc/nodeJs调用接口数据.txt
@@ -0,0 +1,38 @@
+1.����¼��(��ʼ����)����һ���ӿ�
+{
+    "appId": "xxxxxxx",
+    "channel": "xxxxx_xxxx",
+    "channelKey": "xxxxxx",
+    "uid": 11111,
+    "userId": "xxx",
+    "userName": "xxx",
+    "userRole": "xxx",
+    "timestamp": "������Ϣ�ĵĿͻ���ʱ���",
+    "recordTimestamp": "��ǰ¼�ƽ��е�ʱ���(�ط�ʱʹ��)"
+}
+
+2.ֹͣ����
+{
+    "appId": "xxxxxxx",
+    "channel": "xxxxx_xxxx",
+    "channelKey": "xxxxxx",
+    "uid": 11111,
+    "userId": "xxx",
+    "userName": "xxx",
+    "userRole": "xxx",
+    "timestamp": "������Ϣ�ĵĿͻ���ʱ���",
+    "recordTimestamp": "��ǰ¼�ƽ��е�ʱ���(�ط�ʱʹ��)"
+}
+
+3.ֹͣ¼��
+{
+    "appId": "xxxxxxx",
+    "channel": "xxxxx_xxxx",
+    "channelKey": "xxxxxx",
+    "uid": 11111,
+    "userId": "xxx",
+    "userName": "xxx",
+    "userRole": "xxx",
+    "timestamp": "������Ϣ�ĵĿͻ���ʱ���",
+    "recordTimestamp": "��ǰ¼�ƽ��е�ʱ���(�ط�ʱʹ��)"
+}
\ No newline at end of file
diff --git a/doc/录制.txt b/doc/录制.txt
new file mode 100644
index 0000000..cb9fcff
--- /dev/null
+++ b/doc/录制.txt
@@ -0,0 +1,19 @@
+1.时间戳 recordTimestamp
+2.开始录制 startRecord
+3.停止录制 stopRecord
+4.录制权限 :
+	A.第一个进入课堂的人开启录制;
+	B.老师或最后一个离开课堂的人停止录制(课堂中没有人的时候10分钟后会停止录制)
+	C.课堂录制时间更新:老师->1个人->多个人且没有老师的时候,按nodeId值最小的人来更新(人员离开或更新的时候需要选择一个人)
+5.课堂进行时间单独更新,和之前的逻辑一致,暂停和未开始的时候不记录;
+6.录制的时间更新只要开启录制之后就更新,10秒一次发送到Saas和MCU同步;
+ 
+7.刚进入的人员的录制时间从Saas获取默认的,MCU同步更新的时候更改为最新时间;
+
+8.计时器:
+  updateTimer(){
+	//1.更新课堂时间,课堂开始上课的情况下更新
+	
+	//2.更新录制时间,开启录制的情况下更新
+  
+  }
\ No newline at end of file
diff --git a/doc/日志上传.txt b/doc/日志上传.txt
new file mode 100644
index 0000000..405dceb
--- /dev/null
+++ b/doc/日志上传.txt
@@ -0,0 +1,11 @@
+type  1��error��   2(warning)  3(info)
+classId
+userId
+nodeId
+
+data:'aaa\nbbb'
+
+
+//sdk�������Ϣ��ʽ�������Ϣ�û��з� \n����
+
+20170729 16:42:00 INFO XX.js receive param name=lipeng
diff --git a/doc/腾讯云视频录制回调数据结构.txt b/doc/腾讯云视频录制回调数据结构.txt
new file mode 100644
index 0000000..9e101f1
--- /dev/null
+++ b/doc/腾讯云视频录制回调数据结构.txt
@@ -0,0 +1,60 @@
+[
+    {
+        "app": "txlivepush.xuedianyun.com ",
+        "appid": 1251457656,
+        "appname": "live",
+        "channel_id": "marketflashtest_1966232762_user_627052_983041_1506308668",
+        "errcode": 0,
+        "errmsg": "Maybe Error return Data no record!",
+        "event_time": 1506308670,
+        "event_type": 1,
+        "idc_id": 34,
+        "node": "125.39.15.21",
+        "sequence": "7037777160241646428",
+        "set_id": 2,
+        "sign": "2eb0dcbd2ac7c3bade3089bb9aa999be",
+        "stream_id": "marketflashtest_1966232762_user_627052_983041_1506308668",
+        "stream_param": "bizid=11220&txSecret=339c4094afe1ae427e7bcd7f1f8d1128&txTime=59c91afc&record=hls&record_interval=5400",
+        "t": 1506309271,
+        "user_ip": "61.135.194.200"
+    },
+    {
+        "appid": 1251457656,
+        "channel_id": "marketflashtest_1966232762_user_627052_983041_1506308688",
+        "duration": 63,
+        "end_time": 1506308756,
+        "event_type": 100,
+        "file_format": "hls",
+        "file_id": "9031868223267109922",
+        "file_size": 1349,
+        "media_start_time": 2931,
+        "record_file_id": "9031868223267109922",
+        "sign": "21f73f7e75f9e75196d1b16a536eaff2",
+        "start_time": 1506308695,
+        "stream_id": "marketflashtest_1966232762_user_627052_983041_1506308688",
+        "stream_param": "bizid=11220&txSecret=2a53a100442dbd5d660ff14edb4af853&txTime=59c91b10&record=hls&record_interval=5400",
+        "t": 1506309357,
+        "task_id": "479501701",
+        "video_id": "5158_e9a44513cce1471790f8b0c50c983ccc",
+        "video_url": "http://1251457656.vod2.myqcloud.com/9425a3e9vodgzp1251457656/6367ba459031868223267109922/playlist.m3u8 "
+    },
+    {
+        "app": "txlivepush.xuedianyun.com",
+        "appid": 1251457656,
+        "appname": "live",
+        "channel_id": "marketflashtest_1966232762_user_627052_983041_1506308688",
+        "errcode": 2,
+        "errmsg": "recv rtmpcloseStream",
+        "event_time": 1506308756,
+        "event_type": 0,
+        "idc_id": 34,
+        "node": "125.39.15.21",
+        "sequence": "7037777160241957731",
+        "set_id": 2,
+        "sign": "21f73f7e75f9e75196d1b16a536eaff2",
+        "stream_id": "marketflashtest_1966232762_user_627052_983041_1506308688",
+        "stream_param": "bizid=11220&txSecret=2a53a100442dbd5d660ff14edb4af853&txTime=59c91b10&record=hls&record_interval=5400",
+        "t": 1506309357,
+        "user_ip": "61.135.194.200"
+    }
+]
\ No newline at end of file
diff --git a/src/EngineEntrance.js b/src/EngineEntrance.js
index 39993f1..9297462 100644
--- a/src/EngineEntrance.js
+++ b/src/EngineEntrance.js
@@ -62,7 +62,7 @@ export default class MessageEntrance extends Emiter {
   constructor() {
     super();
     //sdk 信息
-    GlobalConfig.sdkVersion = "v2.10.7.20170921";
+    GlobalConfig.sdkVersion = "v2.11.13.20170925";
     loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
 
     //设置
@@ -493,7 +493,7 @@ export default class MessageEntrance extends Emiter {
     if(!_data){
       return;
     }
-    if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2||_data.nodeId==GlobalConfig.nodeId){
+    if(GlobalConfig.deviceType==1||GlobalConfig.deviceType==2||GlobalConfig.deviceType==3||_data.nodeId==GlobalConfig.nodeId){
       return;
     }
     if(_webRtc){
@@ -552,6 +552,7 @@ export default class MessageEntrance extends Emiter {
     GlobalConfig.isRecordPlayBack = false; //设置为非录制回放状态
     GlobalConfig.classId = parseInt(_param.classId);
     GlobalConfig.portal = _param.portal||"";
+    GlobalConfig.openFlash=Boolean(_param.openFlash);
     if(GlobalConfig.isHttps==true){
       //https的时候替换所有80端口
       GlobalConfig.portal= GlobalConfig.replacePort(GlobalConfig.portal,":80","");
@@ -1292,10 +1293,12 @@ export default class MessageEntrance extends Emiter {
     //加入课堂成功,广播消息
     this._emit(MessageTypes.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);
 
-    setTimeout(()=>{
-      //加入音视频通话模块,延迟一秒处理,因为视频需要根据用户列表信息来判断放的位置,太早的话用户列表没有数据
-      this._joinChannel({channelId:GlobalConfig.channelId,channelKey:GlobalConfig.channelKey ,uid:GlobalConfig.userUid,info:""+GlobalConfig.userRole});
-    },1000);
+    if(GlobalConfig.appId&&!GlobalConfig.openFlash){
+      setTimeout(()=>{
+        //加入音视频通话模块,延迟一秒处理,因为视频需要根据用户列表信息来判断放的位置,太早的话用户列表没有数据
+        this._joinChannel({channelId:GlobalConfig.channelId,channelKey:GlobalConfig.channelKey ,uid:GlobalConfig.userUid,info:""+GlobalConfig.userRole});
+      },1000);
+    }
   }
 
   //切换MCU ->_param->{reConnect:false} //reConnect(是否立即替换当前的ip并且重新连接)
@@ -1889,14 +1892,22 @@ export default class MessageEntrance extends Emiter {
         loger.warn("开启录制回放流程失败->还未创建模块");
       }
     } else {
-
       //初始化音视频通话sdk
-      this._initWebRtcSdk({
-        appId:GlobalConfig.appId
-      },()=>{
-        //音视频通话SDK初始化完成之后,根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
+      if(GlobalConfig.appId&&!GlobalConfig.openFlash){
+        loger.log("使用webRtc通话模式");
+        //加入webRtc
+        this._initWebRtcSdk({
+          appId:GlobalConfig.appId
+        },()=>{
+          //音视频通话SDK初始化完成之后,根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
+          this.loadServerJsonAndgetUserIpInfo();
+        });
+      }else {
+        //加入flash
+        loger.log("使用flash通话模式");
         this.loadServerJsonAndgetUserIpInfo();
-      });
+      }
+
      /*
       //根据用户的userIp获取信息,获取服务列表选点,选点测速完成后才加入MCU
       this.loadServerJsonAndgetUserIpInfo();
diff --git a/src/GlobalConfig.js b/src/GlobalConfig.js
index e59e7ff..878d2d3 100644
--- a/src/GlobalConfig.js
+++ b/src/GlobalConfig.js
@@ -371,6 +371,19 @@ class GlobalConfig {
     }
 
   }
+  //通过IP查找IP对象
+  static getIpItem(ip,ipList){
+    if(!ip||!ipList) {
+      return null;
+    }
+    for(let i=0;i<ipList.length;i++){
+      let item=ipList[i];
+      if(item&&item.ip==ip){
+        return item;
+      }
+    }
+    return null;
+  }
 }
 
 GlobalConfig.statusCode_0 = { "code": 0, message: "SDK 未初始化" };
@@ -578,7 +591,7 @@ GlobalConfig.locationProtocol="http://";//https;或http:
 GlobalConfig.websocketProtocol="ws://";//wss或ws
 GlobalConfig.isHttps=false;//是否是https
 
-
+GlobalConfig.openFlash=false;//使用flash通话模式。默认为false,使用的是webRtc
 //webRtc
 GlobalConfig.appId = '';
 GlobalConfig.appCertificate = "";
diff --git a/src/RecordPlayBackParse.js b/src/RecordPlayBackParse.js
index e5a7e5c..82d9c3c 100644
--- a/src/RecordPlayBackParse.js
+++ b/src/RecordPlayBackParse.js
@@ -123,7 +123,6 @@ class RecordPlayBackParse extends Emiter {
 
     //解析和储存,录制回放EverSocket底层消息处理  data-数据;timestamp-数据对应的时间戳
     _parseSaveSocketMsgReceivedHandler(data, timestamp) {
-
         let pduMsg = pdu.decode_pdu(data);
         let pduType = pduMsg.get("type");
         let pduData = pduMsg.get("data");
@@ -135,7 +134,7 @@ class RecordPlayBackParse extends Emiter {
             pduMsg.type = PduType.RCPDU_SEND_DATA_REQUEST;
             pduType = PduType.RCPDU_SEND_DATA_REQUEST;
         }
-        loger.log('解析和储存->pduType', pduType);
+        //loger.log('解析和储存->pduType', pduType);
         switch (pduType) {
             case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
                 //加入课堂请求返回数据处理
@@ -161,7 +160,7 @@ class RecordPlayBackParse extends Emiter {
                 let ape = this._apes[pduMsg.sessionId];
                 let sessionLabel = ApeConsts(pduMsg.sessionId);
                 //只做解析存储,不对外发送
-                loger.log('解析数据-timestamp->', timestamp, 'sessionId->', pduMsg.sessionId, 'sessionLabel->', sessionLabel,"subType:"+pduMsg.subType);
+                //loger.log('解析数据-timestamp->', timestamp, 'sessionId->', pduMsg.sessionId, 'sessionLabel->', sessionLabel,"subType:"+pduMsg.subType);
                 switch (pduMsg.sessionId) {
                     case ApeConsts.CONFERENCE_SESSION_ID:
                         this.saveParseData(data, timestamp, this._conferApeMssages);
@@ -183,11 +182,12 @@ class RecordPlayBackParse extends Emiter {
                         break;
                     case ApeConsts.VIDEO_SESSION_ID:
                         this.saveParseData(data, timestamp, this._videoApeMssages);
-                        this.unPackpduRegAdapterHandler(pduMsg.data,timestamp,data,ApeConsts.VIDEO_SESSION_ID)
+                        this.unpackVideoBroadcastMessage(pduMsg,timestamp,data);
+                        this.unPackpduRegAdapterHandler(pduMsg.data,timestamp,data,ApeConsts.VIDEO_SESSION_ID,pduMsg.subType)
                         break;
                     case ApeConsts.AUDIO_SESSION_ID:
                         this.saveParseData(data, timestamp, this._audioApeMssages);
-                        this.unPackpduRegAdapterHandler(pduMsg.data,timestamp,data,ApeConsts.AUDIO_SESSION_ID)
+                        this.unPackpduRegAdapterHandler(pduMsg.data,timestamp,data,ApeConsts.AUDIO_SESSION_ID,pduMsg.subType)
                         break;
                     default:
                         break;
@@ -625,10 +625,62 @@ class RecordPlayBackParse extends Emiter {
             }
         }
     }
+    //解析视频模块的广播消息
+    unpackVideoBroadcastMessage(pduMsg,timestamp,data){
+        //console.log("VIDEO_SESSION_ID-pduMsg",pduMsg);
+        if(!pduMsg){
+            return;
+        }
+        if(pduMsg.subType!=pdu.RCPDU_SEND_VIDEO_DATA_REQUEST){
+            //视频广播消息,只处理501消息
+            return;
+        }
+        try{
+            let videoReceivePdu = pdu['RCVideoSendDataRequestPdu'].decode(pduMsg.data);
+            if (videoReceivePdu == null) {
+                loger.warn("视频模块广播消息-decode->失败");
+                return;
+            }
+            videoReceivePdu.data = ArrayBufferUtil.uint8ArrayToStr(videoReceivePdu.data, 2);//开头两个字会乱码
+            let dataObj = {};
+            try {
+                dataObj = JSON.parse(videoReceivePdu.data);
+            } catch (err) {
+                loger.warn('视频模块广播消息->JSON转换失败');
+                dataObj = videoReceivePdu.data;
+            }
+            videoReceivePdu.data = dataObj;
+            //actionType:40
+            //data :Object
+            //fromNodeId :902994631
+            //toNodeId : 0
+            if(videoReceivePdu.actionType==40){
+                if(!this._videoApeBroadcastMssages[videoReceivePdu.fromNodeId]){
+                    this._videoApeBroadcastMssages[videoReceivePdu.fromNodeId]={};
+                }
+              /*
+              //结构
+              {
+                    nodeId:{
+                        时间戳:{数据}
+                    },
+                    nodeId:{
+                        时间戳:{数据}
+                    },.....
+                }*/
+
+                this._videoApeBroadcastMssages[videoReceivePdu.fromNodeId][timestamp]={parseData:videoReceivePdu,byteData:data,timestamp: timestamp};
+                //this._videoApeBroadcastMssages[timestamp]={parseData:videoReceivePdu,byteData:data,timestamp: timestamp};
+            }
+
+        }catch (err){
+            console.log("视频模块广播消息->解析失败",err.message);
+        }
+    }
 
     //音视频的数据需要解析,然后按频道储存数据
     // 解析pdu RCAdapterPdu的数据: regBuffer(RCAdapterPdu数据),timestamp(时间戳),  data(mcu的原始数据) sessionId(类型)
-    unPackpduRegAdapterHandler(regBuffer, timestamp, data, sessionId) {
+    unPackpduRegAdapterHandler(regBuffer, timestamp, data, sessionId,subType) {
         let regPdu;
         let regItems ;
         let regItemSize ;
@@ -639,13 +691,7 @@ class RecordPlayBackParse extends Emiter {
              regItemSize = regItems.length;
 
         }catch (err){
-            console.warn('RCAdapterPdu->unpack-error->type类型不对');
-            try {
-                let sendDataPdu = pdu['RCVideoSendDataRequestPdu'].decode(regBuffer);
-                console.log("RCVideoSendDataRequestPdu",sendDataPdu);
-            }catch (err){
-
-            }
+            console.warn('RCAdapterPdu->unpack-error->type类型不对',"subType:"+subType);
             return;
         }
 
@@ -670,7 +716,8 @@ class RecordPlayBackParse extends Emiter {
             let sub_type = regUpdatedItem.subType;
             let object_id = regUpdatedItem.objId;
             let user_data = regUpdatedItem.userData;
-            //console.log('RCRegistryUpdateObjPdu',regUpdatedItem)
+
+            console.log('RCRegistryUpdateObjPdu',regUpdatedItem)
 
             switch (sub_type) {
                 case pdu.RCPDU_REG_ROSTER_INSERT_PDU:
@@ -723,7 +770,7 @@ class RecordPlayBackParse extends Emiter {
                         loger.warn("视频控制消息处理,收到的消息为null,不做处理");
                         return;
                       }
-                      videoReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(videoReceivePdu.data, 2);//开头两个字会乱码
+                      videoReceivePdu.data = ArrayBufferUtil.uint8ArrayToStr(videoReceivePdu.data, 2);//开头两个字会乱码
                       let dataObj = {};
                       try {
                         dataObj = JSON.parse(videoReceivePdu.data);
diff --git a/src/SystemConfig.js b/src/SystemConfig.js
index ecc3035..aa972a0 100644
--- a/src/SystemConfig.js
+++ b/src/SystemConfig.js
@@ -52,28 +52,6 @@ class SystemConfig {
   }
 
   //获取浏览器和信息
-  /*  static getBrowserInfo() {
-   var Sys = {};
-   var ua = navigator.userAgent.toLowerCase();
-   var re = /(trident|msie|firefox|chrome|opera|version).*?([\d.]+)/;
-   var m = ua.match(re);
-   if (!m) m = ["version/1.0.0", "version", "1.0.0"];
-   Sys.explorer = m[1].replace(/version/, "'safari");
-   //判断是否是IE11
-   if (Sys.explorer == "trident") {
-   Sys.explorer = "IE11"
-   Sys.explorerVersion = "11.0";
-   } else if (Sys.explorer == "msie") {
-   //IE
-   Sys.explorer = "IE"
-   Sys.explorerVersion = m[2];
-   } else {
-   //非IE
-   Sys.explorerVersion = m[2];
-   }
-   return Sys;
-   }*/
-  //获取浏览器和信息
   static getBrowserInfo() {
     let Sys = {};
     Sys.explorer = "unknow";
@@ -83,7 +61,7 @@ class SystemConfig {
       let re = /(trident|msie|firefox|chrome|version).*?([\d.]+)/;
       let m = ua.match(re);
       if (!m) m = ["version/1.0.0", "version", "1.0.0"];
-      Sys.explorer = m[1].replace(/version/, "'safari");
+      Sys.explorer = m[1].replace(/version/, "safari");
       //判断是否是IE11
       if (Sys.explorer == "trident") {
         Sys.explorer = "IE11"
diff --git a/src/apes/MediaModule.js b/src/apes/MediaModule.js
index c3c6def..9cf31ed 100644
--- a/src/apes/MediaModule.js
+++ b/src/apes/MediaModule.js
@@ -7,6 +7,7 @@ import Loger from 'Loger';
 import MessageTypes from 'MessageTypes';
 import GlobalConfig from 'GlobalConfig';
 import EngineUtils from 'EngineUtils';
+import MD5 from "md5";
 
 let loger = Loger.getLoger('MediaModule');
 
@@ -37,22 +38,36 @@ class MediaModule {
       if (!GlobalConfig.MS_PLAY_HLS_IP) {
         loger.error("HLS拉流地址地址无效");
       }
-      //http://123.56.73.119:6001/live/h5dev_2106728010_8ab3b0ed5a3a9220015a3a958f0d0003_983041_1489113860/index.m3u8
+    /*  //http://123.56.73.119:6001/live/h5dev_2106728010_8ab3b0ed5a3a9220015a3a958f0d0003_983041_1489113860/index.m3u8
       if (GlobalConfig.siteId == GlobalConfig.siteId_letv) {
         //乐视的hls地址规则
         fileName = 'desc.m3u8';
       } else {
         //fileName='index.m3u8';
         fileName = 'playlist.m3u8';
-      }
+      }*/
       port = (GlobalConfig.MS_PLAY_HLS_PORT == "" || GlobalConfig.MS_PLAY_HLS_PORT == null) ? "" : ":" + GlobalConfig.MS_PLAY_HLS_PORT;
       //path = "http://" + GlobalConfig.MS_PLAY_HLS_IP
+      let ipItem=GlobalConfig.getIpItem(GlobalConfig.MS_PLAY_HLS_IP,GlobalConfig.hlsPullListFinal);//获取IP对象
+      let type="live";//默认值
+      let hlsSuffix="/playlist.m3u8";
+      if(ipItem){
+        type=ipItem.type||"live";
+        hlsSuffix=ipItem.hlsSuffix||"/playlist.m3u8";
+      }
+
       path =GlobalConfig.locationProtocol + GlobalConfig.MS_PLAY_HLS_IP
+        + port + "/"+type+"/"
+        + _param.streamId
+        +hlsSuffix;//
+      //+ "/"+fileName;//
+
+      /*path =GlobalConfig.locationProtocol + GlobalConfig.MS_PLAY_HLS_IP
         + port + "/live/"
         + _param.streamId
         + ".m3u8";//
       //+ "/"+fileName;//
-
+      */
 
     } else {
       //RTMP
@@ -60,12 +75,20 @@ class MediaModule {
         loger.error("RTMP拉流地址地址无效");
       }
       port = (GlobalConfig.MS_PLAY_RTMP_PORT == "" || GlobalConfig.MS_PLAY_RTMP_PORT == null) ? "" : ":" + GlobalConfig.MS_PLAY_RTMP_PORT;
+
+      let ipItem=GlobalConfig.getIpItem(GlobalConfig.MS_PLAY_RTMP_IP,GlobalConfig.rtmpPullListFinal);//获取IP对象
+      let type="live";//默认值
+      if(ipItem){
+        type=ipItem.type||"live";
+      }
       path = "rtmp://" + GlobalConfig.MS_PLAY_RTMP_IP
-        + port + "/live/"
+        + port + "/"+type+"/"
         + _param.streamId;
-    }
-
+      //path = "rtmp://" + GlobalConfig.MS_PLAY_RTMP_IP
+      //  + port + "/live/"
+      //  + _param.streamId;
 
+    }
     path = path.replace("::", ":");//如果ip和port之间有多的:需要去掉
     return {"code": ApeConsts.RETURN_SUCCESS, "data": "", "playUrl": path};
   }
@@ -81,15 +104,41 @@ class MediaModule {
     //M3U8  http://123.56.73.119:6001/live/h5dev_2106728010_8ab3b0ed5a3a9220015a3a958f0d0003_983041_1489113860/total.m3u8
     let port = (GlobalConfig.RS_RECORD_PLAY_PORT == "" || GlobalConfig.RS_RECORD_PLAY_PORT == null) ? "" : ":" + GlobalConfig.RS_RECORD_PLAY_PORT;
     //let path = "http://" + GlobalConfig.RS_RECORD_PLAY_IP
+    let ipItem=GlobalConfig.getIpItem(GlobalConfig.RS_RECORD_PLAY_IP,GlobalConfig.rsPullListFinal);//获取IP对象
+    let type="live";//默认值
+    let rHlsSuffix="/total.m3u8";
+    if(ipItem){
+        type=ipItem.type||"live";
+        rHlsSuffix=ipItem.rHlsSuffix||"/total.m3u8";
+    }
+
     let path =GlobalConfig.locationProtocol + GlobalConfig.RS_RECORD_PLAY_IP
-      + port + "/live/"
+      + port + "/"+type+"/"
       + _param.streamId
-      + "/total.m3u8";
+      +rHlsSuffix;
 
     path = path.replace("::", ":");//如果ip和port之间有多的:需要去掉
     return {"code": ApeConsts.RETURN_SUCCESS, "data": "", "playUrl": path};
   }
 
+  //推流地址后缀拼接参数
+  setPublishSuffix(url,publishSuffix,streamId){
+    let newUrl= url;
+    if(!url||!publishSuffix){
+      return newUrl;
+    }
+    //publishSuffix就是外部传入的key
+    //txSecret  = MD5(key + stream+txTime)
+    let txTime=new Date().getTime()/1000+(12*60*60);
+    //过去时间精确到分钟,转为16进制
+    txTime=parseInt(txTime);
+    txTime=txTime.toString(16);
+    let txSecret= MD5(publishSuffix + streamId+txTime);
+    //rtmp://11220.livepush.myqcloud.com/live/11220_c5a1ea0bce?bizid=11220&txSecret=b1d8af72bf62366eef31cbb5dc5c8778&txTime=59C5337F
+    newUrl=url +"?bizid=11220&txSecret="+txSecret+"&txTime="+txTime+"&record=hls&record_interval=5400";
+    loger.log("生成的推流地址->"+newUrl);
+    return newUrl;
+  }
   //获取推流地址
   getMediaPublishPath(_param) {
     loger.log('获取推流地址->');
@@ -116,8 +165,21 @@ class MediaModule {
       + "_" + freeChannel + "_" + timestamp;
 
     //生成推流地址和推流数据(同步数据的时候用)
+    //let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
+    //  + port + "/" + pubType + "/" + streamId;
+
+    let ipItem=GlobalConfig.getIpItem(GlobalConfig.MS_PUBLISH_IP,GlobalConfig.msListFinal);//获取IP对象
+    let type="live";//默认值
+    if(ipItem){
+      type=ipItem.type||"live";
+    }
     let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
-      + port + "/" + pubType + "/" + streamId;
+      + port + "/"+ type + "/" + streamId;
+
+    //设置推流地址的后缀,有的推流地址需要在地址后面加一些参数
+    if(ipItem&&ipItem.publishSuffix){
+      publishUrl=this.setPublishSuffix(publishUrl,ipItem.publishSuffix,streamId);
+    }
 
     publishUrl = publishUrl.replace("::", ":");//如果ip和port之间有多的:需要去掉
     this.needPublishMediaChannel[publishUrl] = {
@@ -169,9 +231,21 @@ class MediaModule {
       + "_" + freeChannel + "_" + timestamp;
 
     //生成推流地址和推流数据(同步数据的时候用)
+    //let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
+    //  + port + "/" + pubType + "/" + streamId;
+
+    let ipItem=GlobalConfig.getIpItem(GlobalConfig.MS_PUBLISH_IP,GlobalConfig.msListFinal);//获取IP对象
+    let type="live";//默认值
+    if(ipItem){
+      type=ipItem.type||"live";
+    }
     let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
-      + port + "/" + pubType + "/" + streamId;
+      + port + "/"+ type + "/" + streamId;
 
+    //设置推流地址的后缀,有的推流地址需要在地址后面加一些参数
+    if(ipItem&&ipItem.publishSuffix){
+      publishUrl=this.setPublishSuffix(publishUrl,ipItem.publishSuffix,streamId);
+    }
     publishUrl = publishUrl.replace("::", ":");//如果ip和port之间有多的:需要去掉
     this.needPublishMediaChannel[publishUrl] = {
       "channelId": freeChannel,
@@ -213,8 +287,20 @@ class MediaModule {
       + "_" + shareChannel + "_" + timestamp;
 
     //生成推流地址和推流数据(同步数据的时候用)
+    //let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
+    //  + port + "/" + pubType + "/" + streamId;
+    let ipItem=GlobalConfig.getIpItem(GlobalConfig.MS_PUBLISH_IP,GlobalConfig.msListFinal);//获取IP对象
+    let type="live";//默认值
+    if(ipItem){
+      type=ipItem.type||"live";
+    }
     let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
-      + port + "/" + pubType + "/" + streamId;
+      + port + "/"+ type + "/" + streamId;
+
+    //设置推流地址的后缀,有的推流地址需要在地址后面加一些参数
+    if(ipItem&&ipItem.publishSuffix){
+      publishUrl=this.setPublishSuffix(publishUrl,ipItem.publishSuffix,streamId);
+    }
 
     publishUrl = publishUrl.replace("::", ":");//如果ip和port之间有多的:需要去掉
     /* this.needPublishMediaChannel[publishUrl]={
--
libgit2 0.24.0