发布时间:2025-06-24 20:48:14 作者:北方职教升学中心 阅读量:927
本地开发的时候要双击运行webrtc-streamer.exe可执行文件后,vue项目才能展示实时监控,打包发布到线上的时候可能要让后台在服务器上安装webrtc-streamer并提供真实的地址,关于这点现在还没来得及试
发布时间:2025-06-24 20:48:14 作者:北方职教升学中心 阅读量:927
本地开发的时候要双击运行webrtc-streamer.exe可执行文件后,vue项目才能展示实时监控,打包发布到线上的时候可能要让后台在服务器上安装webrtc-streamer并提供真实的地址,关于这点现在还没来得及试
1.因为是纯前端角度,所以从后端可以获取http开头的视频流地址(其实是在后端电脑打开,然后本地接入后端电脑,进行查看或修改配置)因为rstp流需要转码,所以在摄像头配置里面要修改转码格式
2.前端自己可以下载安装VLC播放器然后进行调试设置
1.下载webrtc-streamer
下载地址:https://github.com/mpromonet/webrtc-streamer/releases
下载版本根据自己电脑进行选择,双击webrtc-streamer.exe可执行文件后在浏览器访问http://127.0.0.1:8000,可以看到自己电脑正在操作的内容。注意:视频编码格式必须是H264的,否则无法正常显示,编码格式可在摄像头的后台更改//向后端发送rtsp地址webRtcServer.value.connect(props.rtspUrl)setTimeout(()=>{emit('screenButton')},1000)}catch(error){console.log(error)}}/* 处理双击 视频全屏*/constdbClick=()=>{constelVideo =document.getElementById(props.id)if(elVideo.webkitRequestFullScreen){elVideo.webkitRequestFullScreen()}elseif(elVideo.mozRequestFullScreen){elVideo.mozRequestFullScreen()}elseif(elVideo.requestFullscreen){elVideo.requestFullscreen()}}/* 抓拍*/functionhandleScreenshot(flag){letvideo =document.getElementById(props.id)//获取dom节点letcanvas =document.createElement('canvas')//创建canvas节点letw =window.innerWidth leth =(window.innerWidth /16)*9canvas.width =w canvas.height =h //设置canvas宽高constctx =canvas.getContext('2d')ctx.drawImage(video,0,0,w,h)//video写入到canvasletobj ={name:props.data.name,id:props.data.id,image:canvas.toDataURL('image/jpge'),//生成截图地址flags:flag,}// flag true 手动抓拍 false 自动抓拍emit('screenshot',obj,flag)}// 开始自动抓拍conststartAutoCapture=()=>{captureTimer.value =setInterval(()=>{handleScreenshot(false)},captureInterval)}// 新增:停止自动抓拍功能conststopAutoCapture=()=>{if(captureTimer.value){clearInterval(captureTimer.value)captureTimer.value =null}}onMounted(()=>{startAutoCapture()})//销毁视频流onUnmounted(()=>{webRtcServer.value.disconnect()stopAutoCapture()})</script><!-- style="object-fit: fill; 设置视频内容撑满整个video标签 --><template><divclass="video-contianer"><videoref="videoRef":id="id"controlsautoplaymutedwidth="100%"height="100%"style="object-fit:fill"></video><divclass="mask"@dblclick="dbClick"></div></div></template><stylescopedlang="scss">.video-contianer{position:relative; .mask{position:absolute;cursor:pointer;top:25%;left:0;width:100%;height:50%;}}</style>
本文介绍了如何在Vue应用中通过WebRTC技术获取摄像头的rtsp视频流,同时展示了实时监控,全屏,拍摄,自动拍摄等功能。 1.父页面 2.子页面第一次写这种实时监控加抓拍的功能,可能还有一些不足,后面再看看有没有其他更好的办法。
vue3+setup使用rtsp视频流实现实时监控,全屏,拍摄,自动拍摄等功能(纯前端)
概要
<scriptsrc="/adapter.min.js"></script><scriptsrc="/webrtcstreamer.js"></script>
三、具体代码,video封装
<scriptsetup>import{ref }from'vue'importvideoRtmp from'./videoRtmp.vue'constlist =ref([])constidlist =ref([])constimgArr =ref([])// 手动抓拍的图片constscreenshotUrl =ref([])// 自动抓拍的图片consttotal =ref(0)constcurrentPage =ref(1)constkeyWord =ref('')constrtmpUrl =ref('rtsp://用户:密码@电脑网址:554')// videoFlag 判断是单个还是多个video 对应不同的样式 false是单个 true是多个constform =ref({videoFlag:false,videoList:[]})constopenVideo =ref(false)constscreenButton =ref(false)// 默认解禁 点击抓拍按钮后禁止 抓拍完成后解禁constsButton =ref(true)// 默认禁止 加载完成后解禁letscreenNums =0// 加载完成的数量constloadData=(pageNum =currentPage.value,pageSize =10)=>{list.value =[{id:1,idName:'id1',name:'设备1',rtmpUrl:'rtsp://用户:密码@电脑网址:554',userName:'admin',screenFlag:false,},{id:2,idName:'id2',name:'设备2',code:'002',userName:'admin',password:'VWEFKS',screenFlag:false,rtmpUrl:'rtsp://用户:密码@电脑网址:554',},]total.value =list.value.length}//分页consthandlePageChange=(page)=>{currentPage.value =page loadData()}// 搜索constsearchHandle=async()=>{currentPage.value =1loadData()}/** 选择条数 */functionhandleSelectionChange(selection){console.log(selection)idlist.value =selection}//单个点击观看constvideoLook=(row)=>{console.log(row)form.value.videoList =[row]form.value.videoFlag =falseopenVideo.value =true}//多个观看constvideoAllLook=(row)=>{console.log(row)form.value.videoList =idlist.value form.value.videoFlag =idlist.value.length >1?true:falseopenVideo.value =true}//点击叉号constcloseHandle=()=>{resetData()}//清空数据constresetData=()=>{openVideo.value =falseimgArr.value =[]screenshotUrl.value =[]screenNums =0screenButton.value =falseform.value ={}loadData()}// 抓拍constscreenshot=()=>{form.value.videoList.forEach((v)=>{v.screenFlag =true})screenButton.value =true}//父子传值 获取抓拍的consthandleScreenshot=(data,flag)=>{console.log(data.id,data,flag)if(!flag){// 自动抓拍screenshotUrl.value.push(data.image)imageVideoApi()return}// 手动抓拍form.value.videoList.forEach((v)=>{if(v.id ==data.id){v.screenFlag =false}})imgArr.value.push(data.image)if(!form.value.videoList.some((a)=>a.screenFlag)){screenButton.value =falseimageVideoApi()}}// 父子传值 获取video是否成功// 因为video加载需要一段时间,在这段时间里,不能抓拍,所以要在这段时间给它禁用掉,等到video加载完后,在解禁// 这里做判断 在子页面加载完成emit返回主页面 然后判断返回的数量 符合video的数量,说明都加载完了constscreenButtonS=()=>{screenNums++if(form.value.videoList.length ==screenNums){sButton.value =false}}// 图片检测接口constimageVideoApi=async()=>{letfiles =base64ToFile(imgArr.value[0],'image.png')letres =awaitimageVideo({file:files })}// base64转filefunctionbase64ToFile(base64Data,filename){// 将base64的数据部分提取出来constarr =base64Data.split(',')constmime =arr[0].match(/:(.*?);/)[1]constbstr =atob(arr[1])letn =bstr.length constu8arr =newUint8Array(n)while(n--){u8arr[n]=bstr.charCodeAt(n)}// 将Uint8Array转换为Blob对象constblob =newBlob([u8arr],{type:mime })// 创建File对象constfile =newFile([blob],filename,{type:mime })returnfile}loadData()</script><template><div><el-formclass="main-form":inline="true"><el-form-itemlabel="设备名称:"><el-inputv-model="keyWord"placeholder="请输入设备名称"/></el-form-item><el-form-item><el-button:icon="Search"type="primary"@click="searchHandle">搜索</el-button></el-form-item><el-form-item><el-button:icon="Search"type="primary":disabled="idlist.length <= 0"@click="videoAllLook">多流播放</el-button></el-form-item></el-form><!-- 列表部分 --><el-tableborder:data="list"height="460"scrollbar-always-on="true"@selection-change="handleSelectionChange"><el-table-columnalign="center"type="selection"width="50"/><el-table-columnlabel="设备名称"prop="name"/><el-table-columnlabel="账号"prop="userName"width="100"/><el-table-columnfixed="right"label="操作"width="160"><template#default="scope"><el-buttonsize="small"type="primary"@click="videoLook(scope.row)">播放</el-button></template></el-table-column></el-table><el-paginationbackground:current-page="currentPage":hide-on-single-page="true"layout="prev, pager, next":total="total"@current-change="handlePageChange"/><el-dialogtitle="实时监控"width="900px":close-on-click-modal="false"@close="closeHandle"v-model="openVideo"><divv-if="!form.videoFlag"><h2style="text-align:center">{{ form.videoList[0]?.name}}</h2><video-rtmp:rtspUrl="form.videoList[0]?.rtmpUrl":id="form.videoList[0]?.idName":screenFlag="form.videoList[0]?.screenFlag":data="form.videoList[0]"@screenshot="handleScreenshot"@screenButton="screenButtonS"/></div><divclass="videoAll"v-else><divv-for="(item, index) in form.videoList":key="index"><h2style="text-align:center">{{ item?.name}}</h2><video-rtmp:rtspUrl="item?.rtmpUrl":id="item?.idName":screenFlag="item?.screenFlag":data="item"@screenshot="handleScreenshot"@screenButton="screenButtonS"/></div></div><div><el-buttontype="primary":disabled="screenButton || sButton"v-preventReClick@click="screenshot">抓拍</el-button></div><div>手动抓拍 <imgstyle="width:300px;height:100px"v-for="(item, index) in imgArr":key="index":src="item"/></div><div>自动抓拍 <imgstyle="width:100px;height:50px"v-for="(item, index) in screenshotUrl":key="index":src="item"/></div></el-dialog></div></template><stylescopedlang="scss">.videoAll{> div{width:45%;height:45%;display:inline-block;}> div:nth-child(odd){margin-right:5%;}}</style>
<scriptsetup>defineOptions({name:'VideoRtmp',})// 如果不想放到public里面并在index.html里面引入,也可以选择其他位置// import WebRtcStreamer from './webrtcstreamer.js'import{ref }from'vue'constemit =defineEmits()constprops =defineProps({rtspUrl:{type:String,default:'',},id:{type:String,default:'',},data:{type:Object,default:'',},screenFlag:{type:Boolean,default:'',},})constvideoRef =ref(null)constwebRtcServer =ref(null)constsrcUrl =ref(process.env.NODE_ENV==='development'?'http://网址:端口':'http://网址:端口')//这里看自己的需要,也可以传入另一台电脑的ip,前提是都得在在一个局域网内// 设置抓拍间隔时间,单位为毫秒,这里设置为5000毫秒(即5秒)constcaptureInterval =5000// 新增:用于存储定时器标识constcaptureTimer =ref(null)watch(()=>props.rtspUrl,(val)=>{if(val){// 这里放开会报错,还没有找到原因// webRtcServer.value.disconnect()nextTick(()=>{initVideo()})}},{deep:true,immediate:true})watch(()=>props.screenFlag,(val)=>{if(val){handleScreenshot(true)}},{deep:true,immediate:true})functioninitVideo(){try{//video:需要绑定的video控件ID//127.0.0.1:8000:启动webrtc-streamer的设备IP和端口,默认8000//连接后端的IP地址和端口// 静音videoRef.value.volume =0webRtcServer.value =newWebRtcStreamer(props.id,srcUrl.value)//需要查看的rtsp地址,根据自己的摄像头传入对应的rtsp地址即可。
一、