webRtc-streamer简单使用-备份

公司业务需求,在前端实现海康摄像头的实时播放,参考文档资料后决定使用webrtc-streamer来实现rtsp流的播放,在此备份一下,也希望能够帮助到有需要的友友。

准备工具

1.这里使用的是webrtc-streamer来对rtsp流视频进行转码,从而实现前端界面的播放。因为开始接手项目的时候公司没有流媒体服务器,所以是在本地测试,对本地cpu有一定的压力。你也可以将webrtc打包到docker镜像里运行。

https://wws.lanzouy.com/inBMK08uv02h (webrtc-streamer链接)

2.我这里使用的是videojs包,当然你也可以直接用原生的video标签进行播放。下面附上相关依赖。

{
  "name": "videojsdemo",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "chokidar": "^3.5.3",
    "core-js": "^3.23.4",
    "video.js": "^7.18.1",
    "videojs-contrib-hls": "^5.15.0",
    "vue": "^2.6.14",
    "vue-baidu-map": "^0.21.22",
    "vue-router": "^3.5.1",
    "vue-webrtc": "^2.0.0",
    "vueui": "^0.1.4",
    "vuex": "^3.6.2"
  },
  "devDependencies": {
    "@babel/core": "^7.12.16",
    "@babel/eslint-parser": "^7.12.16",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-eslint": "~5.0.0",
    "@vue/cli-plugin-router": "~5.0.0",
    "@vue/cli-plugin-vuex": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "eslint": "^7.32.0",
    "eslint-plugin-vue": "^8.0.3",
    "vue-template-compiler": "^2.6.14"
  }
}

一、使用步骤

1.这是我封装的视频播放的组件,可以按照需求自行修改。

<template>
  <div>
    <el-row>
      <el-col :span="24">
        <!-- <map-video :showV="videoShow" :rtspIp="rtspIp"></map-video> -->
        <div style="height: 40vh">
          <!-- 
            this.hackReset = false;//销毁组件
            this.$nextTick(() => {
            this.hackReset = true;//重建组件
            });
          -->
          <video
            :id="videoID"
            class="video-js"
            style="object-fit: fill"
            controls
            autoplay
            autobuffer
            muted
            preload="auto"
          ></video>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import "video.js/dist/video-js.css";
import videojs from "video.js";
export default {
  name: "TanchengkjWebDialogCom",

  props: {
    videoID: {
      type: String,
      default() {
        return "videoID";
      },
    },
    rtspIp: {
      type: String,
      default() {
        return "";
      },
    },
    videoShow: {
      type: Boolean,
      default() {
        return false;
      },
    },
    videoPlayName: {
      type: String,
      default() {
        return "";
      },
    },
  },

  data() {
    return {
      dialogFromVisible: this.videoShow,
      inDate: "",
      t2: null,
      getUrl: localStorage.getItem("getUrl"),
      player: null,
      webRtcServer: null,
      webRtcList: [],
      playerList: [],
      videoSeting: {
        language: "zh-CN",
        autoplay: true, // true/false 播放器准备好之后,是否自动播放 【默认false】
        controls: true, // /false 是否拥有控制条 【默认true】,如果设为false ,那么只能通过api进行控制了。也就是说界面上不会出现任何控制按钮
        /* height: 100, // 视频容器的高度,字符串或数字 单位像素 比如: height:300 or height:‘300px‘
         width: 100, // 视频容器的宽度, 字符串或数字 单位像素*/
        loop: false, // /false 视频播放结束后,是否循环播放
        muted: true, // /false 是否静音
        poster: "", // 播放前显示的视频画面,播放开始之后自动移除。通常传入一个URL
        preload: "auto", // 预加载   ‘auto‘ 自动   ’metadata‘ 元数据信息 ,比如视频长度,尺寸等 ‘none‘ 不预加载任何数据,直到用户开始播放才开始下载
        bigPlayButton: true,
      },
    };
  },
  watch: {
    videoShow: {
      immediate: true,
      handler: function (value) {
        this.dialogFromVisible = value;
        if (value == false) {
          console.log("视频关闭了!");
          // this.playerList[0].pause();
          // this.webRtcList[0].webRtcServer.disconnect();
        } else {
          this.$forceUpdate();
          console.log("输出一下rtsp:", this.rtspIp);
          setTimeout(() => {
            this.getWebRtc();
          }, 1000);
        }
      },
    },
  },

  mounted() {
    let that = this;
    this.initNDate();
    let procedure1 = new Promise(function (resolve, reject) {
      setTimeout(function () {
        console.log("1执行crtWebRtc成功!");
        that.crtWebRtc();
        resolve();
      });
    });

    let procedure2 = new Promise(function (resolve, reject) {
      setTimeout(function () {
        console.log("2执行getvideo成功!");
        that.getVideo();
        resolve();
      });
    });

    let procedure3 = new Promise(function (resolve, reject) {
      setTimeout(function () {
        console.log("3执行getWebRtc成功!");
        that.getWebRtc();
        resolve();
      });
    });

    procedure1
      .then((data) => {
        return procedure2;
      })
      .then((data) => {
        return procedure3;
      });

    // console.log("mounted输出rtspip:", this.rtspIp);
    // console.log("mounted输出videoID:", this.videoID);
    // console.log("mounted输出getUrl:", this.getUrl);
  },
  created() {},

  methods: {
    /*设置当前系统时间*/
    initNDate: function () {
      this.t2 = setInterval(() => {
        this.inDate = new Date().toLocaleString();
      }, 1000);
    },

    getVideo() {
      let that = this;
      this.playerList[0] = videojs(
        this.videoID,
        this.videoSeting,
        function onPlayerReady() {
          videojs.log("Your player is ready!");
          this.on("loadstart", function () {
            console.log("开始请求数据 ");
          });
          this.on("progress", function () {
            console.log("正在请求数据 ");
          });
          this.on("loadedmetadata", function () {
            console.log("获取资源长度完成 ");
          });
          this.on("canplaythrough", function () {
            console.log("视频源数据加载完成");
          });
          this.on("waiting", function () {
            console.log("等待数据");
          });
          this.on("play", function () {
            console.log("视频开始播放");
          });
          this.on("playing", function () {
            console.log("视频播放中");
          });
          this.on("pause", function () {
            console.log("视频暂停播放");
            that.webRtcList[0].webRtcServer.disconnect();
          });
          this.on("ended", function () {
            console.log("视频播放结束");
          });
          this.on("error", function () {
            console.log("加载错误");
          });
          this.on("seeking", function () {
            console.log("视频跳转中");
          });
          this.on("seeked", function () {
            console.log("视频跳转结束");
          });
          this.on("ratechange", function () {
            console.log("播放速率改变");
          });
          this.on("timeupdate", function () {
            console.log("播放时长改变");
          });
          this.on("volumechange", function () {
            console.log("音量改变");
          });
          this.on("stalled", function () {
            console.log("网速异常");
          });
        }
      );
      this.playerList.push(this.player);
      console.log("playerList", this.playerList);
      console.log("id_", this.playerList[0].id_);
    },
    crtWebRtc() {
      console.log("webRtcList:", this.webRtcList);
      for (const item of this.webRtcList) {
        if (this.videoID == item.name) {
          return;
        }
      }
      console.log("进来了开始初始化webRtc模块:", this.videoID);
      this.webRtcServer = new WebRtcStreamer(
        this.videoID,
        // "http://192.168.1.166:8000"
        this.getUrl
      );
      let s = {};
      s.name = this.videoID;
      s.webRtcServer = this.webRtcServer;
      this.webRtcList.push(s);
      console.log("this.webrtc哈", this.webRtcList);
    },
    getWebRtc() {
      console.log("将rtspip传递给webRtcServer.connect:", this.rtspIp);
      console.log("打印:webrtclist", this.webRtcList);
      this.webRtcList[0].webRtcServer.connect(this.rtspIp);
      // for (const item of this.webRtcList) {
      //   if (this.videoID == item.name) {
      //     return;
      //   }
      //   item.webRtcServer.connect(this.rtspIp);
      // }
    },
  },
  beforeDestroy() {
    console.log("运行销毁前生命周期事件");
    // this.webRtcList[0].webRtcServer.disconnect();
    // if (this.player) {
    // this.playerList[0].dispose();
    // }
  },
};
</script>

<style scoped>
.lf20 {
  margin-left: 20px;
}

/* // 覆盖层元素增加可穿透点击事件 */
.el-dialog__wrapper {
  pointer-events: none;
}

/* // 弹窗层元素不可穿透点击事件(不影响弹窗层元素的点击事件) */
.el-dialog {
  pointer-events: auto;
}

.el-dialog__title {
  line-height: 24px !important;
  font-size: 15px !important;
  color: #303133;
}

.el-dialog__header {
  padding: 5px 5px 0px 5px !important;
  text-align: left;
}

.el-dialog__headerbtn {
  position: absolute;
  top: 5px !important;
  right: 5px !important;
  padding: 0;
  background: 0 0;
  border: none;
  outline: 0;
  cursor: pointer;
  font-size: 16px;
}

.el-dialog__body {
  padding: 2px !important;
  color: #606266;
  font-size: 14px;
  word-break: break-all;
  height: 40vh;
  overflow-y: auto;
}

.el-divider--horizontal {
  display: block;
  height: 1px;
  width: 100%;
  margin: 0px 0 !important;
}

.el-menu:hover {
  opacity: 1 !important;
}

.ve-line {
  margin-left: 10px;
  padding-top: 20px;
  color: #fff4fd;
  width: 540px !important;
}
.el-row {
  margin-bottom: 2px;
  &:last-child {
    margin-bottom: 0;
  }
}
.el-col {
  border-radius: 4px;
}
.bg-purple-dark {
  background: #99a9bf;
}
.bg-purple {
  background: #d3dce6;
}
.bg-purple-light {
  background: #e5e9f2;
}
.grid-content {
  border-radius: 4px;
  min-height: 36px;
  height: 230px;
}
.row-bg {
  background-color: #f9fafc;
}
.cell-v {
  display: flex;
  flex-direction: column;
  height: 30vh;
}
.player {
  height: 100%;
}
.bk-button-group {
  color: #00a0e9;
}

.video-js {
  width: 100%;
  height: 100%;
}

.video-js .vjs-big-play-button {
  top: 50%;
  left: 50%;
  margin-left: -1.5em;
  margin-top: -1em;
}
.vjs-loading-spinner:before,
.vjs-loading-spinner:after {
  content: "";
  position: absolute;
  margin: -6px;
  -webkit-box-sizing: inherit;
  box-sizing: inherit;
  width: inherit;
  height: inherit;
  border-radius: inherit;
  opacity: 1;
  border: inherit;
  border-color: transparent;
  border-top-color: white;
  display: none;
}
</style>

二、使用步骤

###1.其实使用webrtc来实现rtsp流视频的播放很简单,只需要注意以下几点:
####1.首先是初始化webrtc服务
打开webrtc-streamer.exe我们可以看到,它这里监听的是8000端口
所以后续我们在初始化webrtcserver的时候需要将你运行项目的地址与8000端口拼接

这边的"video"是video标签的id,因为id是唯一标识

####2.初始化好了webrtc服务后是初始化video播放器了

methods: {
    playVideo() {
      this.webRtcServer.connect(this.rtspUrl);
      // 初始化播放器
      this.getVideo();
    },
    getVideo() {
      //this.videoSeting
      let that = this;
      this.player = videojs(
        "video",
        this.videoSeting,
        function onPlayerReady() {
          videojs.log("Your player is ready!");
          this.on("loadstart", function () {
            console.log("开始请求数据 ");
          });
          this.on("progress", function () {
            console.log("正在请求数据 ");
          });
          this.on("loadedmetadata", function () {
            console.log("获取资源长度完成 ");
          });
          this.on("canplaythrough", function () {
            console.log("视频源数据加载完成");
          });
          this.on("waiting", function () {
            console.log("等待数据");
          });
          this.on("play", function () {
            console.log("视频开始播放");
          });
          this.on("playing", function () {
            console.log("视频播放中");
          });
          this.on("pause", function () {
            console.log("视频暂停播放");
            that.webRtcServer.disconnect();
          });
          this.on("ended", function () {
            console.log("视频播放结束");
          });
          this.on("error", function () {
            console.log("加载错误");
          });
          this.on("seeking", function () {
            console.log("视频跳转中");
          });
          this.on("seeked", function () {
            console.log("视频跳转结束");
          });
          this.on("ratechange", function () {
            console.log("播放速率改变");
          });
          this.on("timeupdate", function () {
            console.log("播放时长改变");
          });
          this.on("volumechange", function () {
            console.log("音量改变");
          });
          this.on("stalled", function () {
            console.log("网速异常");
          });
        }
      );
    },
  },


这里的video同样指的是video播放器的id,与初始化播放器是一对一的关系
这里我将整个代码都贴上来吧,以免有友友看不太清楚

<template>
  <div class="container">
    <div class="control_1">
      <a>input http server:</a
      ><input type="text" v-model="httpServer" placeholder="请输入服务端地址" />
    </div>
    <div class="control_2">
      <a>input rtsp url:</a
      ><input type="text" v-model="rtspUrl" placeholder="请输入rtsp流地址" />
    </div>
    <button style="margin-top: 15px" @click="playVideo">
      准备好了点击播放视频
    </button>
    <div class="videoPlay">
      <video
        id="video"
        class="video-js"
        style="object-fit: fill; width: 500px; height: 500px"
        controls
        autoplay
        autobuffer
        muted
        preload="auto"
      ></video>
    </div>
  </div>
</template>

<script>
import "video.js/dist/video-js.css";
import videojs from "video.js";
export default {
  name: "TailwindCSSDaisyUIHomeView",

  data() {
    return {
      httpServer: "",
      rtspUrl: "",
      player: null,
      webRtcServer: null,
      videoSeting: {
        language: "zh-CN",
        autoplay: true, // true/false 播放器准备好之后,是否自动播放 【默认false】
        controls: true, // /false 是否拥有控制条 【默认true】,如果设为false ,那么只能通过api进行控制了。也就是说界面上不会出现任何控制按钮
        /* height: 100, // 视频容器的高度,字符串或数字 单位像素 比如: height:300 or height:‘300px‘
         width: 100, // 视频容器的宽度, 字符串或数字 单位像素*/
        loop: false, // /false 视频播放结束后,是否循环播放
        muted: true, // /false 是否静音
        poster: "", // 播放前显示的视频画面,播放开始之后自动移除。通常传入一个URL
        preload: "auto", // 预加载   ‘auto‘ 自动   ’metadata‘ 元数据信息 ,比如视频长度,尺寸等 ‘none‘ 不预加载任何数据,直到用户开始播放才开始下载
        bigPlayButton: true,
      },
    };
  },

  mounted() {
    var a = `${window.location.href}`;
    var b = a.split(":");
    this.httpServer = `${b[0]}:${b[1]}:8000/`;
    console.log("httpServer", this.httpServer);
    // 初始化webrec服务
    this.webRtcServer = new WebRtcStreamer("video", this.httpServer);
  },

  methods: {
    playVideo() {
      this.webRtcServer.connect(this.rtspUrl);
      // 初始化播放器
      this.getVideo();
    },
    getVideo() {
      //this.videoSeting
      let that = this;
      this.player = videojs(
        "video",
        this.videoSeting,
        function onPlayerReady() {
          videojs.log("Your player is ready!");
          this.on("loadstart", function () {
            console.log("开始请求数据 ");
          });
          this.on("progress", function () {
            console.log("正在请求数据 ");
          });
          this.on("loadedmetadata", function () {
            console.log("获取资源长度完成 ");
          });
          this.on("canplaythrough", function () {
            console.log("视频源数据加载完成");
          });
          this.on("waiting", function () {
            console.log("等待数据");
          });
          this.on("play", function () {
            console.log("视频开始播放");
          });
          this.on("playing", function () {
            console.log("视频播放中");
          });
          this.on("pause", function () {
            console.log("视频暂停播放");
            that.webRtcServer.disconnect();
          });
          this.on("ended", function () {
            console.log("视频播放结束");
          });
          this.on("error", function () {
            console.log("加载错误");
          });
          this.on("seeking", function () {
            console.log("视频跳转中");
          });
          this.on("seeked", function () {
            console.log("视频跳转结束");
          });
          this.on("ratechange", function () {
            console.log("播放速率改变");
          });
          this.on("timeupdate", function () {
            console.log("播放时长改变");
          });
          this.on("volumechange", function () {
            console.log("音量改变");
          });
          this.on("stalled", function () {
            console.log("网速异常");
          });
        }
      );
    },
  },
};
</script>

<style>
.control_1 {
  display: block;
  /* margin-top: 20px; */
}
.control_2 {
  display: block;
  margin-top: 15px;
}
.videoPlay {
  width: 500px;
  height: 500px;
  margin: 15px auto;
}
.video-js {
  width: 100%;
  height: 100%;
}

.video-js .vjs-big-play-button {
  top: 50%;
  left: 50%;
  margin-left: -1.5em;
  margin-top: -1em;
}
.vjs-loading-spinner:before,
.vjs-loading-spinner:after {
  content: "";
  position: absolute;
  margin: -6px;
  -webkit-box-sizing: inherit;
  box-sizing: inherit;
  width: inherit;
  height: inherit;
  border-radius: inherit;
  opacity: 1;
  border: inherit;
  border-color: transparent;
  border-top-color: white;
  display: none;
}
</style>

这个案例是通过input的双向绑定原理,将当前项目的url与8000端口拼接,然后输入rtsp流点击播放进行播放。
成功截图

总结

第一次写,见谅
可能写得不太好
如果有啥问题,可以留言交流

评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值