• 国标GB28181流媒体服务器支持多分屏操作


    最近感觉使用国标协议的开发者有很多,我们国标GB28181流媒体服务器提供流转发服务,负责将GB28181设备/平台推送的PS流转成ES流,然后提供RTSP、RTMP、FLV、HLS多种格式进行分发,实现web浏览器、手机浏览器、微信等各种终端无插件播放。

    之前有开发者说我们国标GB28181的流媒体服务器需要查看视频的时候,只能单独查看一路视频,想同时查看多路视频的时候,就不是很方便操作。

    原本的界面如下:

    我们的研发人员也对这个多分屏的问题进行了研究,在前几天实现了国标GB28181流媒体服务器的多分屏操作(我由衷觉得我的研发部同事们都很厉害啊!),界面如下图:

    以下是实现代码,大家可以参考一下:

    <template>
      <div>
        <div class="screen-main">
          <el-row>
            <el-col :xs="24" :sm="24" :md="24" :lg="4" :xl="4">
              <div class="screen-tree" @scroll="scrollEvent">
                <span class="screen-tree-title">设备列表</span>
                <el-tree
                  v-loading="loading"
                  :data="terrData"
                  node-key="ID"
                  default-expand-all
                  :props="{children: 'Children', label: 'Name'}"
                >
                  <span slot-scope="{ node, data }" class="custom-tree-node">
                    <div :class="['custom-tree-node', {'private-info': !data.Online&&data.Type===1}, {'private-info': data.ChannelCount===0} ]" :title="data.ID" @click="onSelection(data)">
                      <i :class="['fa', {'private-success': data.Online&&data.Type===1}, { 'fa-video-camera': data.Type===2},{'fa-desktop':data.Type===1} ]" />
                      {{ data.Name?data.Name:data.ID }}
                    </div>
                  </span>
                </el-tree>
              </div>
            </el-col>
            <el-col :xs="24" :sm="24" :md="24" :lg="16" :xl="16">  
            
              <div style="padding-top: 50px;">
                <el-row class="screen-main-player" v-if="isShow">
                  <el-col :xs="24" :sm="colNum[3]" :md="colNum[2]" :lg="colNum[1]" :xl="colNum[0]" v-for="(item, index) in PlayerData" :key="index" :class="[{'active-shadow': indexType===index}]" >  
                    <div class="screen-main-item" @click.stop="indexType=index">
                      <SereenPlayer :DeviceID="item.DeviceID" :ID="item.ID" :Index="index" @index="onIndex" :Radio="radio"/>
                    </div>
                  </el-col>
                </el-row>
              </div>
              <div class="screen-radio">
                <el-radio-group v-model="radio" size="small" @change="getList()"> 
                  <el-radio-button :label="item.type" v-for="(item, index) in radioData" :key="index">{{item.name}}</el-radio-button>
                  <el-radio-button :label="radio"><i class="fa fa-arrows-alt" @click.prevent="fullscreen"></i></el-radio-button>
                </el-radio-group>
              </div>
            </el-col>
          </el-row>
        </div>
      </div>
    </template>
    <script>
    import SereenPlayer from './SereenPlayer'
    export default {
      components: { SereenPlayer },
      data() {
        return {
          indexType: 0,
          terrData: [],
          isShow: true,
          loading: true,
          queryDev: undefined,
          DeviceCount: 0,
          radio: 4,
          PlayerData: [],
          PlayerDataName: '',
          radioData: [
            { type: 1, name: '单屏' },
            { type: 4, name: '四分屏' },
            { type: 9, name: '九分屏' },
            { type: 16, name: '十六分屏' },
            { type: 36, name: '三十六分屏' },
            { type: 64, name: '六十四分屏' },
          ]
        }
      },
      computed: {
        colNum(){
          if (this.radio === 1) {
            return [24,24,24,24]
          } else if (this.radio === 4) {
            return [12,12,12,12]
          }else if (this.radio === 9) {
            return [8,8,12,12]
          }else if (this.radio === 16) {
            return [6,6,12,12]
          }else if (this.radio === 36) {
            return [4,4,12,12]
          }else if (this.radio === 64) {
            return [3,3,12,12]
          }
        }
      },
      created() {
        this.getDeviceList()
      },
      mounted() {
        this.getList()
      },
      methods: {
        scrollEvent(e){
          if(e.currentTarget.scrollTop+e.currentTarget.clientHeight>=e.currentTarget.scrollHeight){
            console.log('t!');
          }
        },
        fullscreen() {
          this.$fullscreen.enter(this.$el.querySelector(`.screen-main-player`), {
              wrap: false
          })
        },
        onIndex(index) {
          this.PlayerData[index].DeviceID = ''
          this.PlayerData[index].ID = ''
        },
        getList() {
          this.isShow = false
          this.indexType = 0
          this.PlayerData = []
          for (let index = 0; index < this.radio; index++) {
            this.PlayerData.push({
              ID: '',
              DeviceID: ''
            })  
          }
          this.isShow = true
        },
        onSelection(data) {
          if (data.Type===1&&data.Online===false) {
            this.$message({
              message: '设备已离线!',
              type: 'warning'
            })
            return
          } 
          if (data.Type===2) {
            if (this.indexType<this.radio) {
              this.PlayerData[this.indexType].DeviceID = data.DeviceID
              this.PlayerData[this.indexType].ID = data.ID
              if ((this.indexType+1)<this.radio) {
                this.indexType++
              }
            } 
            return
          } else {
            if (!data.Online) {
              return
            }
            if (data.Children.length!==0) return
            this.getChannels(data.ID, data)
          }
        },
        getDeviceList() {
          this.loading = true;
          let _this = this;
          $.get("/api/v1/device/list", {
            q: this.queryDev      
          })
          .then(res => {
            _this.DeviceCount = res.DeviceCount
            res.DeviceList.forEach(item => {
              _this.terrData.push({
                Name:item.Name,
                ChannelCount:item.ChannelCount,
                ID:item.ID,
                Online:item.Online,
                Children: [],
                Type: 1,
                Loading: false
              })
            })
          })
          .always(() => {
            this.loading = false;
          })
        },
        getChannels(ID, data) {
          this.loading = true;
          let _this = this
          $.get("/api/v1/device/info", {
            serial: ID
          })
          .then(res => {
            if(res.ChannelCount == 0) {
              _this.$message({
                message: '设备下无通道!',
                type: 'warning'
              })
            }else {
              res.ChannelList.forEach(item => {
               data.Children .push({
                  Name:item.Name,
                  DeviceID:item.DeviceID,
                  SnapURL:item.SnapURL,
                  ID:item.ID,
                  Online: true,
                  Children: [],
                  Type: 2,
                  Loading: false
                })
              })
            }
            this.loading = false;
          })
          .always(() => {
            this.loading = false;
          })
        }
      }
    }
    </script>
    <style lang="less" scoped>
      .screen-radio {
        padding: 20px 15px;
        padding-left: 0;
        padding-bottom: 5px; 
      }
      .screen-tree {
        padding-right: 30px;
        padding-top: 40px;
        min-height: e("calc(100vh - 131px)");
        max-height: e("calc(100vh - 131px)");
        overflow:auto;
        .el-tree {
          background: transparent;
        }
        .screen-tree-title {
          display: block;
          font-size: 16px;
          padding-bottom: 5px;
          padding-left: 22px;
        }
      }
      .screen-main {
        .screen-main-item {
          border: 1px solid #ccc;
        }
      }
      .active-shadow{
        .screen-main-item {
          border: 1px solid red;
        }
      }
    </style>
    <style lang="less">
     .screen-main {
        >.el-row>.el-col {
          padding: 0 !important;
        }
      }
    .fullscreen {
      position: fixed;
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
    }
    .screen-radio .el-radio-button:last-child .el-radio-button__inner{
      border-color: #dcdfe6;
      border-left: 0px;
      box-shadow: none !important;
      background-color: #ffffff;
      color: #606266;
      &:hover {
        color: #00a65a;
      }
    }
    </style>
  • 相关阅读:
    使用Haskell写web
    src/lxml/etree.so: undefined symbol: xmlSchematronSetValidStructuredErrors 解决方案
    CentOS允许某一端口接受外部链接
    windows下的NTP服务
    Huffman树,Huffman编码的实现(C#)
    OpenGL的函数(GLU, GLUT)
    OpenGL的函数(GL)
    GLUT函数说明
    FreeImage使用基础,图像旋转,图像滤波
    Hello PureMVC!!!
  • 原文地址:https://www.cnblogs.com/EasyNVR/p/12867422.html
Copyright © 2020-2023  润新知