RecordInfoMatch.js 12.6 KB
import Emiter from 'Emiter';
import MessageTypes from 'MessageTypes';
import Loger from 'Loger';

import MediaModule from "apes/MediaModule";

import Base64 from 'base64-js';
import GlobalConfig from 'GlobalConfig';
import EngineUtils from 'EngineUtils';


// 日志对象
const loger = Loger.getLoger('RecordInfoParse');
class RecordInfoMatch extends Emiter {
  constructor() {
    super();
    this.recordMessages = {};
    this.jsonPathList = {};
    this.m3u8jsonDataList = {};
    this.streamInfoLen = 0;
    this.filePath = "";
    this.matchStreams = {};//记录匹配完成的数据
    this.unMatchStreams = {};//记录匹配完成的数据
    this.unMatchUid = {};//没有匹配到的uid
  }

  start() {
    let serverIp = GlobalConfig.recordFileSever || "123.56.73.119:8080";
    this.filePath = `${GlobalConfig.locationProtocol + serverIp}`;
    this.getRecordInfo(()=> {
      let requestLen = Object.keys(this.jsonPathList).length;
      let currentLen = 0;
      let fileNameArr;
      for (let i in this.jsonPathList) {
        this.getRecordFileJSON(this.jsonPathList [i], (data)=> {
          currentLen++;
          console.log(i, "getRecordFileJSON请求返回", currentLen);
          if (data) {
            for (let k in data) {
              let arr = data[k];
              let indexStr = ".m3u8";
              //"694537045_20171103073546522.m3u8" //522.m3u8是需要截取掉的内容
              for (let j of arr) {
                if (j && j.indexOf(indexStr) >= 0) {
                  //console.log("视频地址:"+i+"/"+k+"/"+j);
                  fileNameArr = j.split("_");
                  if (fileNameArr && fileNameArr.length > 0) {
                    let stream = fileNameArr[1];
                    //20171106102811807  -->20171106102811
                    stream = stream.substr(0, 14);
                    if (!this.m3u8jsonDataList[fileNameArr[0]]) {
                      this.m3u8jsonDataList[fileNameArr[0]] = {}
                    }
                    //筛除一些重复流地址,会出现多录制的情况,保留一个即可
                    this.m3u8jsonDataList[fileNameArr[0]][stream] = {
                      video_url: this.filePath + "/" + i + "/" + k + "/" + j,
                      creatDate: i,
                      folder: k,
                      stream: j,
                      createTimeUTC: stream
                    };
                  }

                }
              }
            }
          }
          if (currentLen >= requestLen) {
            console.log("视频数据获取完成", this.m3u8jsonDataList);
            this.matchRecordFile(this.recordMessages, this.m3u8jsonDataList);
          }
        });
      }
    });
  }

  getRecordInfo(_callback) {
    //获取课堂录制信息   get  localhost:3000/recordInfo/getRecordInfo/7d72365eb9834353397e3e3f9d460bdda
    //localhost:3000/recordInfo/getRecordInfo/ 后面直接添加课堂号 channel
    if (!GlobalConfig.getRecordInfoInterfaces) {
      loger.log("AG-获取媒体录制信息->失败->接口地址无效");
      if (_callback) {
        _callback();
      }
      return;
    }
    let url = `${GlobalConfig.locationProtocol + GlobalConfig.getRecordInfoInterfaces}/${GlobalConfig.channelId}`;
    loger.log('AG-获取媒体录制信息.', url);
    fetch(url, {
      timeout: 15000
    })
      .then(ret => {
        if (ret.ok) {
          return ret.json();
        } else {
          loger.error(`AG-获取媒体录制信息-网络异常.状态码:${ret}`);
          if (_callback) {
            _callback();
          }
          throw '';
        }
      })
      .then(ret => {
        loger.log('AG-获取媒体录制信息-完成');
        for (let i = 0; i < ret.returnData.data.length; i++) {
          let item = ret.returnData.data[i];
          if (item.status == 1) {
            this.streamInfoLen++;
            //console.log(JSON.stringify(item));
            delete item.appId;
            delete  item.id;
            let time = parseInt(item.createTime);
            let timeInfo = this.timestampToUTCTime(time);
            //return {yymmddhhmmss:yymmddhhmmss,yymmdd:yymmdd}
            item.seek = 0;
            item.createTimeUTC = timeInfo.yymmddhhmmss;
            item.creatDate = timeInfo.yymmdd;
            this.jsonPathList [timeInfo.yymmdd] = this.filePath + "/" + timeInfo.yymmdd + "/json/" + item.channel + ".json";
            item.stream_id = item.channel + "_" + item.userId + "_" + item.timestamp;

            if (!this.recordMessages[item.uid]) {
              this.recordMessages[item.uid] = {};
            }
            this.recordMessages[item.uid][item.timestamp] = item;
          }
        }
        if (_callback) {
          _callback();
        }
      })
      .catch(err => {
        loger.error(`AG-获取媒体录制信息-异常.状态码:${err}`);
        if (_callback) {
          _callback();
        }
      });
  }

  getRecordFileJSON(path, _callback) {
    let url = path + "?t=" + new Date().getTime();
    /* $.ajax(
     {
     type: "GET",
     url: location,
     dataType: 'json',
     success: function (data) {
     console.log("getRecordFileJSON success", data);
     if (_callback) {
     _callback(data);
     }
     },
     error: function (data) {
     //alert(data.code);
     console.log("getRecordFileJSON error", data);
     if (_callback) {
     _callback(null);
     }
     }
     }
     );*/
    fetch(url, {
      timeout: 5000,
      method: 'GET',
    })
      .then(ret => {
        if (ret.ok) {
          return ret.json();
        } else {
          loger.error(`AG-getRecordFileJSON-网络异常.状态码:${ret}`);
          if (_callback) {
            _callback();
          }
          throw '';
        }
      })
      .then(ret => {
        loger.log('AG-getRecordFileJSON-完成');
        if (_callback) {
          _callback(ret);
        }
      })
      .catch(err => {
        loger.error(`AG-getRecordFileJSON-异常.状态码:${err}`);
        if (_callback) {
          _callback();
        }
      });
  }

  matchRecordFile(_messages, _m3u8List) {
    let _recordMessages = _messages;
    let _m3u8jsonDataList = _m3u8List;
    console.log("匹配之前的消息集合", _recordMessages);
    console.log("匹配之前的视频地址集合", _m3u8jsonDataList);
    let matchStreams = {};
    let uidRecordInfo;
    let uidRecordFile;

    for (let k in _recordMessages) {
      this.matchForUid(k, _recordMessages[k], _m3u8jsonDataList[k]);
    }

    console.log("unMatchUid", this.matchStreams);
    console.log("_recordMessages", _recordMessages);
    console.log("_m3u8jsonDataList", _m3u8jsonDataList);
    console.log("最终匹配完成的数量为->" + Object.keys(this.matchStreams).length, "未匹配成功的数量为->" + (this.streamInfoLen - parseInt(Object.keys(this.matchStreams).length)));
    console.log("没有录制文件的用户", this.unMatchUid);
    this._emit(RecordInfoMatch.RECORD_INFO_MATCH_COMPLETE, this.matchStreams);
  }

  matchForUid(k, _recordMessages, _m3u8jsonDataList) {
    let uidRecordInfo = _recordMessages;
    let uidRecordFile = _m3u8jsonDataList;
    if (!uidRecordFile) {
      console.log(k, "没有录制文件");
      this.unMatchUid[k] = uidRecordInfo;
    } else {

      let uidRecordInfoArr = Object.values(uidRecordInfo);
      let uidRecordFileArr = Object.values(uidRecordFile);
      uidRecordInfoArr = uidRecordInfoArr.sort(function (a, b) {
        return parseInt(a.createTimeUTC) - parseInt(b.createTimeUTC);
      });
      uidRecordFileArr = uidRecordFileArr.sort(function (a, b) {
        return parseInt(a.createTimeUTC) - parseInt(b.createTimeUTC);
      });

      if (uidRecordInfoArr.length == uidRecordFileArr.length && uidRecordFileArr.length > 0) {
        //1.如果文件数量和消息数量相等,直接关联即可
        console.log(k + "->数量相同->直接匹配", uidRecordInfoArr.length);
        for (let h = 0; h < uidRecordInfoArr.length; h++) {
          let item = uidRecordInfoArr[h];
          item.video_url = uidRecordFileArr[h].video_url;
          this.matchStreams[item.stream_id] = item;
        }

      } else {
        //2.通过时间戳匹配
        for (let f in uidRecordInfo) {
          let time = parseInt(uidRecordInfo[f].createTimeUTC);
          let video_url = "";
          let video_urlObj = uidRecordFile[k + "_" + time];
          if (video_urlObj && video_urlObj.video_url) {
            video_url = video_urlObj.video_url;
          }
          //模糊
          if (!video_url) {
            video_urlObj = uidRecordFile[k + "_" + (time + 1)];
            if (video_urlObj && video_urlObj.video_url) {
              video_url = video_urlObj.video_url;
            }
          }
          if (!video_url) {
            video_urlObj = uidRecordFile[k + "_" + (time - 1)];
            if (video_urlObj && video_urlObj.video_url) {
              video_url = video_urlObj.video_url;
            }
          }

          //通过时间戳匹配 结束
          if (video_url) {
            let item = uidRecordInfo[f];
            item.video_url = video_url;
            this.matchStreams[item.stream_id] = item;
          } else {
            console.log(k + "_" + time, "按时间戳没有查找到->");
          }
        }

        //3.最后一次通过间隔查找
        if (uidRecordInfoArr.length != uidRecordFileArr.length && uidRecordFileArr.length > 0 && uidRecordInfoArr.length > 0) {
          console.log(k + "->数量不同  消息数量:" + uidRecordInfoArr.length, "视频数量:" + uidRecordFileArr.length);
          //按消息的数量大于视频数量处理
          let lastFileItem;//记录最后一个
          for (let h = 0; h < uidRecordInfoArr.length; h++) {
            let infoItem = uidRecordInfoArr[h];
            let fileItem = uidRecordFileArr[h];
            if (fileItem) {
              infoItem.video_url = fileItem.video_url;

              //如果之前没有匹配到才设置
              if (!this.matchStreams[infoItem.stream_id]) {
                this.matchStreams[infoItem.stream_id] = infoItem;
              }
              lastFileItem = infoItem;//记录最后一个文件的数据
            } else {
              if (lastFileItem) {
                infoItem.video_url = lastFileItem.video_url;
                infoItem.seek = parseInt(infoItem.createTimeUTC) - parseInt(lastFileItem.createTimeUTC);
                if (!this.matchStreams[infoItem.stream_id]) {
                  this.matchStreams[infoItem.stream_id] = infoItem;
                }
              }
            }

          }
        }

        /*
         //没有查找到之后,如果两次推流的消息时间过短,只会有一个视频,需要再次匹配
         console.log("uidRecordInfoUnsearch", uidRecordInfoUnsearch, uidRecordInfo);
         if (Object.keys(uidRecordInfoUnsearch).length > 0) {
         let item;
         let item2;
         let minInterval = 10000;
         let nearItem = null;
         for (let s in uidRecordInfoUnsearch) {
         item = uidRecordInfoUnsearch[s];
         for (let h in uidRecordInfo) {
         item2 = uidRecordInfo[h];
         if (item2 && item2.video_url) {
         let interval = parseInt((item.createTime) * 0.001 - parseInt(item2.createTime) * 0.001);
         if (minInterval > interval) {
         nearItem = item2;
         minInterval = interval;
         }
         minInterval = Math.min(minInterval, interval);
         //console.log("两次推流消息的间隔",interval);
         }
         }
         }
         if (item && nearItem) {
         console.log("查找到最接近的消息", nearItem, "seek", minInterval);
         item.video_url = nearItem.video_url;
         item.seek = minInterval;
         matchStreams[item.stream_id] = item;
         }

         }*/
      }
    }

  }


  timestampToUTCTime(_timestamp) {
    let date = new Date(_timestamp - 8 * 60 * 60 * 1000);//GMT 转UTC 减8
    let y = "" + date.getFullYear();
    let month = "" + (date.getMonth() + 1);
    let d = "" + date.getDate();
    let h = "" + (date.getHours());
    let minutes = "" + date.getMinutes();
    let s = "" + date.getSeconds();
    if (month.length < 2) {
      month = "0" + month;
    }
    if (d.length < 2) {
      d = "0" + d;
    }
    if (h.length < 2) {
      h = "0" + h;
    }
    if (minutes.length < 2) {
      minutes = "0" + minutes;
    }
    if (s.length < 2) {
      s = "0" + s;
    }
    let yymmddhhmmss = "" + y + month + d + h + minutes + s;
    let yymmdd = "" + y + month + d;
    console.log(_timestamp, yymmdd, yymmddhhmmss, date);
    return {yymmddhhmmss: yymmddhhmmss, yymmdd: yymmdd}
  }
}

RecordInfoMatch.prototype.RECORD_INFO_MATCH_COMPLETE = RecordInfoMatch.RECORD_INFO_MATCH_COMPLETE = 'recordInfoMatchComplete';//录制数据匹配完成
export default new RecordInfoMatch;