李勇

1.修改视频模块数据的PDU

2.推流和播流地址根据类型拼接
3.在会议模块增加对视频模块的无效的占用channel的释放
... ... @@ -77,6 +77,8 @@ export default class MessageEntrance extends Emiter {
_confer_ape.on(MessageTypes.CLASS_EXIT, this._doClassExit.bind(this));//监听自己的关闭事件
_confer_ape.on(MessageTypes.CLASS_STATUS_INFO_CHANGE, this._onClassStatusInfoChange.bind(this));//当前会议状态信息发生改变
_confer_ape.on(MessageTypes.CLASS_DELETE_ROSTER, this._onClassDeleteRoster.bind(this));//当前会议人员离开
_confer_ape.on(MessageTypes.CLASS_NONENTITY_ROSTER,this._onClassNonentityRoster.bind(this));//当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在
_chat_ape = new ChatApe();
_chat_ape.on('*', (type, data) => this._emit(type, data));
... ... @@ -180,11 +182,24 @@ export default class MessageEntrance extends Emiter {
if(_data!=null&&_data.nodeId!=null&&GlobalConfig.isHost){
loger.log("有人员离开,检查一下离开的人员是否关闭推流");
if(_video_ape){
_video_ape.stopPublishVideo(_data.nodeId);
_video_ape.stopPublishVideo(_data);
}
}
}
//当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
//的占用状态导致,对于这种情况,需要释放掉
_onClassNonentityRoster(_param){
if(_param==null||_param.fromNodeId==null){
loger.warn("onClassNonentityRoster.参数错误")
return;
}
if(_video_ape){
_video_ape.stopPublishVideo({"nodeId":_param.fromNodeId});
}
}
//Sass
//初始化
_init(_param, _onSuccess, _mcuErrorCallBack) {
... ... @@ -397,13 +412,14 @@ export default class MessageEntrance extends Emiter {
//包含整个会议最全的信息,储存数据
if (_data) {
GlobalConfig.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表
GlobalConfig.setDocRecordList(_data.docRecordList);//
GlobalConfig.setDocList(_data.docList);//
GlobalConfig.setMsList(_data.msList);//
GlobalConfig.setMcuList(_data.mcuList);//
GlobalConfig.setDocRecordList(_data.docRecordList);//录制回放地址??
GlobalConfig.setDocList(_data.docList);//文档地址
GlobalConfig.setMsList(_data.msList);//推流播流服务器地址
GlobalConfig.setRsList(_data.rsList);//播放m3u8格式的地址
GlobalConfig.setMcuList(_data.mcuList);//mcu
GlobalConfig.setMusicList(_data.musicList);//
GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//
GlobalConfig.setRsList(_data.rsList);//
GlobalConfig.setMusicListPrepare(_data.musicListPrepare);//提前上传的声音文件列表
}
if (_data.currentInfo) {
... ...
... ... @@ -16,8 +16,10 @@ MessageTypes.CLASS_JOIN_SUCCESS = 'join.class.success';
//会议信息和操作事件定义
//MessageTypes.CLASS_SHOW_DETAIL = 'class_detail.message';
MessageTypes.CLASS_SHOW_ROSTER_NUM = 'roster_num.message';
MessageTypes.CLASS_INSERT_ROSTER = 'roster_insert.message';
MessageTypes.CLASS_DELETE_ROSTER = 'roster_delete.message';
MessageTypes.CLASS_INSERT_ROSTER = 'roster.insert.message';
MessageTypes.CLASS_DELETE_ROSTER = 'roster.delete.message';
MessageTypes.CLASS_NONENTITY_ROSTER = 'roster.nonentity.message';
MessageTypes.CLASS_EXIT = 'class.exit';//退出 关闭会议
MessageTypes.CLASS_UPTATE_STATUS = 'class.update.status';//更新会议状态信息
MessageTypes.CLASS_STATUS_INFO_CHANGE= 'class.status.info.change';//会议状态信息发生改变,需要保存数据到sass和同步MCU
... ...
... ... @@ -97,7 +97,7 @@ ApeConsts.CHANNEL_STATUS_OPENING = 1;///< 已经占用成功
//媒体类型
ApeConsts.MEDIA_TYPE_DEFAULT=0;//没有类型
ApeConsts.MEDIA_TYPE_VIDEO=1;//视频流(包含音频)
ApeConsts.MEDIA_TYPE_VIDEO=2;//音频流
ApeConsts.MEDIA_TYPE_AUDIO=2;//音频流
//FLASH中使用下面4个
ApeConsts.CGS_RELEASED = 0;///< 无人占用状态
... ...
... ... @@ -12,16 +12,9 @@ import Loger from 'Loger';
import GlobalConfig from 'GlobalConfig';
import EngineUtils from 'EngineUtils';
let loger = Loger.getLoger('ConferApe');
let itemIdx=0;//table插入新数据的计数id,目前用时间戳
let timerCounter;
//const ACTION_TYPE_0=0;
//const ACTION_TYPE_1=1;
//const ACTION_TYPE_2=2;
//const ACTION_TYPE_3=3;
//const ACTION_TYPE_4=4;
class ConferApe extends Ape {
constructor() {
super(
... ... @@ -460,9 +453,22 @@ class ConferApe extends Ape {
//视频模块发生更新,人员状态需要更新
updaterRosterStatus(_param){
loger.log("视频模块发生更新,人员状态需要更新");
console.log(_param);
//如果是自己。改变自己的状态同步到MCU
if(_param){
loger.log("视频模块发生更新,人员状态需要更新,fromNodeId->",_param.fromNodeId);
loger.log(_param.status,_param.fromNodeId,this.rosters[_param.fromNodeId]);
//console.log(_param.fromNodeId);
//如果是自己。改变自己的状态同步到MCU
//if(_param.fromNodeId==GlobalConfig.nodeId){
//
//}
//如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的
if(_param.status==ApeConsts.CHANNEL_STATUS_OPENING&&this.rosters[_param.fromNodeId]==null){
loger.log("视频模块被占用,占有人已经不存在课堂中,释放Channel,_param->",_param);
this._emit(MessageTypes.CLASS_NONENTITY_ROSTER,_param.fromNodeId);
}
}
}
//删除用户
rosterDelHandler(nodeId) {
... ... @@ -570,7 +576,6 @@ class ConferApe extends Ape {
return null;
}
}
export default ConferApe;
... ...
... ... @@ -56,18 +56,21 @@ class VideoChat extends Ape {
}
let path = "";
let port="";
if (_param.type == "m3u8") {
//M3U8 默认用80端口
//http://123.56.73.119/hls/h5dev_403074980_0_983042_1487641745/index.m3u8
//M3U8
//http://123.56.73.119:6001/hls/h5dev_403074980_0_983041_1487663265/index.m3u8
port = (GlobalConfig.RSServerPort == "" || GlobalConfig.RSServerPort == null) ? "":":" + GlobalConfig.RSServerPort;
path = "http://" + GlobalConfig.RSServerIP
+"/hls/" + _param.siteId
+ port + "/live/"
+ _param.siteId
+ "_" + _param.classId
+ "_" + _param.userId
+ "_" + _param.channelId
+ "_" + _param.timestamp
+ "/index.m3u8";
} else {
let port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "" : ":" + GlobalConfig.MSServerPort;
port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort;
path = "rtmp://" + GlobalConfig.MSServerIP
+ port + "/live/"
+ _param.siteId
... ... @@ -82,21 +85,40 @@ class VideoChat extends Ape {
//获取推流地址
getPublishVideoPath(_param) {
loger.log('getPublishVideoPath');
//if(_param==null){
// loger.warn('getPublishVideoPath,参数错误',_param);
// this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
// return {"code":1,"data":"getPublishVideoPath,参数错误"};;
//}
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let freeChannel = this.getFreeVideoChannel();
if (freeChannel == 0) {
return {"code": 1, "data": "不能再打开更多的设备"};
}
let port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "" : ":" + GlobalConfig.MSServerPort;
//默认方式推流
let pubType="live";
//flash推流
if(_param&&_param.type=="flash"){
pubType ="flash";
}
//端口,有端口就显示 ":xxx",没有端口就是""
let port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort;
//时间戳
let timestamp = EngineUtils.creatTimestamp();
let publishUrl = "rtmp://" + GlobalConfig.MSServerIP + port + "/flash/" +GlobalConfig.siteId+"_"+ GlobalConfig.classId + "_"+GlobalConfig.userId+"_" + freeChannel + "_" + timestamp;
return {"code": 0, "data": {"siteId":GlobalConfig.siteId,"classId":GlobalConfig.classId,"userId":GlobalConfig.userId,"channelId": freeChannel, "timestamp": timestamp, "publishUrl": publishUrl}};
//生成推流地址和推流数据(同步数据的时候用)
let publishUrl = "rtmp://" + GlobalConfig.MSServerIP
+ port + "/"+pubType+"/" +GlobalConfig.siteId+"_"
+ GlobalConfig.classId + "_"+GlobalConfig.userId
+"_" + freeChannel + "_" + timestamp;
return {"code": 0,
"data":
{ "siteId":GlobalConfig.siteId,
"classId":GlobalConfig.classId,
"userId":GlobalConfig.userId,
"channelId": freeChannel,
"timestamp": timestamp,
"publishUrl": publishUrl
}
};
}
//推流
... ... @@ -148,7 +170,12 @@ class VideoChat extends Ape {
stopPublishVideo(_param) {
loger.log('stopPublishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels);
//_param如果为空,那么默认就是当前自己的nodeId,否则用_param
let nodeId=_param||GlobalConfig.nodeId;
let nodeId;
if(_param&&parseInt(_param.nodeId)>=0){
nodeId=parseInt(_param.nodeId);
}else {
nodeId=GlobalConfig.nodeId;
}
let openingChannel = this.getOpeningVideoChannel(nodeId);
if (openingChannel == 0) {
... ... @@ -351,11 +378,12 @@ class VideoChat extends Ape {
packPduModel.channelId = _itemIdx;
packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId;
packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId);
packPduModel.userId =_param.userId||"0";
packPduModel.mediaType =_param.mediaType|| ApeConsts.MEDIA_TYPE_VIDEO;
packPduModel.timestamp =_param.timestamp||EngineUtils.creatTimestamp();
packPduModel.fromNodeId = GlobalConfig.nodeId;
packPduModel.toNodeId = 0;
console.log(packPduModel);
console.log("packPdu",packPduModel);
return packPduModel;
}
... ...
... ... @@ -768,6 +768,8 @@ message RCVideoChannelInfoPdu {
optional uint32 to_node_id = 5;//接收者的id,(如果是0,所有人都接收)
optional uint32 media_type = 6;//媒体类型:视频(包含音频)或音频
optional uint32 class_id = 7;//课堂号
optional string site_id = 8;//站点号
optional string user_id = 9;//用户的userId
}
message RCVideoChannelInfoRecordPdu {
... ...