vue2使用rtsp视频流接入海康威视摄像头(纯前端)
一.获取海康威视rtsp视频流
海康威视官方的RTSP最新取流格式如下:
rtsp://用户名:密码@IP:554/Streaming/Channels/101
用户名和密码
IP就是登陆摄像头时候的IP(笔者这里IP是192.168.1.210)
所以笔者的rtsp流地址就是rtsp://用户名:密码@192.168.1.210:554/Streaming/Channels/101
二. 测试rtsp流是否可以播放
1.实现RTSP协议推流需要做的配置
1.1关闭萤石云的接入
1.2调整视频编码为H.264
2.安装VLC播放器
在此下载 video mediaplay官网 即(VLC)
安装完成之后 打开VLC播放器
在VLC播放器中打开网络串流 输入rtsp地址
成功的话我们可以看到我们所显示的摄像头
如果RTSP流地址正确且取流成功,VLC的界面会显示监控画面。否则会报错,报错信息写在了日志里,在[工具]>[消息]里可以看到
三.在vue2中引用rtsp视频流形式的海康摄像头
1.新建webrtcstreamer.js文件
在public文件夹下新建webrtcstreamer.js 代码贴在下方,复制粘贴即可
var WebRtcStreamer = (function() {/** * Interface with WebRTC-streamer API* @constructor* @param {string} videoElement - id of the video element tag* @param {string} srvurl - url of webrtc-streamer (default is current location)
*/
var WebRtcStreamer = function WebRtcStreamer (videoElement, srvurl) {if (typeof videoElement === "string") {this.videoElement = document.getElementById(videoElement);} else {this.videoElement = videoElement;}this.srvurl = srvurl || location.protocol+"//"+window.location.hostname+":"+window.location.port;this.pc = null; this.mediaConstraints = { offerToReceiveAudio: true, offerToReceiveVideo: true };this.iceServers = null;this.earlyCandidates = [];
}WebRtcStreamer.prototype._handleHttpErrors = function (response) {if (!response.ok) {throw Error(response.statusText);}return response;
}/** * Connect a WebRTC Stream to videoElement * @param {string} videourl - id of WebRTC video stream* @param {string} audiourl - id of WebRTC audio stream* @param {string} options - options of WebRTC call* @param {string} stream - local stream to send
*/
WebRtcStreamer.prototype.connect = function(videourl, audiourl, options, localstream) {this.disconnect();// getIceServers is not already receivedif (!this.iceServers) {console.log("Get IceServers");fetch(this.srvurl + "/api/getIceServers").then(this._handleHttpErrors).then( (response) => (response.json()) ).then( (response) => this.onReceiveGetIceServers(response, videourl, audiourl, options, localstream)).catch( (error) => this.onError("getIceServers " + error ))} else {this.onReceiveGetIceServers(this.iceServers, videourl, audiourl, options, localstream);}
}/** * Disconnect a WebRTC Stream and clear videoElement source
*/
WebRtcStreamer.prototype.disconnect = function() { if (this.videoElement?.srcObject) {this.videoElement.srcObject.getTracks().forEach(track => {track.stop()this.videoElement.srcObject.removeTrack(track);});}if (this.pc) {fetch(this.srvurl + "/api/hangup?peerid=" + this.pc.peerid).then(this._handleHttpErrors).catch( (error) => this.onError("hangup " + error ))try {this.pc.close();}catch (e) {console.log ("Failure close peer connection:" + e);}this.pc = null;}
} /*
* GetIceServers callback
*/
WebRtcStreamer.prototype.onReceiveGetIceServers = function(iceServers, videourl, audiourl, options, stream) {this.iceServers = iceServers;this.pcConfig = iceServers || {"iceServers": [] };try { this.createPeerConnection();var callurl = this.srvurl + "/api/call?peerid=" + this.pc.peerid + "&url=" + encodeURIComponent(videourl);if (audiourl) {callurl += "&audiourl="+encodeURIComponent(audiourl);}if (options) {callurl += "&options="+encodeURIComponent(options);}if (stream) {this.pc.addStream(stream);}// clear early candidatesthis.earlyCandidates.length = 0;// create Offerthis.pc.createOffer(this.mediaConstraints).then((sessionDescription) => {console.log("Create offer:" + JSON.stringify(sessionDescription));this.pc.setLocalDescription(sessionDescription).then(() => {fetch(callurl, { method: "POST", body: JSON.stringify(sessionDescription) }).then(this._handleHttpErrors).then( (response) => (response.json()) ).catch( (error) => this.onError("call " + error )).then( (response) => this.onReceiveCall(response) ).catch( (error) => this.onError("call " + error ))}, (error) => {console.log ("setLocalDescription error:" + JSON.stringify(error)); });}, (error) => { alert("Create offer error:" + JSON.stringify(error));});} catch (e) {this.disconnect();alert("connect error: " + e);}
}WebRtcStreamer.prototype.getIceCandidate = function() {fetch(this.srvurl + "/api/getIceCandidate?peerid=" + this.pc.peerid).then(this._handleHttpErrors).then( (response) => (response.json()) ).then( (response) => this.onReceiveCandidate(response)).catch( (error) => this.onError("getIceCandidate " + error ))
}/*
* create RTCPeerConnection
*/
WebRtcStreamer.prototype.createPeerConnection = function() {console.log("createPeerConnection config: " + JSON.stringify(this.pcConfig));this.pc = new RTCPeerConnection(this.pcConfig);var pc = this.pc;pc.peerid = Math.random(); pc.onicecandidate = (evt) => this.onIceCandidate(evt);pc.onaddstream = (evt) => this.onAddStream(evt);pc.oniceconnectionstatechange = (evt) => { console.log("oniceconnectionstatechange state: " + pc.iceConnectionState);if (this.videoElement) {if (pc.iceConnectionState === "connected") {this.videoElement.style.opacity = "1.0";} else if (pc.iceConnectionState === "disconnected") {this.videoElement.style.opacity = "0.25";} else if ( (pc.iceConnectionState === "failed") || (pc.iceConnectionState === "closed") ) {this.videoElement.style.opacity = "0.5";} else if (pc.iceConnectionState === "new") {this.getIceCandidate();}}}pc.ondatachannel = function(evt) { console.log("remote datachannel created:"+JSON.stringify(evt));evt.channel.onopen = function () {console.log("remote datachannel open");this.send("remote channel openned");}evt.channel.onmessage = function (event) {console.log("remote datachannel recv:"+JSON.stringify(event.data));}}pc.onicegatheringstatechange = function() {if (pc.iceGatheringState === "complete") {const recvs = pc.getReceivers();recvs.forEach((recv) => {if (recv.track && recv.track.kind === "video") {console.log("codecs:" + JSON.stringify(recv.getParameters().codecs))}});}}try {var dataChannel = pc.createDataChannel("ClientDataChannel");dataChannel.onopen = function() {console.log("local datachannel open");this.send("local channel openned");}dataChannel.onmessage = function(evt) {console.log("local datachannel recv:"+JSON.stringify(evt.data));}} catch (e) {console.log("Cannor create datachannel error: " + e);} console.log("Created RTCPeerConnnection with config: " + JSON.stringify(this.pcConfig) );return pc;
}/*
* RTCPeerConnection IceCandidate callback
*/
WebRtcStreamer.prototype.onIceCandidate = function (event) {if (event.candidate) {if (this.pc.currentRemoteDescription) {this.addIceCandidate(this.pc.peerid, event.candidate); } else {this.earlyCandidates.push(event.candidate);}} else {console.log("End of candidates.");}
}WebRtcStreamer.prototype.addIceCandidate = function(peerid, candidate) {fetch(this.srvurl + "/api/addIceCandidate?peerid="+peerid, { method: "POST", body: JSON.stringify(candidate) }).then(this._handleHttpErrors).then( (response) => (response.json()) ).then( (response) => {console.log("addIceCandidate ok:" + response)}).catch( (error) => this.onError("addIceCandidate " + error ))
}/*
* RTCPeerConnection AddTrack callback
*/
WebRtcStreamer.prototype.onAddStream = function(event) {console.log("Remote track added:" + JSON.stringify(event));this.videoElement.srcObject = event.stream;var promise = this.videoElement.play();if (promise !== undefined) {promise.catch((error) => {console.warn("error:"+error);this.videoElement.setAttribute("controls", true);});}
}/*
* AJAX /call callback
*/
WebRtcStreamer.prototype.onReceiveCall = function(dataJson) {console.log("offer: " + JSON.stringify(dataJson));var descr = new RTCSessionDescription(dataJson);this.pc.setRemoteDescription(descr).then(() => { console.log ("setRemoteDescription ok");while (this.earlyCandidates.length) {var candidate = this.earlyCandidates.shift();this.addIceCandidate(this.pc.peerid, candidate); }this.getIceCandidate()}, (error) => { console.log ("setRemoteDescription error:" + JSON.stringify(error)); });
} /*
* AJAX /getIceCandidate callback
*/
WebRtcStreamer.prototype.onReceiveCandidate = function(dataJson) {console.log("candidate: " + JSON.stringify(dataJson));if (dataJson) {for (var i=0; i<dataJson.length; i++) {var candidate = new RTCIceCandidate(dataJson[i]);console.log("Adding ICE candidate :" + JSON.stringify(candidate) );this.pc.addIceCandidate(candidate).then( () => { console.log ("addIceCandidate OK"); }, (error) => { console.log ("addIceCandidate error:" + JSON.stringify(error)); } );}this.pc.addIceCandidate();}
}/*
* AJAX callback for Error
*/
WebRtcStreamer.prototype.onError = function(status) {console.log("onError:" + status);
}return WebRtcStreamer;
})();if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {window.WebRtcStreamer = WebRtcStreamer;
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {module.exports = WebRtcStreamer;
}
2.下载webrtc-streamer
资源在最上面
也可以去github上面下载:webrtc-streamer
下载完解压,打开文件夹,启动webrtc-streamer.exe
打开完会出现cmd一样的黑框框如下
如果没有启动成功可以在浏览器中输入http://127.0.0.1:8000/查看本地端口8000是否被其他应用程序占用,如果没有被占用打开窗口应该如下图所示(是可以看见自己的页面的)
3.封装组件video.vue(名字随意)
代码如下(但是有需要注意的地方,请看下方)
<template><div id="video-contianer"><videoclass="video"ref="video"preload="auto"autoplay="autoplay"mutedwidth="600"height="400"/><divclass="mask"@click="handleClickVideo":class="{ 'active-video-border': selectStatus }"></div></div>
</template><script>
import WebRtcStreamer from '../../public/hk/webrtcstreamer'export default {name: 'videoCom',props: {rtsp: {type: String,required: true,},isOn: {type: Boolean,default: false,},spareId: {type: Number,},selectStatus: {type: Boolean,default: false,},},data() {return {socket: null,result: null, // 返回值pic: null,webRtcServer: null,clickCount: 0, // 用来计数点击次数}},watch: {rtsp() {// do somethingconsole.log(this.rtsp)this.webRtcServer.disconnect()this.initVideo()},},destroyed() {this.webRtcServer.disconnect()},beforeCreate() {window.onbeforeunload = () => {this.webRtcServer.disconnect()}},created() {},mounted() {this.initVideo()},methods: {initVideo() {try {//连接后端的IP地址和端口this.webRtcServer = new WebRtcStreamer(this.$refs.video,`http://192.168.1.102:8000`)//向后端发送rtsp地址this.webRtcServer.connect(this.rtsp)} catch (error) {console.log(error)}},/* 处理双击 单机 */dbClick() {this.clickCount++if (this.clickCount === 2) {this.btnFull() // 双击全屏this.clickCount = 0}setTimeout(() => {if (this.clickCount === 1) {this.clickCount = 0}}, 250)},/* 视频全屏 */btnFull() {const elVideo = this.$refs.videoif (elVideo.webkitRequestFullScreen) {elVideo.webkitRequestFullScreen()} else if (elVideo.mozRequestFullScreen) {elVideo.mozRequestFullScreen()} else if (elVideo.requestFullscreen) {elVideo.requestFullscreen()}},/* ison用来判断是否需要更换视频流dbclick函数用来双击放大全屏方法*/handleClickVideo() {if (this.isOn) {this.$emit('selectVideo', this.spareId)this.dbClick()} else {this.btnFull()}},},
}
</script><style scoped lang="scss">
.active-video-border {border: 2px salmon solid;
}
#video-contianer {position: relative;// width: 100%;// height: 100%;.video {// width: 100%;// height: 100%;// object-fit: cover;}.mask {position: absolute;top: 0;left: 0;width: 100%;height: 100%;cursor: pointer;}
}
</style>
这里要注意两个地方
第一个是
第二个是
不会查看本机端口的看这里(首先使用 Win + R打开运行 输入cmd)
4.使用video封装组件播放rtsp视频流
首先我们在要使用video封装组件的地方引入并且注册video组件
之后在页面中使用video组件 并且定义了两个变量将rtsp流传给封装的video组件
效果图如下
5.使用此种方法播放的时候会默认带声音播放,如何取消(看这里)
之后声明一个方法
然后在created里面调用就静音了
四.其他功能
1.截图功能
rtsp流引入海康威视摄像头——截图功能-CSDN博客
到此为止海康摄像头引入vue的方法就完美完结了
如果同学们有什么好的意见或者有什么问题可以私信我
最后祝大家事业蒸蒸日上,心想事成!
相关文章:

vue2使用rtsp视频流接入海康威视摄像头(纯前端)
一.获取海康威视rtsp视频流 海康威视官方的RTSP最新取流格式如下: rtsp://用户名:密码IP:554/Streaming/Channels/101 用户名和密码 IP就是登陆摄像头时候的IP(笔者这里IP是192.168.1.210) 所以笔者的rtsp流地址就是rtsp://用户名:密码192.168.1.210:554/Streaming/Channel…...
利用PHP和GD库实现图片拼接的方法
利用PHP和GD库实现图片拼接的方法主要涉及到加载图片资源、创建目标画布、将图片资源绘制到目标画布上,并最终输出或保存拼接后的图片。以下是实现图片拼接的基本步骤: 加载图片资源: 使用imagecreatefromjpeg()、imagecreatefrompng()或ima…...

自动驾驶领域常用的软件与工具
CarSim:专门针对车辆动力学的仿真软件,能够预测和仿真汽车整车的操纵稳定性、制动性、平顺性、动力性和经济性。CarMaker:德国IPG公司推出的动力学、ADAS和自动驾驶仿真软件,提供精准的车辆本体模型和闭环仿真系统。VTD (Virtual …...
uniapp-内部项目使用文档
uniapp-内部项目使用文档 目录 uniapp-内部项目使用文档阶段1自行实现内容:阶段1问题记录: 阶段2自行实现内容: 阶段3 APP项目介绍及规范阶段4 公共组件方法UseList 列表页面HooksListItem 列表项uni-load-more 列表加载更多组件CardTitle 列…...

ASP .NET Core 中的环境变量
在本文中,我们将通过组织一场小型音乐会(当然是在代码中)来了解 ASP .NET Core 中的环境变量。让我们从创建项目开始: dotnet new web --name Concert 并更新Program.cs: // replace this: app.MapGet("/"…...
学科竞赛管理系统
文末获取源码和万字论文,制作不易,感谢点赞支持。 摘 要 随着国家教育体制的改革,全国各地举办的竞赛活动数目也是逐年增加,面对如此大的数目的竞赛信息,传统竞赛管理方式已经无法满足需求,为了提高效率&am…...

unity 让文字变形
效果: using TMPro; using UnityEngine; using NaughtyAttributes;[ExecuteInEditMode] public class TMTextPerpective : MonoBehaviour {[OnValueChanged("DoPerspective")][Range(-1f, 1f)]public float CenterBias 0f;[OnValueChanged("DoPers…...

Linux高并发服务器开发 第一天(Linux的目录结构 cd用法 终端提示符格式)
目录 1.命令解析器:shell 2.LINUX下的目录结构 3.cd的使用 3.1cd 绝对路径 3.2cd 相对路径 3.3cd 回车 3.4cd - 4. 终端提示符格式 1.命令解析器:shell 默认运行与计算机系统终端的 用来解析用户输入命令的工具 内核:操作系统的核…...

可造成敏感信息泄露!Spring Boot之Actuator信息泄露漏洞三种利用方式总结
1.介绍 Spring Boot是一个基于Spring的套件,它提供了一个即开即用的应用程序架构,可以简化Spring应用的创建及部署流程,帮助开发者更轻松快捷地构建出企业及应用。 Spring Boot项目中Actuator模块提供了众多HTTP接口端点(Endpoi…...

支持图像和视频理解多模态开源大模型:CogVLM2 CogVLM2-Video
CogVLM2和CogVLM2-Video是新一代的开源模型,支持图像和视频理解,具有显著的性能提升。最近发布的更新包括CogVLM2论文的发表、在线演示和对视频理解的支持,能够处理最多1分钟的视频。新模型支持中英文,文本长度可达8K,…...

ClouderaManager 集群搭建
前提:服务器之前做过域名映射、免密登录 ClouderaManager 集群 1. 组件分布规划 服务器服务器h1zk、hdfs(dn)、yarn(nm)、spark、kafka、flumeh2hdfs(nn-standy)、yarn(rm-active)、sparkh3hdfs(nn-active)、yarn(rm-standy)、hive、sparkh4zk、hdfs(dn)、yarn(n…...
Docker 搭建 gitlab 服务器卡顿问题解决方法(创建:swap分区)
Docker 安装系列 服务器搭建了一个 gitlab 服务器以供自己开发使用,服务器搭建很简单,但是使用起来是相当的卡顿,在代码 pull,push 过程中都会有相应的延迟。gitlab 启动运行就占用了大量的内存,4G内存在启动后已经所…...

PVE修改IP地址
一、在局域网的电脑浏览器输入PVE的IP地址登录后台,从左边的菜单找到“PVE”—“_Shell”菜单,进入网页版的ssh界面下;或者在主机的控制台下输入root密码后登录到ssh下; 二、输入以下命令回车: vi /etc/network/inter…...

智能合约的离线签名(EIP712协议)解决方案
引言:本文由天玄链开源开发者提供,欢迎报名公益天玄链训练营 https://blockchain.163.com/trainingCamp 一、解决核心问题 项目方不支付gas费,由用户自己发起交易,用户支付gas费。用户的数据保存在链下服务器中,tok…...
大模型Qwen面试内容整理-应用场景与案例分析
Qwen模型凭借其强大的自然语言理解和生成能力,在多个实际应用场景中得到了广泛应用。以下是Qwen模型的主要应用场景及一些典型的案例分析,展示了它如何解决具体问题和带来实际价值。 智能对话系统 ● 应用场景 ○ 客服机器人:Qwen被用于开发智能客服机器人,能够理解客户的问…...
spring boot的统一异常处理,使用@RestControllerAdvice
RestControllerAdvice 是 Spring Boot 中用于全局异常处理的注解,它结合了 ControllerAdvice 和 ResponseBody 的功能。这意味着使用 RestControllerAdvice 注解的类将应用于所有 RequestMapping 方法,并且任何从这些方法返回的对象都会被转换为 HTTP 响…...

OFCA-OpenHarmony课后习题答案
本文是 OFCA-OpenHarmony 认证模拟考试的习题答案,涵盖 OpenHarmony 的多内核设计、权限申请、通知发布、系统线程、启动过程、分布式软总线、模块导入、文件管理、公共事件等多个方面。每道题目均提供了详细的选择项和正确答案,旨在帮助考生熟悉考试内容…...

Open AI 推出 ChatGPT Pro
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
利用PHP和GD库实现图片切割
利用PHP和GD库实现图片切割的详细步骤如下: 一、检查GD库是否安装 确保服务器上已经安装了PHP和GD库。可以使用phpinfo()函数来检查GD库是否已经安装和启用。 二、加载原始图片 使用PHP提供的imagecreatefromjpeg()、imagecreatefrompng()或imagecreatefromgif(…...

【css】基础(一)
本专栏内容为:前端专栏 记录学习前端,分为若干个子专栏,html js css vue等 💓博主csdn个人主页:小小unicorn ⏩专栏分类:css专栏 🚚代码仓库:小小unicorn的代码仓库🚚 &a…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
Netty自定义协议解析
目录 自定义协议设计 实现消息解码器 实现消息编码器 自定义消息对象 配置ChannelPipeline Netty提供了强大的编解码器抽象基类,这些基类能够帮助开发者快速实现自定义协议的解析。 自定义协议设计 在实现自定义协议解析之前,需要明确协议的具体格式。例如,一个简单的…...