李勇

1.视频模块增加字段,推流的时候可以设置流名称和拉流的地址;2.录制回放增加接获取声网视频文件地址的接口;3.修复chrome浏览器被识别为360极速的问题;4…

….录制回放模块增加流名称和视频地址的匹配接口
market_webrtc_发布版
mcu/ms/rs服务器:腾讯云测试
appConfig:
eyJhcHBJZCI6IjBmZTQ1YmJlYTU5YjRlZTU4NmM4ZGVkNjlmMmJjOGY3IiwiYXBwQ2VydGlmaWNhdGUiOiIiLCJhcHBSZWNvcmRpbmdLZXkiOiIiLCJyZWNvcmRJbnRlcmZhY2VzIjoibmV0d29ya3NjaG9vbC54dWVkaWFueXVuLmNvbS9zZXJ2ZXIvdXNlcnMvUmVjb3JkaW5nIiwiZ2V0Q2hhbm5lbFRva2VuIjoibmV0d29ya3NjaG9vbC54dWVkaWFueXVuLmNvbS9zZXJ2ZXIvdXNlcnMvZW5jcnlwdGlvblRva2VuIiwiZ2V0UmVjb3JkSW5mb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL2dldFJlY29yZEluZm8iLCJzdG9wUmVjb3JkaW5nSW50ZXJmYWNlcyI6Im5ldHdvcmtzY2hvb2wueHVlZGlhbnl1bi5jb20vc2VydmVyL3JlY29yZEluZm8vc3RvcFJlY29yZGluZyIsImdldFR4UmVjb3JkSW5mb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL3RlbmNlbnRSZWNvcmRJbmZvIn0=
eyJhcHBJZCI6IjBmZTQ1YmJlYTU5YjRlZTU4NmM4ZGVkNjlmMmJjOGY3IiwiYXBwQ2VydGlmaWNhdGUiOiIiLCJhcHBSZWNvcmRpbmdLZXkiOiIiLCJyZWNvcmRJbnRlcmZhY2VzIjoibmV0d29ya3NjaG9vbC54dWVkaWFueXVuLmNvbS9zZXJ2ZXIvdXNlcnMvUmVjb3JkaW5nIiwiZ2V0Q2hhbm5lbFRva2VuIjoibmV0d29ya3NjaG9vbC54dWVkaWFueXVuLmNvbS9zZXJ2ZXIvdXNlcnMvZW5jcnlwdGlvblRva2VuIiwiZ2V0UmVjb3JkSW5mb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL2dldFJlY29yZEluZm8iLCJzdG9wUmVjb3JkaW5nSW50ZXJmYWNlcyI6Im5ldHdvcmtzY2hvb2wueHVlZGlhbnl1bi5jb20vc2VydmVyL3JlY29yZEluZm8vc3RvcFJlY29yZGluZyIsImdldFR4UmVjb3JkSW5mb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL3RlbmNlbnRSZWNvcmRJbmZvIiwiZ2V0UmVjb3JkRmlsZVVSTEFnb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL2dldFJlY29yZEZpbGVVUkwifQ==
market_webrtc_测试版
mcu/ms/rs服务器:腾讯云测试
appConfig: eyJhcHBJZCI6ImViMjUzY2M3YjQwYzRhOGI4MmYwYTViNmY5M2MyY2UwIiwiYXBwQ2VydGlmaWNhdGUiOiIiLCJhcHBSZWNvcmRpbmdLZXkiOiIiLCJyZWNvcmRJbnRlcmZhY2VzIjoibmV0d29ya3NjaG9vbC54dWVkaWFueXVuLmNvbS9zZXJ2ZXIvdXNlcnMvUmVjb3JkaW5nIiwiZ2V0Q2hhbm5lbFRva2VuIjoibmV0d29ya3NjaG9vbC54dWVkaWFueXVuLmNvbS9zZXJ2ZXIvdXNlcnMvZW5jcnlwdGlvblRva2VuIiwiZ2V0UmVjb3JkSW5mb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL2dldFJlY29yZEluZm8iLCJzdG9wUmVjb3JkaW5nSW50ZXJmYWNlcyI6Im5ldHdvcmtzY2hvb2wueHVlZGlhbnl1bi5jb20vc2VydmVyL3JlY29yZEluZm8vc3RvcFJlY29yZGluZyIsImdldFR4UmVjb3JkSW5mb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL3RlbmNlbnRSZWNvcmRJbmZvIn0=
appConfig: eyJhcHBJZCI6ImViMjUzY2M3YjQwYzRhOGI4MmYwYTViNmY5M2MyY2UwIiwiYXBwQ2VydGlmaWNhdGUiOiIiLCJhcHBSZWNvcmRpbmdLZXkiOiIiLCJyZWNvcmRJbnRlcmZhY2VzIjoibmV0d29ya3NjaG9vbC54dWVkaWFueXVuLmNvbS9zZXJ2ZXIvdXNlcnMvUmVjb3JkaW5nIiwiZ2V0Q2hhbm5lbFRva2VuIjoibmV0d29ya3NjaG9vbC54dWVkaWFueXVuLmNvbS9zZXJ2ZXIvdXNlcnMvZW5jcnlwdGlvblRva2VuIiwiZ2V0UmVjb3JkSW5mb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL2dldFJlY29yZEluZm8iLCJzdG9wUmVjb3JkaW5nSW50ZXJmYWNlcyI6Im5ldHdvcmtzY2hvb2wueHVlZGlhbnl1bi5jb20vc2VydmVyL3JlY29yZEluZm8vc3RvcFJlY29yZGluZyIsImdldFR4UmVjb3JkSW5mb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL3RlbmNlbnRSZWNvcmRJbmZvIiwiZ2V0UmVjb3JkRmlsZVVSTEFnb0ludGVyZmFjZXMiOiJuZXR3b3Jrc2Nob29sLnh1ZWRpYW55dW4uY29tL3NlcnZlci9yZWNvcmRJbmZvL2dldFJlY29yZEZpbGVVUkwifQ==
market_flash_发布版
... ...
... ... @@ -62,7 +62,7 @@ export default class MessageEntrance extends Emiter {
constructor() {
super();
//sdk 信息
GlobalConfig.sdkVersion = "v2.17.11.20171014";
GlobalConfig.sdkVersion = "v2.18.10.20171019";
loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
//设置
... ... @@ -311,6 +311,7 @@ export default class MessageEntrance extends Emiter {
this.addWarn = this._addWarn.bind(this);
this.addError = this._addError.bind(this);
this.hasFreePublishChannel=this._hasFreePublishChannel.bind(this);//判断是否还有空闲的推流通道
}
//设置是否输出日志
... ... @@ -1227,10 +1228,16 @@ export default class MessageEntrance extends Emiter {
if(GlobalConfig.appId&&!GlobalConfig.openFlash){
//加入之前先设置旁录地址,只有直播支持旁路
if(_webRtc&&GlobalConfig.isTeachOrAssistant){
let publishData=this._getVideoPublishPath();
let curTimestamp = new Date().getTime();
let streamId=GlobalConfig.siteId+"_"+GlobalConfig.classId+"_"+GlobalConfig.userId+"_"+curTimestamp;
//传入固定的流Id
let publishData=this._getVideoPublishPath({streamId:streamId});
loger.log("加入之前先设置旁录地址",publishData);
if(publishData&&publishData.code==0){
_webRtc.setConfigPublisherUrl(publishData.publishUrl);
let m3u8Stream = _video_ape.getPlayVideoPath({"type": "m3u8", "streamId":streamId});
let rtmpStream = _video_ape.getPlayVideoPath({"type": "rtmp", "streamId":streamId});
_webRtc.setRtmpM3u8Path({m3u8Url:m3u8Stream.playUrl,rtmpUrl:rtmpStream.playUrl});
}
}
setTimeout(()=>{
... ... @@ -1987,6 +1994,14 @@ export default class MessageEntrance extends Emiter {
return {"code": ApeConsts.RETURN_FAILED, "data": ""};
}
if (_video_ape) {
//if(_data.status==WebRtcApe.RECORD_STATUS_1&&!_data.publishUrl){
if(_data.status==WebRtcApe.RECORD_STATUS_1){
let publishData=this._getVideoPublishPath();
let publishUrl="";
if(publishData&&publishData.code==0){
_data.publishUrl=publishData.publishUrl||"";
}
}
_video_ape.mediaPublishStatusChange(_data);
}
}
... ... @@ -2808,6 +2823,7 @@ export default class MessageEntrance extends Emiter {
_webRtc.leaveChannel(_params);
}
}
/*
* 发布流
* */
... ... @@ -2826,7 +2842,8 @@ export default class MessageEntrance extends Emiter {
loger.log("调用webRtc推流");
GlobalConfig.openCamera = EngineUtils.creatTimestamp();
GlobalConfig.openMicrophones = GlobalConfig.openCamera;
this.userDeviecStatusChange({
this.userDeviecStatusChange({
nodeId: GlobalConfig.nodeId,
userRole: GlobalConfig.userRole,
userName: GlobalConfig.userName,
... ... @@ -2943,10 +2960,16 @@ export default class MessageEntrance extends Emiter {
if(_webRtc){
_webRtc.changeRtcVideoConfig(_params);
//如果是老师操作,需要同步给所有人
if(GlobalConfig.isHost){
//如果是老师和主讲人操作,需要同步给所有人
if(GlobalConfig.isTeachOrAssistant){
if(_confer_ape){
GlobalConfig.videoScale=_params.videoScale||1;
let newVideoScale=_params.videoScale||1;
if(GlobalConfig.videoScale==newVideoScale){
loger.log("不需要设置视频视图大小,没有发生改变",newVideoScale);
return;
}
loger.log("设置视频视图大小->",newVideoScale);
GlobalConfig.videoScale=newVideoScale;
_confer_ape.sendUpdaterClassStatusInfo({videoScale:_params.videoScale});
}
}
... ... @@ -2982,6 +3005,7 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.getRecordInfoInterfaces=_params.getRecordInfoInterfaces||"";
GlobalConfig.stopRecordingInterfaces=_params.stopRecordingInterfaces||"";
GlobalConfig.getTxRecordInfoInterfaces=_params.getTxRecordInfoInterfaces||"";
GlobalConfig.getRecordFileURLAgoInterfaces=_params.getRecordFileURLAgoInterfaces||"";
//去掉协议头
try{
... ... @@ -2997,6 +3021,10 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.getTxRecordInfoInterfaces=GlobalConfig.getTxRecordInfoInterfaces.replace('http://',"");
GlobalConfig.getTxRecordInfoInterfaces=GlobalConfig.getTxRecordInfoInterfaces.replace('https://',"");
}
if(GlobalConfig.getRecordFileURLAgoInterfaces){
GlobalConfig.getRecordFileURLAgoInterfaces=GlobalConfig.getRecordFileURLAgoInterfaces.replace('http://',"");
GlobalConfig.getRecordFileURLAgoInterfaces=GlobalConfig.getRecordFileURLAgoInterfaces.replace('https://',"");
}
if(GlobalConfig.stopRecordingInterfaces){
GlobalConfig.stopRecordingInterfaces=GlobalConfig.stopRecordingInterfaces.replace('http://',"");
... ... @@ -3035,5 +3063,17 @@ export default class MessageEntrance extends Emiter {
}
}
//webRtc-----------------end --------------------------------
//判断是否能推流,当前课堂推流人数是有限制的
_hasFreePublishChannel(){
let premission=GlobalConfig.getPublishPermission();
loger.log("判断是否能推流->",premission);
if(!premission&&GlobalConfig.userRole!=ApeConsts.invisible){
loger.warn("不能再打开更多设备");
console.log("当前用户列表",GlobalConfig.rosters);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_WEBRTC_PUBLISH_FULL);
return premission;
}
return premission;
}
}
... ...
... ... @@ -617,7 +617,7 @@ GlobalConfig.recordInterfaces="";//控制开启录制和录制状态改变的接
GlobalConfig.getRecordInfoInterfaces="";//获取媒体录制信息数据的接口
GlobalConfig.stopRecordingInterfaces="";//停止录制的接口
GlobalConfig.getTxRecordInfoInterfaces="";//获取媒体录制信息数据的接口(tx)
GlobalConfig.getRecordFileURLAgoInterfaces="";//获取媒体录制信息数据的接口(ago)
GlobalConfig.getChannelToken="";//获取token的地址
GlobalConfig.videoScale=1;//视频的缩放倍数,默认1倍无缩放
... ...
... ... @@ -33,8 +33,9 @@ class RecordPlayBackParse extends Emiter {
this._recordPlaybackTimestamp = 0;//回放的时间
this._recordPlaybackMaxTime = 0;//录制回放的总时间
this._isReady = false;//录制回放是否已经准备完成
this.isLoadTxRecordInfo=false;//是否已经加载腾讯云的录制数据
this.isLoadAgoraRecordInfo=false;//是否已经加载声网的录制数据
this.isLoadTxRecordInfo=false;//是否已经加载TXY的录制数据
this.isLoadAgoRecordInfo=false;//是否已经加载AGO的录制数据
this.isgetRecordFileURLFromAgo=false;//是否已经加载AGO的录制文件地址数据
this._apes = {};
this._videoApeBroadcastMssages={};//视频模块的广播消息
... ... @@ -301,20 +302,85 @@ class RecordPlayBackParse extends Emiter {
this.getMediaRecrodInfoFromTx(()=>{
//解析录制的rec数据
this.isLoadTxRecordInfo=true;
if(this.isLoadTxRecordInfo&&this.isLoadAgoraRecordInfo){
if(this.isLoadTxRecordInfo&&this.isLoadAgoRecordInfo&&this.isgetRecordFileURLFromAgo){
this.parseArrayBuf();
}
});
this.getMediaRecrodInfoFromAgora(()=>{
this.isLoadAgoraRecordInfo=true;
this.isLoadAgoRecordInfo=true;
//解析录制的rec数据
if(this.isLoadTxRecordInfo&&this.isLoadAgoraRecordInfo){
if(this.isLoadTxRecordInfo&&this.isLoadAgoRecordInfo&&this.isgetRecordFileURLFromAgo){
this.parseArrayBuf();
}
});
this.getRecordFileURLFromAgo(()=>{
this.isgetRecordFileURLFromAgo=true;
//解析录制的rec数据
if(this.isLoadTxRecordInfo&&this.isLoadAgoRecordInfo&&this.isgetRecordFileURLFromAgo){
this.parseArrayBuf();
}
})
}
}
//获取媒体录制的地址信息-时间戳流名称和文件地址对应
getRecordFileURLFromAgo(_callback){
if(!GlobalConfig.getRecordFileURLAgoInterfaces){
loger.log("AGOR-获取媒体录制信息->失败->接口地址无效");
if(_callback){
_callback();
}
return ;
}
let url = `${GlobalConfig.locationProtocol+GlobalConfig.getRecordFileURLAgoInterfaces}`;
loger.log('AGOR-获取媒体录制信息.', url);
//接口中用的是GET
fetch(encodeURI(url), {
method: 'POST',
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"
},
body: `path=${ GlobalConfig.channelId}`,
timeout: 15000
})
.then(ret => {
if (ret.ok) {
return ret.json();
} else {
loger.error(`AGOR-获取媒体录制信息-网络异常.状态码:${ret}`);
if(_callback){
_callback();
}
throw '';
}
})
.then(ret => {
loger.log('AGOR-获取媒体录制地址信息-完成',ret);
/* {"code": 200,
"returnData":{
"data":[
{channel:"markettest_153452314"
createTime:"1508125785740"
fileUrl:"http://networkschool.xuedianyun.com:8899/20171016/markettest_153452314_033717/125533402_20171016034945745_av.mp4"
timestamp :"1508125785519"
uid:"125533402" }
]
} }*/
if(ret&&ret.code==200){
if(ret.returnData&&ret.returnData.data){
this.parseAndSavaStreamInfoFromAgor(ret.returnData.data);
}
}
if(_callback){
_callback();
}
})
.catch(err => {
loger.error(`AGOR-获取媒体录制信息-异常.状态码:${err}`);
if(_callback){
_callback();
}
});
}
//获取媒体录制信息
getMediaRecrodInfoFromAgora(_callback){
//获取课堂录制信息 get localhost:3000/recordInfo/getRecordInfo/7d72365eb9834353397e3e3f9d460bdda
... ... @@ -373,7 +439,7 @@ class RecordPlayBackParse extends Emiter {
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"
},
body: `channelId=${ GlobalConfig.channelId}`,
timeout: 5000
timeout: 15000
})
.then(ret => {
if (ret.ok) {
... ... @@ -415,8 +481,38 @@ class RecordPlayBackParse extends Emiter {
}
});
}
//解析agor录制的视频数据,数组[]
parseAndSavaStreamInfoFromAgor(_dataArr){
//{channel:"markettest_153452314"
// createTime:"1508125785740"
// fileUrl:"http://networkschool.xuedianyun.com:8899/20171016/markettest_153452314_033717/125533402_20171016034945745_av.mp4"
// timestamp :"1508125785519",
// userId:"T9663",
// uid:"125533402" }
if(!_dataArr){
loger.log("AGOR-外部录制的视频数据无效");
return;
}
let item;
loger.log("AGOR-外部录制的视频数据-length="+_dataArr.length)
for(let i=0;i<_dataArr.length;i++){
item=_dataArr[i];
if(item&&item.fileUrl){
let streamId=item.channel+"_"+item.userId+"_"+item.timestamp;
//if(item.fileUrl.indexOf(".m3u8")>0){
// MediaModule.streams[itemJson.stream_id]=itemJson.video_url;
//}
if(!MediaModule.streams[streamId]){
MediaModule.streams[streamId]=item.fileUrl;
}else {
loger.log("流数据已经存在->",streamId, MediaModule.streams[streamId],item.fileUrl);
}
}
}
console.log("AGO MediaModule.streams", MediaModule.streams);
}
//解析腾讯云录制的视频数据,数组[]
//解析TXY录制的视频数据,数组[]
parseAndSavaStreamInfoFromTx(_dataArr){
/* "id": "0zo9GALQdmkwrJVYxqgaE6xM7j8yvOZN",
"channelId": "marketflashtest_1966232762",
... ... @@ -445,7 +541,7 @@ class RecordPlayBackParse extends Emiter {
}
}
}
console.log(" MediaModule.streams", MediaModule.streams);
console.log("TX MediaModule.streams", MediaModule.streams);
}
//解析录制的rec数据
... ...
... ... @@ -170,23 +170,40 @@ class SystemConfig {
}
else if (Sys.explorer == "chrome") {
if (window.clientInformation.languages) {
let versionNum=0;
let versions=[];
if(Sys.explorerVersion){
versions=Sys.explorerVersion.split(".");
}
versionNum=parseInt(versions[0]);
loger.log("versionNum", versionNum);
if (window.clientInformation.languages.length > 2) {
Sys.explorer = "chrome";
loger.log("chrome", Sys);
}else if (window.clientInformation.languages.length == 2) {
} else if (window.clientInformation.languages.length == 2&&versionNum<60) {
var _track = 'track' in document.createElement('track');
var webstoreKeysLength = window.chrome && window.chrome.webstore ? Object.keys(window.chrome.webstore).length : 0;
if (_track) {
webstoreKeysLength > 1 ? '360ee' : '360se';
if(webstoreKeysLength>1){
if (webstoreKeysLength > 1) {
//loger.log("当前是360极速浏览器", Sys);
Sys.explorer = "360极速";
}else {
} else {
loger.log("当前是360安全浏览器", Sys);
Sys.explorer = "360安全";
}
}
}
//61版本的chrome速浏览器在有的系统会被误认为是360极速,需要处理
if (Sys.explorer == "360极速") {
if (Sys.explorerVersion.indexOf("60.") == 0 ||
Sys.explorerVersion.indexOf("61.") == 0) {
//这个是chrome浏览器
Sys.explorer = "chrome";
}
}
}
}
//safari浏览器
... ...
... ... @@ -103,7 +103,7 @@ class MediaModule {
}
//如果是外部的流地址,不需要拼接,直接使用就可以,是完整的地址
let streamPlayUrl=MediaModule.streams[_param.streamId]
let streamPlayUrl=MediaModule.streams[_param.streamId];
if(streamPlayUrl){
loger.log("使用外部的流地址->",streamPlayUrl);
streamPlayUrl=streamPlayUrl.replace("http://","");
... ... @@ -175,6 +175,11 @@ class MediaModule {
+ GlobalConfig.classId + "_" + GlobalConfig.userId
+ "_" + freeChannel + "_" + timestamp;
//如果外部传入了流ID就使用外部的
if(_param&&_param.streamId){
streamId=_param.streamId;
}
//生成推流地址和推流数据(同步数据的时候用)
//let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
// + port + "/" + pubType + "/" + streamId;
... ... @@ -241,6 +246,10 @@ class MediaModule {
+ GlobalConfig.classId + "_" + GlobalConfig.userId
+ "_" + freeChannel + "_" + timestamp;
//如果外部传入了流ID就使用外部的
if(_param&&_param.streamId){
streamId=_param.streamId;
}
//生成推流地址和推流数据(同步数据的时候用)
//let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
// + port + "/" + pubType + "/" + streamId;
... ...
... ... @@ -121,7 +121,6 @@ class VideoApe extends Ape {
//根据推流的地址获取对应的频道信息
let needPublishChannelInfo = this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl);
console.log("needPublishChannelInfo",needPublishChannelInfo);
if (needPublishChannelInfo == null) {
loger.warn('推流->推流数据已经无效', _param);
this._emit(MessageTypes.VIDEO_PUBLISH_RESULT, {
... ... @@ -132,6 +131,14 @@ class VideoApe extends Ape {
return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"};
}
//如果外部传入了流Id就使用外部的
if(_param.streamId){
needPublishChannelInfo.streamId=_param.streamId;
loger.log("推流信息->使用外部传递的流ID",needPublishChannelInfo);
}else {
loger.log("推流信息->使用原始的流ID",needPublishChannelInfo);
}
//判断当前是否还有空闲的channle
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
... ... @@ -175,6 +182,8 @@ class VideoApe extends Ape {
channelInfo.status = ApeConsts.CHANNEL_STATUS_OPENING;
channelInfo.channelId = needPublishChannelInfo.channelId;
channelInfo.streamId = needPublishChannelInfo.streamId;//按规则拼接的流名称
channelInfo.m3u8Url=_param.m3u8Url||"";
channelInfo.rtmpUrl=_param.rtmpUrl||""
channelInfo.timestamp = needPublishChannelInfo.timestamp;//时间戳
channelInfo.mediaType = ApeConsts.MEDIA_TYPE_VIDEO;
this.sendTableUpdateHandler(channelInfo);
... ... @@ -218,14 +227,14 @@ class VideoApe extends Ape {
}
//推流状态发生改变
mediaPublishStatusChange(_data){
loger.log("推流状态发生改变->");
loger.log("推流状态发生改变->",_data);
this.sendVideoBroadcastMsg({
"actionType": ApeConsts.MEDIA_ACTION_PUBLISH_STATUS,
"toNodeId": 0,
"data":_data|| ""
});
//如果是老师或主讲人助教,推流需要同步
/* //如果是老师或主讲人助教,推流需要同步
if(GlobalConfig.isTeachOrAssistant){
_data.nodeId=GlobalConfig.nodeId;
if(_data.status==1){
... ... @@ -234,8 +243,16 @@ class VideoApe extends Ape {
_data.nodeId=GlobalConfig.nodeId;
this.stopPublishVideo(_data)
}
}
}*/
//推流需要同步
_data.nodeId=GlobalConfig.nodeId;
if(_data.status==1){
this.publishVideo(_data);
}else if(_data.status==0){
_data.nodeId=GlobalConfig.nodeId;
this.stopPublishVideo(_data)
}
}
//==========================屏幕共享=========================================================================
... ... @@ -622,6 +639,14 @@ class VideoApe extends Ape {
"type": "m3u8",
"streamId": unpackChannelInfo.streamId
});
//如果接收的消息中已经有拉流地址,优先使用
if(unpackChannelInfo.m3u8Url){
m3u8Stream.playUrl=unpackChannelInfo.m3u8Url;
}
if(unpackChannelInfo.rtmpUrl){
rtmpStream.playUrl=unpackChannelInfo.rtmpUrl;
}
if (m3u8Stream.code == 0) {
receiveChannelInfo.m3u8Url = m3u8Stream.playUrl;
... ... @@ -771,6 +796,9 @@ class VideoApe extends Ape {
packPduModel.status = _param.status || ApeConsts.CHANNEL_STATUS_RELEASED;
packPduModel.channelId = _itemIdx;
packPduModel.streamId = _param.streamId || "";
packPduModel.m3u8Url=_param.m3u8Url || "";
packPduModel.rtmpUrl=_param.rtmpUrl || "";
packPduModel.siteId = _param.siteId || GlobalConfig.siteId;//GlobalConfig.siteId;
packPduModel.classId = parseInt(_param.classId) || parseInt(GlobalConfig.classId);
packPduModel.userId = _param.userId || "0";
... ...
... ... @@ -21,6 +21,8 @@ class WebRtcApe extends Emiter {
this.appRecordingKey = "";
this.configPublisherUrl = "";//旁路地址;
this.m3u8Url="";//旁路拉流地址
this.rtmpUrl="";//旁路拉流地址
this.channelKey = null;
this.channelId = "";
... ... @@ -434,7 +436,17 @@ class WebRtcApe extends Emiter {
loger.warn("设置旁路地址->失败->为初始化或旁路地址无效",_publishUrl);
}
}
/*
* 设置旁录拉流地址
* */
setRtmpM3u8Path(_param){
//_webRtc.setRtmpM3u8Path({m3u8Url:m3u8Stream,rtmpUrl:rtmpStream});
loger.log("设置旁录拉流地址",_param);
if(_param){
this.m3u8Url=_param.m3u8Url||"";
this.rtmpUrl=_param.rtmpUrl||"";
}
}
publish(_params) {
if (!this.client || !this.localStream) {
return;
... ... @@ -574,7 +586,6 @@ class WebRtcApe extends Emiter {
this.videoScale=scale;
loger.log("更新视频视图大小->videoScale:"+this.videoScale);
this.updateAllVideoSize();
}
/*
... ... @@ -730,6 +741,8 @@ class WebRtcApe extends Emiter {
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;
//mcu记录一份数据
this._emit(MessageTypes.MEDIA_PUBLISH_STATUS_CHANGE, {
appId: GlobalConfig.appId,
... ... @@ -742,7 +755,10 @@ class WebRtcApe extends Emiter {
userRole: GlobalConfig.userRole,
timestamp: curTimestamp,
recordTimestamp: GlobalConfig.recordTimestamp,
publishUrl:this.configPublisherUrl
streamId:streamId,
publishUrl:this.configPublisherUrl,
m3u8Url:this.m3u8Url,
rtmpUrl:this.rtmpUrl
});
return data;
}
... ...
... ... @@ -853,6 +853,8 @@ message RCVideoChannelInfoPdu {
optional uint32 screenHeight = 14;//屏幕分辨率高
optional uint32 deviceType = 15;//设备类型
optional string optionJsonData =16;//其他参数的json对象
optional string m3u8Url =17;//m3u8拉流地址
optional string rtmpUrl =18;//rtmp拉流地址
}
message RCVideoChannelInfoRecordPdu {
... ...