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
            //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
                + port + "/live/"
                + _param.streamId
                + "/"+fileName;


        } else {
            //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
                + 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";
        ////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":"",
                "mediaId":freeChannel,
                "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":"",
            "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,
            "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
    getOpeningMediaChannel(_nodeId){
        loger.log("getOpeningMediaChannel","nodeId",_nodeId,"mediaChannels:",this.mediaChannels);
        if(_nodeId==null||_nodeId==0){
            return 0;
        }
        for (let key in this.mediaChannels) {
            let item = this.mediaChannels[key];
            if (item && item.status == ApeConsts.CHANNEL_STATUS_OPENING&&item.fromNodeId==_nodeId) {
                return item.channelId;
            }
        }
        return 0;
    }

    //检查频道是否已经被占用
    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;