MediaModule.js 11.7 KB
// //////////////////////////////////////////////////////////////////////////////
//  VideoApe、AudioApe 共用的方法单独提取处理
// //////////////////////////////////////////////////////////////////////////////

import ApeConsts from './ApeConsts';
import Loger from 'Loger';
import MessageTypes from 'MessageTypes';
import GlobalConfig from 'GlobalConfig';
import EngineUtils from 'EngineUtils';

let loger = Loger.getLoger('MediaModule');

class MediaModule {
  constructor() {
    this.needPublishMediaChannel = {};//记录准备推流的频道信息
    this.mediaChannels = {};
    this.maxMediaChannel = 0;
    this.mediaType = ApeConsts.MEDIA_TYPE_DEFAULT;
    this.MEDIA_OBJ_TABLE_ID = 0;
    this.SCREENSHARING_OBJ_TABLE_ID = ApeConsts.SCREENSHARING_OBJ_TABLE_ID;
  }

  //获取播流地址
  getMediaPlayPath(_param) {
    loger.log('获取播放地址->');
    if (_param == null || _param.streamId == null) {
      loger.warn('获取播放地址->参数错误', _param);
      //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
      return {"code": ApeConsts.RETURN_FAILED, "data": ""};
    }

    let path = "";
    let port = "";
    let fileName = '';
    if (_param.type == "m3u8") {
      //M3U8
      if (!GlobalConfig.MS_PLAY_HLS_IP) {
        loger.error("HLS拉流地址地址无效");
      }
      //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
      path =GlobalConfig.locationProtocol + GlobalConfig.MS_PLAY_HLS_IP
        + port + "/live/"
        + _param.streamId
        + ".m3u8";//
      //+ "/"+fileName;//


    } else {
      //RTMP
      if (!GlobalConfig.MS_PLAY_RTMP_IP) {
        loger.error("RTMP拉流地址地址无效");
      }
      port = (GlobalConfig.MS_PLAY_RTMP_PORT == "" || GlobalConfig.MS_PLAY_RTMP_PORT == null) ? "" : ":" + GlobalConfig.MS_PLAY_RTMP_PORT;
      path = "rtmp://" + GlobalConfig.MS_PLAY_RTMP_IP
        + port + "/live/"
        + _param.streamId;
    }


    path = path.replace("::", ":");//如果ip和port之间有多的:需要去掉
    return {"code": ApeConsts.RETURN_SUCCESS, "data": "", "playUrl": path};
  }


  //获取录制回放时点播的地址,只有m3u8
  getMediaRecordPlaybackPath(_param) {
    loger.log('获取录制回放时点播的地址->m3u8');
    if (_param == null || _param.streamId == null) {
      loger.warn('获取录制回放时点播的地址->参数错误', _param);
      return {"code": ApeConsts.RETURN_FAILED, "data": ""};
    }
    //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 path =GlobalConfig.locationProtocol + GlobalConfig.RS_RECORD_PLAY_IP
      + port + "/live/"
      + _param.streamId
      + "/total.m3u8";

    path = path.replace("::", ":");//如果ip和port之间有多的:需要去掉
    return {"code": ApeConsts.RETURN_SUCCESS, "data": "", "playUrl": path};
  }

  //获取推流地址
  getMediaPublishPath(_param) {
    loger.log('获取推流地址->');
    //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
    let freeChannel = this.getFreeMediaChannel();
    if (freeChannel == 0) {
      return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaChannels};
    }

    //默认方式推流
    let pubType = "live";

    if (!GlobalConfig.MS_PUBLISH_IP) {
      loger.error("MS推流地址地址无效");
    }

    //端口,有端口就显示 ":xxx",没有端口就是""
    let port = (GlobalConfig.MS_PUBLISH_PORT == "" || GlobalConfig.MS_PUBLISH_PORT == null) ? "" : ":" + GlobalConfig.MS_PUBLISH_PORT;
    //时间戳
    let timestamp = EngineUtils.creatTimestamp();

    let streamId = GlobalConfig.siteId + "_"
      + GlobalConfig.classId + "_" + GlobalConfig.userId
      + "_" + freeChannel + "_" + timestamp;

    //生成推流地址和推流数据(同步数据的时候用)
    let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
      + port + "/" + pubType + "/" + streamId;

    publishUrl = publishUrl.replace("::", ":");//如果ip和port之间有多的:需要去掉
    this.needPublishMediaChannel[publishUrl] = {
      "channelId": freeChannel,
      "publishUrl": publishUrl,
      "streamId": streamId,
      "timestamp": timestamp,
      "nodeId": GlobalConfig.nodeId
    };
    return {
      "code": ApeConsts.RETURN_SUCCESS,
      "data": "",
      "mediaId": freeChannel,
      "userId": GlobalConfig.userId,
      "userName": GlobalConfig.userName,
      "userRole": GlobalConfig.userRole,
      "publishUrl": publishUrl
    };
  }

  //监课获取推流地址
  getMediaPublishPathForInVisible(_param) {
    let mediaLen = Object.keys(MediaModule.allMediaChannelsList).length;
    let freeChannel = (this.MEDIA_OBJ_TABLE_ID - 20 - mediaLen) || GlobalConfig.nodeId;
    loger.log('监课获取推流地址->' + freeChannel + " mediaLen:" + mediaLen);
    //默认方式推流
    let pubType = "live";
    ////flash推流
    //if(_param&&_param.type=="flash"){
    //    pubType ="flash";
    //}

    //端口,有端口就显示 ":xxx",没有端口就是""
    let port = (GlobalConfig.MS_PUBLISH_PORT == "" || GlobalConfig.MS_PUBLISH_PORT == null) ? "" : ":" + GlobalConfig.MS_PUBLISH_PORT;
    //时间戳
    let timestamp = EngineUtils.creatTimestamp();

    let streamId = GlobalConfig.siteId + "_"
      + GlobalConfig.classId + "_" + GlobalConfig.userId
      + "_" + freeChannel + "_" + timestamp;

    //生成推流地址和推流数据(同步数据的时候用)
    let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
      + port + "/" + pubType + "/" + streamId;

    publishUrl = publishUrl.replace("::", ":");//如果ip和port之间有多的:需要去掉
    this.needPublishMediaChannel[publishUrl] = {
      "channelId": freeChannel,
      "publishUrl": publishUrl,
      "streamId": streamId,
      "timestamp": timestamp,
      "nodeId": GlobalConfig.nodeId
    };
    return {
      "code": ApeConsts.RETURN_SUCCESS,
      "data": "",
      "userId": GlobalConfig.userId,
      "userName": GlobalConfig.userName,
      "userRole": GlobalConfig.userRole,
      "mediaId": freeChannel,
      "publishUrl": publishUrl
    };
  }

  //桌面共享获取推流地址,频道号由外部传入
  getMediaPublishPathForScreenShare(_shareChannel, _publishType) {

    let shareChannel = _shareChannel || this.SCREENSHARING_OBJ_TABLE_ID;
    loger.log('桌面共享获取推流地址->' + shareChannel);
    //默认方式推流
    let pubType = "live";//统一使用live 20170615
    /*//flash推流
     if(_publishType=="live"){
     pubType ="live";
     }*/

    //端口,有端口就显示 ":xxx",没有端口就是""
    let port = (GlobalConfig.MS_PUBLISH_PORT == "" || GlobalConfig.MS_PUBLISH_PORT == null) ? "" : ":" + GlobalConfig.MS_PUBLISH_PORT;
    //时间戳
    let timestamp = EngineUtils.creatTimestamp();

    let streamId = GlobalConfig.siteId + "_"
      + GlobalConfig.classId + "_" + GlobalConfig.userId
      + "_" + shareChannel + "_" + timestamp;

    //生成推流地址和推流数据(同步数据的时候用)
    let publishUrl = "rtmp://" + GlobalConfig.MS_PUBLISH_IP
      + port + "/" + pubType + "/" + streamId;

    publishUrl = publishUrl.replace("::", ":");//如果ip和port之间有多的:需要去掉
    /* this.needPublishMediaChannel[publishUrl]={
     "channelId":shareChannel,
     "publishUrl":publishUrl,
     "streamId":streamId,
     "timestamp":timestamp,
     "nodeId":GlobalConfig.nodeId
     };*/
    return {
      "code": ApeConsts.RETURN_SUCCESS,
      "data": "",
      "mediaId": shareChannel,
      "userId": GlobalConfig.userId,
      "userName": GlobalConfig.userName,
      "userRole": GlobalConfig.userRole,
      "publishUrl": publishUrl,
      "streamId": streamId
    };
  }

  //获取当前空闲的channel,返回值为0代表没有空闲的,否则返回的就是空闲的channelId
  getFreeMediaChannel() {
    let counter = 0;
    for (let key in this.mediaChannels) {
      let item = this.mediaChannels[key];
      if (item && item.status == ApeConsts.CHANNEL_STATUS_RELEASED) {
        loger.log("已获取空闲的通道->channelId:" + item.channelId);
        return item.channelId;
      }
      counter++;
    }
    loger.log("获取空闲的通道", "mediaChannels", this.mediaChannels, "counter:", counter);
    //loger.log(this.mediaChannels);
    if (counter < this.maxMediaChannel) {
      return this.MEDIA_OBJ_TABLE_ID + (counter);
    }
    return 0;//没有空闲的
  }

  //获取准备推流的频道信息
  getNeedPublishMediaChannel(_publishUrl) {
    return this.needPublishMediaChannel[_publishUrl];
  }

  //获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId
  getOpeningMediaChannelForNodeId(_nodeId) {
    loger.log("getOpeningMediaChannel", "nodeId", _nodeId, "mediaChannels:", this.mediaChannels);
    let channelInfo = {};
    channelInfo.channelId = 0;
    if (_nodeId == null || _nodeId == 0) {
      return channelInfo;
    }
    for (let key in this.mediaChannels) {
      let item = this.mediaChannels[key];
      if (item && item.status == ApeConsts.CHANNEL_STATUS_OPENING && item.fromNodeId == _nodeId) {
        return item;
      }
    }
    return channelInfo;
  }

  //检查频道是否已经被占用
  checkChannelIsOpening(_channelId) {
    if (_channelId == null) {
      loger.warn("checkChannelIsOpening error,channel=", _channelId);
      return true;
    }
    let channelInfo = this.mediaChannels[_channelId];
    if (channelInfo == null || channelInfo.status == ApeConsts.CHANNEL_STATUS_RELEASED) {
      return false;
    }
    return true;
  }

  //获取当前所有频道的信息
  getAllMediaChannelInfo() {
    let channels = [];
    for (let key in this.mediaChannels) {
      let channel = this.mediaChannels[key];
      if (channel) {
        channels.push({"mediaId": channel.channelId, "status": channel.status, "fromNodeId": channel.fromNodeId});
      }
    }
    if (channels.length < this.maxMediaChannel) {
      for (let i = channels.length; i < this.maxMediaChannel; i++) {
        let channelId = this.MEDIA_OBJ_TABLE_ID + (i);
        channels.push({"mediaId": channelId, "status": ApeConsts.CHANNEL_STATUS_RELEASED, "fromNodeId": 0});
      }
    }
    return channels;
  }

  //获取默认的频道信息
  getDefaultChannelInfo() {
    let channelInfo = {};
    channelInfo.owner = 0;//这个很重要,释放的时候必须设置为0,占用的时候设置为自己的nodeId
    channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
    channelInfo.fromNodeId = GlobalConfig.nodeId;
    channelInfo.channelId = 0;//channelId不能为0
    channelInfo.streamId = "";
    channelInfo.classId = GlobalConfig.classId;
    channelInfo.siteId = GlobalConfig.siteId;
    channelInfo.toNodeId = 0;
    channelInfo.userId = GlobalConfig.userId;
    channelInfo.mediaType = this.mediaType || ApeConsts.MEDIA_TYPE_DEFAULT;
    return channelInfo;
  }
}
MediaModule.allMediaChannelsList = {};//当前已经创建的所有音视频通道(包含释放或未未释放的)
export default MediaModule;