李勇

1.修改FLASH推流拉流的规则-使用腾讯云

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
... ...
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
... ...
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
... ...
[
{
"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
... ...
... ... @@ -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();
... ...
... ... @@ -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 = "";
... ...
... ... @@ -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);
... ...
... ... @@ -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"
... ...
... ... @@ -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]={
... ...