EasyNVR网页Chrome无插件播放摄像机视频功能二次开发之云台控制接口示例代码

转自: https://blog.csdn.net/xiejiashu/article/details/90083568

 

 

版权声明:本文为EasyDarwin开源社区原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiejiashu/article/details/90083568
随着多媒体技术和网络通信技术的迅速发展,视频监控技术在电力系统、电信行业、工业监控、工地、城市交通、水利系统、社区安防等领域得到越来越广泛的应用。摄像头直播视频监控通过网络直接连接,可达到的世界任何角落,并能够通过控制云台、存储视频监控音视频,对现场远程运维,实现随时随地想看就看的安防需求。

背景需求
摄像机云台控制在摄像机当中很常见,摄像机能将当前状态下云台的水平角度、倾斜角度和摄像机镜头焦距等位置参数存储到设备中,需要时可以迅速调用这些参数并将云台和摄像头调整至该位置。 摄像机只要支持Onvif协议进行和第三方软件或设备对接,大部分都能进行远程控制。EasyNVR支持Onvif协议的设备云台控制,能实现和设备的实时数据传输及控制。

今天主要介绍通过EasyNVR接口二次开发,将云台控制及实时直播功能集成在自己的原有的web业务系统上。
demo效果如下:


demo是通过vue-cli脚手架搭建起来,简单说一下,目录结构


对easy-player不了解的这是播放器插件地址可以参看(https://www.npmjs.com/package/easy-player)

这里主要讲解一下App.vue内容文件

   <template>
  <div id="app">
    <!-- 测试鉴权 如果鉴权已关闭请忽略 -->
    <div class="div-btn">
      <el-button-group>
        <el-button size="mini" type="success" @click="login">测试登录</el-button>
        <el-button size="mini" type="success" @click="loginout">测试退出</el-button>
        <el-button size="mini" type="success" @click="testapi">测试鉴权</el-button>
      </el-button-group>
    </div>
    <el-row>
      <!-- 播放窗口组件 -->
      <el-col :span="12">
        <EasyPlayer :videoUrl="videoUrl" fluent autoplay live stretch></EasyPlayer>
        <el-input v-model="input" placeholder="请输入播放地址接口" size="mini"></el-input>
        <p>列如:http://127.0.0.1:10800/api/v1/getchannelstream?channel=1&protocol=RTMP</p>
        <el-button class="player-button" size="mini" type="success" @click="player">播放</el-button>
      </el-col>
      <!-- 云台控制组件 -->
      <el-col :span="12">
          <div class="control-box">
            <!-- 云台控制按钮列表 -->
            <span @click="testControl('zoomin')"><i class="el-icon-circle-plus-outline"></i></span>
            <span @click="testControl('up')"><i class="el-icon-arrow-up"></i></span>
            <span @click="testControl('zoomout')"><i class="el-icon-remove-outline"></i></span>
            <span @click="testControl('left')"><i class="el-icon-arrow-left"></i></span>
            <span @click="testControl('stop')">停止</span>
            <span @click="testControl('right')"><i class="el-icon-arrow-right"></i></span>
            <span></span>
            <span @click="testControl('down')"><i class="el-icon-arrow-down"></i></span>
            <span></span>
          </div>
      </el-col>
    </el-row>
  </div>
</template>
    <script>
      import md5 from "md5"; //引入md加密密码传给服务端,这里默认是admin *修改在103行*
      import EasyPlayer from "easy-player"
      export default {
        data() {
          return {
            videoUrl:'',                // 这里定义一个变量用来保存视频流地址
            input:'',                   // 接收用户的接口地址
            timer: 0,                   // 定时器用来保活接口
            channels: '',               // 保存接口地址通道地址
            protocols: ''               // 保存接口地址视频类型
          }
        },
        components:{
          EasyPlayer
        },
        mounted() {},
        methods: {
          player() { // 当输入完接口地址按下播放会执行这个函数
            if(!this.input){
              this.$message.error('请输入接口地址!');
            }else{
              let strs = this.input.split('?')[1].split('&')
              for (const iterator of strs) {
                if (iterator.indexOf('channel') != -1) this.channels = parseInt(iterator.split('=')[1])
                if (iterator.indexOf('protocol') != -1) this.protocols = iterator.split('=')[1]
              }
              this.play() //当player函数接收到可用的地址执行play函数
            }
          },
          play() { //play函数会向服务端发送请求对应的通道及视频类型
            this.$axios.get('/api/v1/getchannelstream', {
                params: {
                  channel: this.channels,
                  protocol: this.protocols
                }
              })
              
              .then((response) => { //请求成功服务端会返回对应的通道的视频流地址把返回的地址传给之前定义videoUrl 就可以播放视频但是视频播放一会就会停止,需要保活接口下面创建一个定时器(注意:保活只是在按需的情况下使用)
                this.videoUrl = response.data.EasyDarwin.Body.URL
                this.timer = setInterval(() => { //当请求成功定时器打开每30秒向服端端发送一下请求告诉服务端客户端需要播放视频,不然服务端就会停止向设备端拉取视频。
                  this.touchStream();
                }, 30 * 1000);
                if(!response.data.EasyDarwin.Body.URL)this.$message.error('播放失败,检查接口是否正确或者通道是否启用!');
              })
              .catch((error) => {
                let { status } = error.response
                if (status == 401) Message.error('token值无效,请重新登录')
              });
          },
          touchStream() { //touchStream用来调取保活接口
            this.$axios.get('/api/v1/touchchannelstream', {
                params: {
                  channel: this.channels,
                  protocol: this.protocols
                }
              })
              .then((response) => {
                this.videoUrl = response.data.EasyDarwin.Body.URL
                if(!response.data.EasyDarwin.Body.URL)this.$message.error('播放失败!');
              })
              .catch((error) => {
                let { status } = error.response
                if (status == 401) Message.error('token值无效,请重新登录')
              });
          },
          login() { //测试登录
            this.$axios.get('/api/v1/login', {
                params: {
                  username: "admin",
                  password: md5("admin")
                }
              })
              .then((response) => {
                this.$message({
                  message: '恭喜你,登录成功!',
                  type: 'success'
                });
              })
              .catch((error) => {
                this.$message.error('用户名或密码错误,登录失败!');
              });
          },
          loginout() { //测试推出
            this.$axios.get('/api/v1/logout')
              .then((response) => {
                this.$message({
                  message: '成功退出!',
                  type: 'success'
                });
              })
              .catch((error) => {
                console.log(error)
              });
          },
          
          testapi() {   //测试接口鉴权是否生效
            this.$axios.get('/api/v1/getchannelsconfig', {
                params: {
                  start: 0,
                  limit: 1
                }
              })
              .then((response) => {
                this.$message({
                  message: '鉴权成功!',
                  type: 'success'
                });
              })
              .catch((error) => {
                this.$message.error('鉴权失败!');
              });
          },
          testControl(data) {  // testControl里的data是接收云台控制组件的里按钮传递的参数。
            this.$axios.get('/api/v1/ptzcontrol', {// 调取云台接口地址
                params: {
                  channel: this.channelNum,     // 调取对应的设备通道地址
                  command: data                 // 调取云台接口的控制参数
                }
              })
              .then((response) => {
                console.log(response)
              })
              .catch((error) => {
                console.log(error)
              });
          }
        }
      }
    </script>
    
    <style lang="scss">
      #app {
        font-family: 'Avenir', Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        // text-align: center;
        color: #2c3e50;
      }
      .el-row, .div-btn{
        max-width: 800px;
        margin: auto;
      }
      .div-btn {
        padding: 5px 0;
      }
      .el-col {
        min-height: 300px;
        // border: 1px pink solid
      }
      .el-input {
        padding: 5px;
        box-sizing: border-box;
      }
      .player-button {
        margin: 5px;
        width: 100%;
      }
      .control-box {
        width: 180px;
        height: 180px;
        margin: 50px;
        span {
          display: inline-block;
          text-align: center;
          float: left;
          width: 60px;
          height: 60px;
          padding: 5px;
          border-radius: 50%;
          box-sizing: border-box;
          // border: 1px solid #ccc;
          line-height: 50px;
          cursor: pointer;
          &:hover {
            background-color: #67C23A;
             border: none;
          }
        }
      }
      p {
        font-size: 12px;
      }
    </style>


项目仓库地址(https://github.com/EasyNVR/EasyNVR/tree/master/EasyNVR_apidemo/apidemo)
下载项目到本地到目录下安装demo需要的依赖
npm install
运行项目
npm run serve
打包
npm run build
注意:需要摄像头支持云台控制。

EasyNVR部署架构


单点内网


单点公网


多点公网


RTMP推流
EasyNVR应用场景
EasyNVR在互联网安防直播行业已有多年实战经验,通过各行业的市场检验已成为一套便捷、安全、覆盖范围广的成熟产品,结合硬件产品,服务于各行各业视频基础建设,同时提供二次开发接口便于企业集成到自己的业务系统中,打造专属于自己的互联网视频监控平台。

手机看家


航空监控


景区监控
关于EasyNVR
EasyNVR是一款拥有完整、自主、可控知识产权,同时又能够具备软硬一体功能的安防互联网化流媒体服务器,能够通过简单的网络摄像机通道配置,将传统监控行业里面的高清网络摄像机IP Camera、NVR等具有RTSP、Onvif协议输出的设备接入到EasyNVR,EasyNVR能够将这些视频源的音视频数据进行拉取,转换为RTMP/HLS,进行全平台终端H5直播(Web、Android、iOS),并且EasyNVR能够将视频源的直播数据对接到第三方CDN网络,实现互联网级别的直播分发。详情可访问EasyNVR官网:http://www.easynvr.com


—本文转自EasyNVR官方技术博客:https://blog.csdn.net/EasyNVR
--------------------- 
作者:xiejiashu 
来源:CSDN 
原文:https://blog.csdn.net/xiejiashu/article/details/90083568 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值