前言

主要参考https://blog.csdn.net/qq_39923762/article/details/89149715?spm=1001.2014.3001.5506

我们的项目是在大华摄像机通过流媒体服务器进行拉流的方式进行的,前端调取视频数据只需要通过访问ip就可以获取到了。

cnpm install video.js
cnpm install videojs-contrib-hls --save

main.js中引入css
import ‘video.js/dist/video-js.css’

template页面:

<div v-show='!isError'><video id="videobox" class="video-js vjs-default-skin vjs-big-play-centered vjs-16-9" controls preload="auto" webkit-playsinline="true" playsinline="true" type="application/x-mpegURL" allowsInlineMediaPlayback=YES  webview.allowsInlineMediaPlayback=YES  width='100%' ref='videoRef' x5-video-player-fullscreen="true" :poster="posterSrc" ><source id="sourceBox" :src="videoSrc"><p class="vjs-no-js">不支持播放</p></video>
</div>
<div v-show='isError' class="errorTip"><p>视频出错了!</p></div>
<script>
组件页面引入:
import videojs from 'video.js'
import 'videojs-contrib-hls'
......data(){return{videoSrc:'http://down.soundaer.com/live/stream_89003_sd/playlist.m3u8?k=d708550fbd49c58a1b8a8412c8623277&t=1553687908',posterSrc:'https://matrimony001.100msh.net.cn/public/code/material/mp-7261-1554175849.jpg',isError:false}
}
mounted() {//为避免在初始化video时播放源是空的,报播放源错误,需要先给source 的src赋值var player = videojs('videobox',{bigPlayButton: true,textTrackDisplay: true,posterImage: true,errorDisplay: false,controlBar: false,playbackRates: [0.5, 1, 1.5, 2],ControlBar:{customControlSpacer: true}},function onPlayerReady(){this.play();setTimeout(() => {   //延时确保能监听到视频源错误var mediaError = this.error();if(mediaError!=null && mediaError.code){_this.isError=trueDialog.alert({message: '啊哦,播放出错了。<br>请刷新重试,如无法播放建议您观看其它内容。',confirmButtonText:'确定'}).then(() => {_this.goback();});}},1000);});        // player.width(this.videoW)   //设置播放器宽度
},beforeDestroy(){const videoDom = this.$refs.videoRef;   //不能用document 获取节点videojs(videoDom).dispose();  //销毁video实例,避免出现节点不存在 但是flash一直在执行,也避免重新进入页面video未重新声明}
</script>

下面是自己的内容

上图是大华摄像机的拉流方式,需要知道的信息是平台ip,地址,设备编号,通道号和码流类型,这些都可以通过大华的摄像机管理平台进行获取,码流类型分为主码流和辅码流,两个的差别是视频的清晰度问题,因为我们需要在一个页面展示多个视频数据,所以同时传输主码流会发生问题,造成卡顿,对网络造成压力。然而使用辅码流会对视频在全屏的时候造成视频模糊的问题。

问题一


由于项目图片不便于展示进行打码,页面进行视频展示采用的是videojs,在github上可以查到使用方法,这里出现了一个小问题是在github上的视频播放器不支持h265格式的浏览器展现,所以在做vue页面之前需要保证视频流格式是h264的。如果使用videojs对h265视频进行播放会发现只有声音没有画面,是因为声音的解码方式和画面解码方式不同。使用vlc工具可以对视频流格式进行分析vlc下载地址
然后我们使用videojs的全屏检测功能进行处理,当我们是正常屏幕时我们使用辅码流,在全屏时使用主码流。

async initVideo () {await this.getUrlsList()this.urlsList.map((item, i) => {var player1 = videojs('myVideo' + i, {bigPlayButton: true,textTrackDisplay: true,posterImage: true,errorDisplay: false,controlBar: false,ControlBar: {customControlSpacer: true}},function onPlayerReady () {player1.play()// 捕捉是否全屏,对视频流进行主码流和辅码流的切换player1.on('fullscreenchange', function (e) {if (player1.isFullscreen()) {player1.src(item.src)player1.load()player1.play()} else {player1.src(item.lowsrc)player1.load()player1.play()}})const _this = thissetTimeout(() => {var mediaError = this.error()if (mediaError != null && mediaError.code) {_this.isError = true}}, 1000)})})},

借鉴videojs全屏设置

问题二


我们设置的是可以切换页面的,因为不只有6个视频流所以需要监听切换事件,但是因为不同步,在我们切换的时候可能会出现视频没有加载出来的问题,同样在上面的代码中进行呈现。我们使用async和await配合的方式进行处理,进行对获取url信息进行等待。

问题三

data-setup="{}"设置陷阱
使用data-setup="{}",不需要对videojs对象进行初始化,比较方便,一开始我也是使用这种方式但是这种方式会出现白屏问题,无法显示。所以千万不要用data-setup="{}"!!!

问题四

多个视频如何呈现的问题
首先建立urllist,对后台的url进行存储

<div v-show='!isError' v-for="(item,i) in urlsList" :key="i" :style="{width: list[i].width+ 'px', height: list[i].height+ 'px', left: list[i].left+ 'px', top: list[i].top+ 'px', position: 'absolute'}"><video :id="'myVideo'+i" ref='videoRef'   style="object-fit: fill; width: 100%; height: 100%" class="video-js vjs-default-skin vjs-big-play-centered " muted controls preload="auto" webkit-playsinline="true" playsinline="true" type="application/x-mpegURL" allowsInlineMediaPlayback=YES  webview.allowsInlineMediaPlayback=YES  width='100%'  x5-video-player-fullscreen="true"><source id="sourceBox" :src="item.lowsrc"><p class="vjs-no-js">不支持播放</p></video></div>

使用v-for对urllist数据进行查询,同时video标签中 :id="‘myVideo’+i" 对每个视频进行id设置,在后面初始化的时候进行一一对应。同时设置视频的videoref,一开始的时候以为多个组件只设置一个ref是不行的,在销毁的使用需要用到这个东西。后来发现对于这种多个组件使用一个ref的方式可以使用ref[i]

beforeDestroy () {console.log('destroy')this.urlsList.map((item, i) => {const videoDom = this.$refs.videoRef[i]videojs(videoDom).dispose()})}

对于多个视频的位置设置我们将六个视频的位置保存在list中,可以直接调用来固定每个视频的位置

全部代码

<template><div><el-form :inline="true"  class="demo-form-inline"><el-form-item label="摄像头设备编号"><el-input v-model="device_num" placeholder="例如:1000000"></el-input></el-form-item><el-form-item label="摄像头通道号"><el-input v-model="way_num" placeholder="摄像头通道号"></el-input></el-form-item><el-form-item label="摄像头名字"><el-input v-model="cameraName" placeholder="摄像头名字"></el-input></el-form-item><el-form-item><el-button type="primary" @click="addCamera">添加</el-button></el-form-item><el-form-item label="摄像头选择"><el-select v-model="cameraid" clearable placeholder="请选择" style='paddingLeft:20px;'><el-optionv-for="item in cameraOptions":key="item.value":label="item.label":value="item.value"></el-option></el-select><el-button type="primary" @click="deleteCamera" style="color:#fff;margin-left:20px;">删除</el-button></el-form-item></el-form><div v-show='!isError' v-for="(item,i) in urlsList" :key="i" :style="{width: list[i].width+ 'px', height: list[i].height+ 'px', left: list[i].left+ 'px', top: list[i].top+ 'px', position: 'absolute'}"><video :id="'myVideo'+i" ref='videoRef'   style="object-fit: fill; width: 100%; height: 100%" class="video-js vjs-default-skin vjs-big-play-centered " muted controls preload="auto" webkit-playsinline="true" playsinline="true" type="application/x-mpegURL" allowsInlineMediaPlayback=YES  webview.allowsInlineMediaPlayback=YES  width='100%'  x5-video-player-fullscreen="true"><source id="sourceBox" :src="item.lowsrc"><p class="vjs-no-js">不支持播放</p></video></div><div v-show='isError' class="errorTip"><p>视频出错了!</p></div><div class="footer"><el-pagination@current-change="handleCurrentChange":current-page="queryInfo.pagenum":page-size="queryInfo.pagesize"layout="total, prev, pager, next, jumper":total="total"></el-pagination></div></div>
</template><script>
import videojs from 'video.js'
import 'videojs-contrib-hls'
export default {inject: ['reload'],data () {return {cameraOptions: [],cameraid: '',queryInfo: {query: '',// 当前的页数pagenum: 1,// 当前每页显示多少条数据pagesize: 6},urlsList: [],total: 0,device_num: '',way_num: '',cameraName: '',list: [{width: 416,height: 234,left: 100,top: 150}, {width: 416,height: 234,left: 550,top: 150}, {width: 416,height: 234,left: 1000,top: 150}, {width: 416,height: 234,left: 100,top: 400}, {width: 416,height: 234,left: 550,top: 400}, {width: 416,height: 234,left: 1000,top: 400}],isError: false}},methods: {deleteCamera () {this.$confirm('此操作将永久删除该摄像头, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(async () => {const {meta} = await this.$api.cctv.removeCamera({params: {cctvName: this.cameraOptions[this.cameraid].label}})if (meta.status !== 200) {return this.$message.error('删除摄像头失败!')}await this.getCameraOptions()this.$router.go(0)this.$message.success('删除成功!')}).catch(() => {this.$message.info('取消删除!')})},async getCameraOptions () {const {meta,data} = await this.$api.cctv.getCameraOptions()console.log('meta', meta)if (meta.status !== 200) {return this.$message.error('获取播放列表失败!')}this.cameraOptions = data.cameraOptions},async addCamera () {const {meta} = await this.$api.cctv.addCamera({params: {device_num: this.device_num,way_num: this.way_num,cctvName: this.cameraName}})if (meta.status !== 200) {return this.$message.error('添加摄像头失败!')}this.$router.go(0)},async getUrlsList () {const {meta,data} = await this.$api.cctv.getRealplay({ params: this.queryInfo })console.log('meta', meta)if (meta.status !== 200) {return this.$message.error('获取播放列表失败!')}this.urlsList = data.urlsthis.total = data.totalthis.dataBack = dataconsole.log(data)},async initVideo () {await this.getUrlsList()this.urlsList.map((item, i) => {var player1 = videojs('myVideo' + i, {bigPlayButton: true,textTrackDisplay: true,posterImage: true,errorDisplay: false,controlBar: false,ControlBar: {customControlSpacer: true}},function onPlayerReady () {player1.play()player1.on('fullscreenchange', function (e) {if (player1.isFullscreen()) {player1.src(item.src)player1.load()player1.play()} else {player1.src(item.lowsrc)player1.load()player1.play()}})const _this = thissetTimeout(() => {var mediaError = this.error()if (mediaError != null && mediaError.code) {_this.isError = true}}, 1000)})})},async handleCurrentChange (newPage) {this.queryInfo.pagenum = newPage//  切换页面的时候需要添加这个将前一个页面的视频流关闭掉并且初始化urllist不然会导致页面不出现视频的问题,同时视频流一直在发送this.urlsList.map((item, i) => {const videoDom = this.$refs.videoRef[i]videojs(videoDom).dispose()})this.urlsList = ''this.initVideo()}},created () {this.initVideo()},mounted () {this.initVideo()this.getCameraOptions()this.$emit('change_index',{itemId: 52,subPath: '/realtime'})},beforeDestroy () {console.log('destroy')this.urlsList.map((item, i) => {const videoDom = this.$refs.videoRef[i]videojs(videoDom).dispose()})}
}
</script><style>.footer{position:fixed;bottom: 10px;left: 100px;}</style>

上面对videojs的使用作介绍,借鉴https://blog.csdn.net/qq_39923762/article/details/89149715?spm=1001.2014.3001.5506

【大华摄像机hls拉流vue使用videojs展示 一个页面多个视频同时播放】相关推荐

  1. 2019.11.12-最新大华摄像机SDK开发,预览实时视频并指定码流格式保存到文件中(可观看)

    大华摄像机SDK开发,预览实时视频并指定码流格式保存到文件中 由于本人最近在开发大华摄像机,特此分享一些经验给到各位开发朋友,本次实例是关于大华摄像机的实时预览视频码流保存到文件中的Demo,本人还开 ...

  2. java接口方式调用海康大华摄像机预览。

    客户有海康和大华的监控设备,没有买各类安防平台,国标方式需要预留给其他需要接入的系统,得兼容高版本chrome,询问了大华的客服人员,最后选择了该方案进行解决,记录下曲折的过程.延迟大约10秒的样子, ...

  3. EasyNVR网页摄像机无插件H5、谷歌Chrome直播方案中海康大华摄像机rtsp地址配置方法

    背景分析 众所周知,为了让用户更好的了解与使用EasyNVR,熟悉EasyNVR的相关功能,将EasyNVR与本地应用场景更好的融合,我们团队提出产品免费试用的理念.只要我们的产品符合用户的使用场景, ...

  4. 关于使用GB28181协议实现与大华摄像机的语音对讲功能小记

    目前只测试了与大华摄像机的语音对讲功能,在此记录下对接工程中遇到的问题和收获. 首先我们需要理清下思路: 第一步要熟悉语音对讲的协议流程,下图为国标28181中的参考图: 这里我们可以简化下流程,只参 ...

  5. Onvif登录海康、大华摄像机(IPC)提示权鉴失败的问题解决

    最近用我们的Onvif设备发现客户端测试,发现连接某些摄像机Onvif获取不到设备信息,提示401权鉴失败.确认用户名和密码都没错的情况下,都还是失败,软件提示信息截图如下: 我们测的摄像机有海康和大 ...

  6. OpenCv通过RTSP预览大华摄像机视频

    一.配置大华摄像机参数 检查RTSP端口号 修改分辨率,在这里我们主要设置[辅码流] 大华RTSP协议解释 访问主码流 rtsp://admin:a12345678@192.168.1.108:554 ...

  7. python+opencv打开大华摄像机视频

    学习笔记 python+opencv打开大华摄像机视频 python+opencv打开大华摄像机视频 import cv2 # 大华摄像机的视频采集语句,subtype=1,辅码流.0,主码流. ca ...

  8. ffmpeg 使用ffplay 进行 hls 拉流 分析 1

    ffmpeg 使用 ffplay 进行 hls 拉流 分析 1 从使用ffplay 调用 http://192.168.1.100:8080/live/livestream.m3u8 开始,进入到ff ...

  9. 海康大华摄像机图像收集工具

    文章目录 简介 准备工作 设置需要连接的摄像机 设置需要采集的点位信息 收集图像 开始收集图像 查看图像收集信息 暂停/恢复摄像机收集 取消图像收集 完成图像收集 其他功能 实时预览 开始实时预览 结 ...

最新文章

  1. 合肥天鹅湖万达广场机器人_王健林再考察合肥!瞄准政务、高新,年末合肥楼市出现区域分化...
  2. 梯度提升树(GBDT)原理小结
  3. python 多数据输出到txt_python-BeautifulSoup输出到.txt文件
  4. struts2入门之action获取表单提交数据
  5. 30天敏捷结果(24):恢复你的精力
  6. LAMP源码安装配置实战
  7. 使用 Python 的人脸识别系统
  8. 你应该掌握的浏览器相关知识
  9. word文档除号怎么打出来之除号插入的方法教程
  10. 巴比特 | 元宇宙每日必读:HTC 宣布推出首款元宇宙手机,售价约2700元人民币,都有哪些新玩法?...
  11. 【c++中内存拷贝函数(C++ memcpy)详解】
  12. 有关日期参数匹配数据库数据的方法
  13. 最近设计的一个无人机app的界面
  14. 赛扬处理器_【硬件资讯】Intel 10代酷睿 桌面处理器正式发布
  15. unity解压缩文件踩坑记录
  16. NYOJ 1036 非洲小孩
  17. windows命令行技巧dos命令ren的用法小记
  18. PCI-E x1/x4/x8/x16四种插槽区别是什么
  19. python remi库官网_python库介绍-PySimpleGUI-简单的GUI开发工具
  20. centos安装Maven教程

热门文章

  1. 离散化(保序 / 非保序)
  2. SpringSecurity配置用户和密码
  3. 魔力拼图V1.0下载地址
  4. 守一隅静美,醉一域风情
  5. Oracle 数据库监听日志过大,怎么清除?
  6. twitter_如何将Twitter主题转化为可读的博客文章
  7. Python+Vue计算机毕业设计享瘦减肥中心管理系统47ccq(源码+程序+LW+部署)
  8. 论文《Product-based Neural Networks for User Response Prediction》阅读
  9. 5.3nbsp;进化论
  10. Docker 1.5新特性