李勇

webRtc增加对移动连续推流和停止推流导致的无法收到流消息处理,解决收不到移动端视频的问题

... ... @@ -62,7 +62,7 @@ export default class MessageEntrance extends Emiter {
constructor() {
super();
//sdk 信息
GlobalConfig.sdkVersion = "v2.9.3.20170919";
GlobalConfig.sdkVersion = "v2.10.4.20170920";
loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
//设置
... ... @@ -147,6 +147,7 @@ export default class MessageEntrance extends Emiter {
//_confer_ape.on(MessageTypes.SWITCH_RTMP_PULL_IP, this._switchRtmpPullIpHandler.bind(this)); //MS 拉流地址动态选点
//_confer_ape.on(MessageTypes.SWITCH_HLS_IP, this._switchHlsIpHandler.bind(this)); //MS HLS动态选点
_confer_ape.on(MessageTypes.STOP_ALL_MEDIA_PUBLISH, this._stopAllMediaPublishHandler.bind(this)); //课堂状态发生改变,需要停止当前的所有推流
_confer_ape.on(MessageTypes.CLASS_UPDATE_ROSTER,this._onRosterUpdateHandler.bind(this));
_chat_ape = new ChatApe();
_chat_ape.on('*', (type, data) => this._emit(type, data));
... ... @@ -1359,6 +1360,22 @@ export default class MessageEntrance extends Emiter {
loger.log('课堂状态发生改变,需要停止当前的所有推流');
this._emit(MessageTypes.MEDIA_STOP_PUBLISH);
}
//用更状态数据发送变更
_onRosterUpdateHandler(_data){
//数据无效/ios/android 不处理数据
if(!_data||GlobalConfig.deviceType==1||GlobalConfig.deviceType==2){
return;
}
let nodeData=_data.nodeData;
//数据用户是pc或H5不处理
if(!nodeData||nodeData.deviceType==0||nodeData.deviceType==3){
return;
}
if(nodeData.openCamera>0&&_webRtc){
loger.log("收到移动端用户数据更新,当前是开启摄像头状态,需要尝试添加一个远程视频");
_webRtc.tryAddMobileStream(_data.nodeId);
}
}
//手动切换MS -> {ip;"xxx.xx.xx","port":"xxxx"}
_switchMediaServer(_param) {
... ... @@ -1742,7 +1759,7 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.className = _data.meetingName || "";
GlobalConfig.classBeginTime = _data.beginTime || "";
GlobalConfig.classEndTime = _data.endTime || "";
GlobalConfig.channelId = ""+GlobalConfig.siteId+"_"+GlobalConfig.classId;
//sdk获取ip失败就使用saas返回的
if(!GlobalConfig.userIp){
GlobalConfig.userIp = _data.userIp || "";
... ...
... ... @@ -33,6 +33,7 @@ class RecordPlayBackParse extends Emiter {
this._recordPlaybackMaxTime = 0;//录制回放的总时间
this._isReady = false;//录制回放是否已经准备完成
this._apes = {};
this._videoApeBroadcastMssages={};//视频模块的广播消息
this.mediaChannleList={};
this._conferApeMssages = {};//会议数据
this._chatApeMssages = {};//聊天数据
... ... @@ -134,7 +135,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:
//加入课堂请求返回数据处理
... ... @@ -160,7 +161,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);
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);
... ... @@ -375,7 +376,7 @@ class RecordPlayBackParse extends Emiter {
console.log('文档数据',this._docApeMssages);
console.log('白板数据',this._whiteApeMssages);
console.log('聊天数据',this._chatApeMssages);
console.log('视频模块广播消息',this._videoApeBroadcastMssages);
loger.log("录制回放数据解析完成,录制回放的总时间长为->", this._recordPlaybackMaxTime,"recordTimestamp:"+GlobalConfig.recordTimestamp);
this._emit(RecordPlayBackParse.CLASS_JOIN_RECORD_PLAYBACK_SUCCESS, {"recordPlaybackMaxTime": this._recordPlaybackMaxTime});
}
... ... @@ -638,9 +639,16 @@ class RecordPlayBackParse extends Emiter {
regItemSize = regItems.length;
}catch (err){
console.warn('RCAdapterPdu->unpack-error->type类型不对')
console.warn('RCAdapterPdu->unpack-error->type类型不对');
try {
let sendDataPdu = pdu['RCVideoSendDataRequestPdu'].decode(regBuffer);
console.log("RCVideoSendDataRequestPdu",sendDataPdu);
}catch (err){
}
return;
}
for (var i = 0; i < regItemSize; ++i) {
let regItem = regItems[i];
let regItemType = regItem.type;
... ... @@ -707,6 +715,28 @@ class RecordPlayBackParse extends Emiter {
let tableDeleteData = pdu['RCRegistryTableDeleteItemPdu'].decode(user_data);
//console.log("tableDeleteData",object_id,tableDeleteData);
break;
case pdu.RCPDU_SEND_VIDEO_DATA_REQUEST:
//视频模块的控制消息
try{
let videoReceivePdu = pdu['RCVideoSendDataRequestPdu'].decode(user_data);
if (videoReceivePdu == null) {
loger.warn("视频控制消息处理,收到的消息为null,不做处理");
return;
}
videoReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(videoReceivePdu.data, 2);//开头两个字会乱码
let dataObj = {};
try {
dataObj = JSON.parse(videoReceivePdu.data);
} catch (err) {
loger.warn('控制消息->JSON转换失败');
dataObj = videoReceivePdu.data;
}
videoReceivePdu.data = dataObj;
this._videoApeBroadcastMssages[timestamp]={parseData:videoReceivePdu,byteData:data,timestamp: timestamp};
}catch (err){
loger.warn("RCPDU_SEND_VIDEO_DATA_REQUEST->err",err);
}
break;
case pdu.RCPDU_REG_TABLE_UPDATE_PDU:
let tableUpdateData = pdu['RCRegistryTableUpdateItemPdu'].decode(user_data);
let tableUpdateItems = tableUpdateData.items;
... ...
... ... @@ -30,7 +30,7 @@ class SystemConfig {
}
if (mdetect.isAndroid()) {
GlobalConfig.platform = "android"; //"android";
GlobalConfig.deviceType = 2; //"ios";
GlobalConfig.deviceType = 2; //"android";
}
//语言
... ...
... ... @@ -35,6 +35,8 @@ class WebRtcApe extends Emiter {
this.curCameraId = "";
this.curMicrophoneId = "";
this.remoteVideoList={};//记录远程视频流
this.videoResolution = "240P";
this.isOpenVideo = true;
... ... @@ -138,6 +140,10 @@ class WebRtcApe extends Emiter {
});
this.client.on('stream-subscribed', (evt)=> {
let stream = evt.stream;
this.addRemoetStreamView(stream);
});
/* this.client.on('stream-subscribed', (evt)=> {
let stream = evt.stream;
if(stream){
//let viewDiv=`<div id="${this.xdyRemote + stream.getId()}" style="width:${this.hostRemoteVideoWidth}px;height:${this.hostRemoteVideoHeight}px;"></div>`;
let uid=stream.getId();
... ... @@ -148,6 +154,7 @@ class WebRtcApe extends Emiter {
userName=user.name||"";
userRole=user.userRole;
}
let nameDiv=`<div style="width:98%;height:20px; position: absolute; z-index: 1;left: 4px;overflow:hidden;font-size: 14px; color: #cccccc;display:${this.nameDisplay}">${userName}</div>`;
if(userRole==ApeConsts.invisible){
... ... @@ -172,14 +179,21 @@ class WebRtcApe extends Emiter {
stream.play(this.xdyRemote + stream.getId());
}catch (err){
}
if(user.deviceType==1||user.deviceType==2){
this.remoteVideoList[user.nodeId]=stream;
}
console.log("移动端远程视频流集合->",this.remoteVideoList);
}
});
});*/
this.client.on('stream-removed', (evt)=> {
let stream = evt.stream;
stream.stop();
$('#' + this.xdyRemote + stream.getId()).remove();
loger.log("远程视频流已经断开:" + stream.getId());
if(stream){
stream.stop();
$('#' + this.xdyRemote + stream.getId()).remove();
loger.log("远程视频流已经断开:" + stream.getId());
}
});
this.client.on('peer-leave', (evt)=> {
... ... @@ -196,6 +210,48 @@ class WebRtcApe extends Emiter {
});
}
addRemoetStreamView(stream){
if(stream){
//let viewDiv=`<div id="${this.xdyRemote + stream.getId()}" style="width:${this.hostRemoteVideoWidth}px;height:${this.hostRemoteVideoHeight}px;"></div>`;
let uid=stream.getId();
let user=GlobalConfig.getUserInfoFromeNodeId(uid);
let userName="";
let userRole=""
if(user){
userName=user.name||"";
userRole=user.userRole;
}
let nameDiv=`<div style="width:98%;height:20px; position: absolute; z-index: 1;left: 4px;overflow:hidden;font-size: 14px; color: #cccccc;display:${this.nameDisplay}">${userName}</div>`;
if(userRole==ApeConsts.invisible){
//把远程视频添加到监课列表
loger.log("获取远程视频流成功->监课:"+userName+"->" + uid,new Date().getTime());
let viewDiv=`<div id="${this.xdyRemote + uid}" style="width:${this.invisibleVideoWidth}px;height:${this.invisibleVideoHeight}px;float: left;margin-right: 1px;pointer-events: none;">${nameDiv}</div>`;
$(this.invisibleViewId).append(viewDiv);
}else if(userRole==ApeConsts.host){
//把远程视图添加到老师列表
loger.log("获取远程视频流成功->老师:"+userName+"->" + uid,new Date().getTime());
let viewDiv=`<div id="${this.xdyRemote + uid}" style="width:${this.hostRemoteVideoWidth}px;height:${this.hostRemoteVideoHeight}px;float: left;margin-right: 1px;pointer-events: none;">${nameDiv}</div>`;
$(this.hostRemoteViewId).append(viewDiv);
}else {
//把视图添加到学生列表
loger.log("获取远程视频流成功->学生:"+userName+"->" +uid,new Date().getTime());
let viewDiv=`<div id="${this.xdyRemote + uid}" style="width:${this.normalRemoteVideoWidth}px;height:${this.normalRemoteVideoHeight}px;float: left;margin-right: 1px;pointer-events: none;">${nameDiv}</div>`;
$(this.normalRemoteViewId).append(viewDiv);
}
//播放视频,隐藏控制条
try{
$("bar_"+stream.getId()).hide();
stream.play(this.xdyRemote + stream.getId());
}catch (err){
}
if(user.deviceType==1||user.deviceType==2){
this.remoteVideoList[user.nodeId]=stream;
}
console.log("移动端远程视频流集合->",this.remoteVideoList);
}
}
//重新添加远程视频
reAddRemoteStream(_stream){
if(!_stream){
... ... @@ -215,7 +271,6 @@ class WebRtcApe extends Emiter {
return;
}
if(err=="PEERCONNECTION_FAILED"){
//this.reAddRemoteStreamDelay=setTimeout(()=>{
setTimeout(()=>{
loger.warn("连接远程的流失败->尝试重新连接",err);
this.reAddRemoteStream(_stream);
... ... @@ -224,6 +279,23 @@ class WebRtcApe extends Emiter {
loger.warn("添加一个远程视频流->失败", err); }
});
}
//尝试添加远程的移动设备视频流
tryAddMobileStream(nodeId){
let stream=this.remoteVideoList[nodeId];
if(!stream){
return;
}
let remoteView=document.getElementById(this.xdyRemote +nodeId)
console.log("remoteView->",remoteView)
if(remoteView){
loger.log(nodeId+" 流已经添加显示,不需要再处理");
return;
}
if(stream) {
loger.log("收到移动端推流的消息,主动添加一个远程视频流");
this.addRemoetStreamView(stream);
}
}
joinChannel(_params) {
this.channelId = _params.channelId||"";
... ...