panlinlin
2021-05-07 bd570d167be9671f46ec27568b2a591713897323
优化直播流点播流程, 添加流代理接口添加直接关联国标功能
9个文件已修改
174 ■■■■ 已修改文件
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/ParentPlatformList.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/StreamProxyList.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/dialog/StreamProxyEdit.vue 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/dialog/platformEdit.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
@@ -92,10 +92,18 @@
                DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
                GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
                // 不是通道可能是直播流
                if (channel != null || gbStream != null ) {
                if (channel != null && gbStream == null ) {
                    if (channel.getStatus() == 0) {
                        logger.info("通道离线,返回400");
                        responseAck(evt, Response.BAD_REQUEST, "channel [" + channel.getChannelId() + "] offline");
                        return;
                    }
                    responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
                }else if(channel == null && gbStream != null){
                    Boolean streamReady = zlmrtpServerFactory.isStreamReady(gbStream.getApp(), gbStream.getStream());
                    if (!streamReady) {
                        logger.info("[ app={}, stream={} ]通道离线,返回400",gbStream.getApp(), gbStream.getStream());
                        responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
                        return;
                    }
                    responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
@@ -240,34 +248,30 @@
                    // 写入redis, 超时时回复
                    redisCatchStorage.updateSendRTPSever(sendRtpItem);
                    // 检测直播流是否在线
                    Boolean streamReady = zlmrtpServerFactory.isStreamReady(gbStream.getApp(), gbStream.getStream());
                    if (streamReady) {
                        sendRtpItem.setStatus(1);
                        redisCatchStorage.updateSendRTPSever(sendRtpItem);
                        // TODO 添加对tcp的支持
                        ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
                        StringBuffer content = new StringBuffer(200);
                        content.append("v=0\r\n");
                        content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
                        content.append("s=Play\r\n");
                        content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
                        content.append("t=0 0\r\n");
                        content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n");
                        content.append("a=sendonly\r\n");
                        content.append("a=rtpmap:96 PS/90000\r\n");
                        content.append("y="+ ssrc + "\r\n");
                        content.append("f=\r\n");
                    sendRtpItem.setStatus(1);
                    redisCatchStorage.updateSendRTPSever(sendRtpItem);
                    // TODO 添加对tcp的支持
                    ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
                    StringBuffer content = new StringBuffer(200);
                    content.append("v=0\r\n");
                    content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
                    content.append("s=Play\r\n");
                    content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
                    content.append("t=0 0\r\n");
                    content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n");
                    content.append("a=sendonly\r\n");
                    content.append("a=rtpmap:96 PS/90000\r\n");
                    content.append("y="+ ssrc + "\r\n");
                    content.append("f=\r\n");
                        try {
                            responseAck(evt, content.toString());
                        } catch (SipException e) {
                            e.printStackTrace();
                        } catch (InvalidArgumentException e) {
                            e.printStackTrace();
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    try {
                        responseAck(evt, content.toString());
                    } catch (SipException e) {
                        e.printStackTrace();
                    } catch (InvalidArgumentException e) {
                        e.printStackTrace();
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java
@@ -16,6 +16,7 @@
    private boolean enable;
    private boolean enable_hls;
    private boolean enable_mp4;
    private String platformGbId;
    public String getType() {
        return type;
@@ -114,4 +115,11 @@
    }
    public String getPlatformGbId() {
        return platformGbId;
    }
    public void setPlatformGbId(String platformGbId) {
        this.platformGbId = platformGbId;
    }
}
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -59,11 +59,7 @@
                JSONArray tracks = mediaJSON.getJSONArray("tracks");
                streamInfo = getStreamInfoByAppAndStream(app, stream, tracks);
            }
        }
        return streamInfo;
    }
}
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -1,9 +1,11 @@
package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.service.IGbStreamService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
@@ -13,6 +15,9 @@
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
 * 视频代理业务
@@ -38,6 +43,9 @@
    @Autowired
    private PlatformGbStreamMapper platformGbStreamMapper;
    @Autowired
    private IGbStreamService gbStreamService;
    @Override
    public String save(StreamProxyItem param) {
@@ -46,6 +54,7 @@
                param.getStream() );
        param.setDst_url(dstUrl);
        StringBuffer result = new StringBuffer();
        boolean streamLive = false;
        // 更新
        if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) {
            if (videoManagerStorager.updateStreamProxy(param)) {
@@ -62,9 +71,11 @@
        }else { // 新增
            if (videoManagerStorager.addStreamProxy(param)){
                result.append("保存成功");
                streamLive = true;
                if (param.isEnable()) {
                    JSONObject jsonObject = addStreamProxyToZlm(param);
                    if (jsonObject == null) {
                        streamLive = false;
                        result.append(", 但是启用失败,请检查流地址是否可用");
                        param.setEnable(false);
                        videoManagerStorager.updateStreamProxy(param);
@@ -73,6 +84,15 @@
            }
        }
        if (param.getPlatformGbId() != null && streamLive) {
            List<GbStream> gbStreams = new ArrayList<>();
            gbStreams.add(param);
            if (gbStreamService.addPlatformInfo(gbStreams, param.getPlatformGbId())){
                result.append(",  关联国标平台[ " + param.getPlatformGbId() + " ]成功");
            }else {
                result.append(",  关联国标平台[ " + param.getPlatformGbId() + " ]失败");
            }
        }
        return result.toString();
    }
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
@@ -75,10 +75,15 @@
    @ResponseBody
    public WVPResult del(String app, String stream){
        logger.info("移除代理: " + app + "/" + stream);
        streamProxyService.del(app, stream);
        WVPResult<Object> result = new WVPResult<>();
        result.setCode(0);
        result.setMsg("success");
        if (app == null || stream == null) {
            result.setCode(400);
            result.setMsg(app == null ?"app不能为null":"stream不能为null");
        }else {
            streamProxyService.del(app, stream);
            result.setCode(0);
            result.setMsg("success");
        }
        return result;
    }
web_src/src/components/ParentPlatformList.vue
@@ -156,7 +156,7 @@
      this.$axios({
          method: 'get',
    url:`/api/platform/query/${that.count}/${that.currentPage}`
          url:`/api/platform/query/${that.count}/${that.currentPage}`
      }).then(function (res) {
        that.total = res.data.total;
        that.platformList = res.data.list;
web_src/src/components/StreamProxyList.vue
@@ -33,6 +33,14 @@
                        </template>
                    </el-table-column>
                    <el-table-column prop="gbId" label="国标编码" width="180" align="center" show-overflow-tooltip/>
          <el-table-column label="启用" width="120" align="center">
            <template slot-scope="scope">
              <div slot="reference" class="name-wrapper">
                <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
                <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
              </div>
            </template>
          </el-table-column>
                    <el-table-column label="转HLS" width="120" align="center">
                        <template slot-scope="scope">
                        <div slot="reference" class="name-wrapper">
@@ -49,14 +57,7 @@
                        </div>
                        </template>
                    </el-table-column>
                    <el-table-column label="启用" width="120" align="center">
                        <template slot-scope="scope">
                        <div slot="reference" class="name-wrapper">
                            <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
                            <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
                        </div>
                        </template>
                    </el-table-column>
                    <el-table-column label="操作" width="360" align="center" fixed="right">
                        <template slot-scope="scope">
web_src/src/components/dialog/StreamProxyEdit.vue
@@ -56,6 +56,22 @@
                  <el-option label="组播" value="2"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="国标平台">
                <el-select
                  v-model="proxyParam.platformGbId"
                  style="width: 100%"
                  placeholder="请选择国标平台"
                >
                  <el-option
                    v-for="item in platformList"
                    :key="item.name"
                    :label="item.name"
                    :value="item.serverGBId">
                    <span style="float: left">{{ item.name }}</span>
                    <span style="float: right; color: #8492a6; font-size: 13px">{{ item.serverGBId }}</span>
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="其他选项">
                <div style="float: left;">
                  <el-checkbox label="启用" v-model="proxyParam.enable" ></el-checkbox>
@@ -106,6 +122,27 @@
      isLoging: false,
      dialogLoading: false,
      onSubmit_text: "立即创建",
      platformList: [{
          id: 1,
          enable: true,
          name: "141",
          serverGBId: "34020000002000000001",
          serverGBDomain: "3402000000",
          serverIP: "192.168.1.141",
          serverPort: 15060,
          deviceGBId: "34020000002000000001",
          deviceIp: "192.168.1.20",
          devicePort: "5060",
          username: "34020000002000000001",
          password: "12345678",
          expires: "300",
          keepTimeout: "60",
          transport: "UDP",
          characterSet: "GB2312",
          ptz: false,
          rtcp: false,
          status: true,
      }],
      proxyParam: {
          name: null,
          type: "default",
@@ -120,6 +157,7 @@
          enable: true,
          enable_hls: true,
          enable_mp4: false,
          platformGbId: null,
      },
      rules: {
@@ -140,6 +178,17 @@
      if (proxyParam != null) {
        this.proxyParam = proxyParam;
      }
      let that = this;
      this.$axios({
        method: 'get',
        url:`/api/platform/query/10000/0`
      }).then(function (res) {
        that.platformList = res.data.list;
      }).catch(function (error) {
        console.log(error);
      });
    },
    onSubmit: function () {
      console.log("onSubmit");
web_src/src/components/dialog/platformEdit.vue
@@ -105,9 +105,6 @@
        callback(new Error("请输入设备国标编号"));
      } else {
        var exit = await this.deviceGBIdExit(value);
        console.log(exit);
        console.log(exit == "true");
        console.log(exit === "true");
        if (exit) {
          callback(new Error("设备国标编号已存在"));
        } else {