vue2使用rtsp视频流接入海康威视摄像头(纯前端)

打印 上一主题 下一主题

主题 830|帖子 830|积分 2490

一.获取海康威视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 代码贴在下方,复制粘贴即可
  1. var WebRtcStreamer = (function() {
  2. /**
  3. * Interface with WebRTC-streamer API
  4. * @constructor
  5. * @param {string} videoElement - id of the video element tag
  6. * @param {string} srvurl -  url of webrtc-streamer (default is current location)
  7. */
  8. var WebRtcStreamer = function WebRtcStreamer (videoElement, srvurl) {
  9.         if (typeof videoElement === "string") {
  10.                 this.videoElement = document.getElementById(videoElement);
  11.         } else {
  12.                 this.videoElement = videoElement;
  13.         }
  14.         this.srvurl           = srvurl || location.protocol+"//"+window.location.hostname+":"+window.location.port;
  15.         this.pc               = null;   
  16.         this.mediaConstraints = { offerToReceiveAudio: true, offerToReceiveVideo: true };
  17.         this.iceServers = null;
  18.         this.earlyCandidates = [];
  19. }
  20. WebRtcStreamer.prototype._handleHttpErrors = function (response) {
  21.     if (!response.ok) {
  22.         throw Error(response.statusText);
  23.     }
  24.     return response;
  25. }
  26. /**
  27. * Connect a WebRTC Stream to videoElement
  28. * @param {string} videourl - id of WebRTC video stream
  29. * @param {string} audiourl - id of WebRTC audio stream
  30. * @param {string} options -  options of WebRTC call
  31. * @param {string} stream  -  local stream to send
  32. */
  33. WebRtcStreamer.prototype.connect = function(videourl, audiourl, options, localstream) {
  34.         this.disconnect();
  35.        
  36.         // getIceServers is not already received
  37.         if (!this.iceServers) {
  38.                 console.log("Get IceServers");
  39.                
  40.                 fetch(this.srvurl + "/api/getIceServers")
  41.                         .then(this._handleHttpErrors)
  42.                         .then( (response) => (response.json()) )
  43.                         .then( (response) =>  this.onReceiveGetIceServers(response, videourl, audiourl, options, localstream))
  44.                         .catch( (error) => this.onError("getIceServers " + error ))
  45.                                
  46.         } else {
  47.                 this.onReceiveGetIceServers(this.iceServers, videourl, audiourl, options, localstream);
  48.         }
  49. }
  50. /**
  51. * Disconnect a WebRTC Stream and clear videoElement source
  52. */
  53. WebRtcStreamer.prototype.disconnect = function() {               
  54.         if (this.videoElement?.srcObject) {
  55.                 this.videoElement.srcObject.getTracks().forEach(track => {
  56.                         track.stop()
  57.                         this.videoElement.srcObject.removeTrack(track);
  58.                 });
  59.         }
  60.         if (this.pc) {
  61.                 fetch(this.srvurl + "/api/hangup?peerid=" + this.pc.peerid)
  62.                         .then(this._handleHttpErrors)
  63.                         .catch( (error) => this.onError("hangup " + error ))
  64.                
  65.                 try {
  66.                         this.pc.close();
  67.                 }
  68.                 catch (e) {
  69.                         console.log ("Failure close peer connection:" + e);
  70.                 }
  71.                 this.pc = null;
  72.         }
  73. }   
  74. /*
  75. * GetIceServers callback
  76. */
  77. WebRtcStreamer.prototype.onReceiveGetIceServers = function(iceServers, videourl, audiourl, options, stream) {
  78.         this.iceServers       = iceServers;
  79.         this.pcConfig         = iceServers || {"iceServers": [] };
  80.         try {            
  81.                 this.createPeerConnection();
  82.                 var callurl = this.srvurl + "/api/call?peerid=" + this.pc.peerid + "&url=" + encodeURIComponent(videourl);
  83.                 if (audiourl) {
  84.                         callurl += "&audiourl="+encodeURIComponent(audiourl);
  85.                 }
  86.                 if (options) {
  87.                         callurl += "&options="+encodeURIComponent(options);
  88.                 }
  89.                
  90.                 if (stream) {
  91.                         this.pc.addStream(stream);
  92.                 }
  93.                 // clear early candidates
  94.                 this.earlyCandidates.length = 0;
  95.                
  96.                 // create Offer
  97.                 this.pc.createOffer(this.mediaConstraints).then((sessionDescription) => {
  98.                         console.log("Create offer:" + JSON.stringify(sessionDescription));
  99.                        
  100.                         this.pc.setLocalDescription(sessionDescription)
  101.                                 .then(() => {
  102.                                         fetch(callurl, { method: "POST", body: JSON.stringify(sessionDescription) })
  103.                                                 .then(this._handleHttpErrors)
  104.                                                 .then( (response) => (response.json()) )
  105.                                                 .catch( (error) => this.onError("call " + error ))
  106.                                                 .then( (response) =>  this.onReceiveCall(response) )
  107.                                                 .catch( (error) => this.onError("call " + error ))
  108.                                
  109.                                 }, (error) => {
  110.                                         console.log ("setLocalDescription error:" + JSON.stringify(error));
  111.                                 });
  112.                        
  113.                 }, (error) => {
  114.                         alert("Create offer error:" + JSON.stringify(error));
  115.                 });
  116.         } catch (e) {
  117.                 this.disconnect();
  118.                 alert("connect error: " + e);
  119.         }            
  120. }
  121. WebRtcStreamer.prototype.getIceCandidate = function() {
  122.         fetch(this.srvurl + "/api/getIceCandidate?peerid=" + this.pc.peerid)
  123.                 .then(this._handleHttpErrors)
  124.                 .then( (response) => (response.json()) )
  125.                 .then( (response) =>  this.onReceiveCandidate(response))
  126.                 .catch( (error) => this.onError("getIceCandidate " + error ))
  127. }
  128.                                        
  129. /*
  130. * create RTCPeerConnection
  131. */
  132. WebRtcStreamer.prototype.createPeerConnection = function() {
  133.         console.log("createPeerConnection  config: " + JSON.stringify(this.pcConfig));
  134.         this.pc = new RTCPeerConnection(this.pcConfig);
  135.         var pc = this.pc;
  136.         pc.peerid = Math.random();               
  137.        
  138.         pc.onicecandidate = (evt) => this.onIceCandidate(evt);
  139.         pc.onaddstream    = (evt) => this.onAddStream(evt);
  140.         pc.oniceconnectionstatechange = (evt) => {  
  141.                 console.log("oniceconnectionstatechange  state: " + pc.iceConnectionState);
  142.                 if (this.videoElement) {
  143.                         if (pc.iceConnectionState === "connected") {
  144.                                 this.videoElement.style.opacity = "1.0";
  145.                         }                       
  146.                         else if (pc.iceConnectionState === "disconnected") {
  147.                                 this.videoElement.style.opacity = "0.25";
  148.                         }                       
  149.                         else if ( (pc.iceConnectionState === "failed") || (pc.iceConnectionState === "closed") )  {
  150.                                 this.videoElement.style.opacity = "0.5";
  151.                         } else if (pc.iceConnectionState === "new") {
  152.                                 this.getIceCandidate();
  153.                         }
  154.                 }
  155.         }
  156.         pc.ondatachannel = function(evt) {  
  157.                 console.log("remote datachannel created:"+JSON.stringify(evt));
  158.                
  159.                 evt.channel.onopen = function () {
  160.                         console.log("remote datachannel open");
  161.                         this.send("remote channel openned");
  162.                 }
  163.                 evt.channel.onmessage = function (event) {
  164.                         console.log("remote datachannel recv:"+JSON.stringify(event.data));
  165.                 }
  166.         }
  167.         pc.onicegatheringstatechange = function() {
  168.                 if (pc.iceGatheringState === "complete") {
  169.                         const recvs = pc.getReceivers();
  170.                
  171.                         recvs.forEach((recv) => {
  172.                           if (recv.track && recv.track.kind === "video") {
  173.                                 console.log("codecs:" + JSON.stringify(recv.getParameters().codecs))
  174.                           }
  175.                         });
  176.                   }
  177.         }
  178.         try {
  179.                 var dataChannel = pc.createDataChannel("ClientDataChannel");
  180.                 dataChannel.onopen = function() {
  181.                         console.log("local datachannel open");
  182.                         this.send("local channel openned");
  183.                 }
  184.                 dataChannel.onmessage = function(evt) {
  185.                         console.log("local datachannel recv:"+JSON.stringify(evt.data));
  186.                 }
  187.         } catch (e) {
  188.                 console.log("Cannor create datachannel error: " + e);
  189.         }       
  190.        
  191.         console.log("Created RTCPeerConnnection with config: " + JSON.stringify(this.pcConfig) );
  192.         return pc;
  193. }
  194. /*
  195. * RTCPeerConnection IceCandidate callback
  196. */
  197. WebRtcStreamer.prototype.onIceCandidate = function (event) {
  198.         if (event.candidate) {
  199.                 if (this.pc.currentRemoteDescription)  {
  200.                         this.addIceCandidate(this.pc.peerid, event.candidate);                                       
  201.                 } else {
  202.                         this.earlyCandidates.push(event.candidate);
  203.                 }
  204.         }
  205.         else {
  206.                 console.log("End of candidates.");
  207.         }
  208. }
  209. WebRtcStreamer.prototype.addIceCandidate = function(peerid, candidate) {
  210.         fetch(this.srvurl + "/api/addIceCandidate?peerid="+peerid, { method: "POST", body: JSON.stringify(candidate) })
  211.                 .then(this._handleHttpErrors)
  212.                 .then( (response) => (response.json()) )
  213.                 .then( (response) =>  {console.log("addIceCandidate ok:" + response)})
  214.                 .catch( (error) => this.onError("addIceCandidate " + error ))
  215. }
  216.                                
  217. /*
  218. * RTCPeerConnection AddTrack callback
  219. */
  220. WebRtcStreamer.prototype.onAddStream = function(event) {
  221.         console.log("Remote track added:" +  JSON.stringify(event));
  222.        
  223.         this.videoElement.srcObject = event.stream;
  224.         var promise = this.videoElement.play();
  225.         if (promise !== undefined) {
  226.           promise.catch((error) => {
  227.                 console.warn("error:"+error);
  228.                 this.videoElement.setAttribute("controls", true);
  229.           });
  230.         }
  231. }
  232.                
  233. /*
  234. * AJAX /call callback
  235. */
  236. WebRtcStreamer.prototype.onReceiveCall = function(dataJson) {
  237.         console.log("offer: " + JSON.stringify(dataJson));
  238.         var descr = new RTCSessionDescription(dataJson);
  239.         this.pc.setRemoteDescription(descr).then(() =>  {
  240.                         console.log ("setRemoteDescription ok");
  241.                         while (this.earlyCandidates.length) {
  242.                                 var candidate = this.earlyCandidates.shift();
  243.                                 this.addIceCandidate(this.pc.peerid, candidate);                               
  244.                         }
  245.                
  246.                         this.getIceCandidate()
  247.                 }
  248.                 , (error) => {
  249.                         console.log ("setRemoteDescription error:" + JSON.stringify(error));
  250.                 });
  251. }       
  252. /*
  253. * AJAX /getIceCandidate callback
  254. */
  255. WebRtcStreamer.prototype.onReceiveCandidate = function(dataJson) {
  256.         console.log("candidate: " + JSON.stringify(dataJson));
  257.         if (dataJson) {
  258.                 for (var i=0; i<dataJson.length; i++) {
  259.                         var candidate = new RTCIceCandidate(dataJson[i]);
  260.                        
  261.                         console.log("Adding ICE candidate :" + JSON.stringify(candidate) );
  262.                         this.pc.addIceCandidate(candidate).then( () =>      { console.log ("addIceCandidate OK"); }
  263.                                 , (error) => { console.log ("addIceCandidate error:" + JSON.stringify(error)); } );
  264.                 }
  265.                 this.pc.addIceCandidate();
  266.         }
  267. }
  268. /*
  269. * AJAX callback for Error
  270. */
  271. WebRtcStreamer.prototype.onError = function(status) {
  272.         console.log("onError:" + status);
  273. }
  274. return WebRtcStreamer;
  275. })();
  276. if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
  277.         window.WebRtcStreamer = WebRtcStreamer;
  278. }
  279. if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
  280.         module.exports = WebRtcStreamer;
  281. }
复制代码
2.下载webrtc-streamer

资源在最上面
也可以去github上面下载:webrtc-streamer
下载完解压,打开文件夹,启动webrtc-streamer.exe

打开完会出现cmd一样的黑框框如下

如果没有启动乐成可以在浏览器中输入http://127.0.0.1:8000/查看当地端口8000是否被其他应用程序占用,如果没有被占用打开窗口应该如下图所示(是可以看见自己的页面的)

3.封装组件video.vue(名字随意)

代码如下(但是有需要留意的地方,请看下方)
  1. <template>
  2.   <div id="video-contianer">
  3.     <video
  4.       class="video"
  5.       ref="video"
  6.       preload="auto"
  7.       autoplay="autoplay"
  8.       muted
  9.       width="600"
  10.       height="400"
  11.     />
  12.     <div
  13.       class="mask"
  14.       @click="handleClickVideo"
  15.       :class="{ 'active-video-border': selectStatus }"
  16.     ></div>
  17.   </div>
  18. </template>
  19. <script>
  20. import WebRtcStreamer from '../../public/hk/webrtcstreamer'
  21. export default {
  22.   name: 'videoCom',
  23.   props: {
  24.     rtsp: {
  25.       type: String,
  26.       required: true,
  27.     },
  28.     isOn: {
  29.       type: Boolean,
  30.       default: false,
  31.     },
  32.     spareId: {
  33.       type: Number,
  34.     },
  35.     selectStatus: {
  36.       type: Boolean,
  37.       default: false,
  38.     },
  39.   },
  40.   data() {
  41.     return {
  42.       socket: null,
  43.       result: null, // 返回值
  44.       pic: null,
  45.       webRtcServer: null,
  46.       clickCount: 0, // 用来计数点击次数
  47.     }
  48.   },
  49.   watch: {
  50.     rtsp() {
  51.       // do something
  52.       console.log(this.rtsp)
  53.       this.webRtcServer.disconnect()
  54.       this.initVideo()
  55.     },
  56.   },
  57.   destroyed() {
  58.     this.webRtcServer.disconnect()
  59.   },
  60.   beforeCreate() {
  61.     window.onbeforeunload = () => {
  62.       this.webRtcServer.disconnect()
  63.     }
  64.   },
  65.   created() {},
  66.   mounted() {
  67.     this.initVideo()
  68.   },
  69.   methods: {
  70.     initVideo() {
  71.       try {
  72.         //连接后端的IP地址和端口
  73.         this.webRtcServer = new WebRtcStreamer(
  74.           this.$refs.video,
  75.           `http://192.168.1.102:8000`
  76.         )
  77.         //向后端发送rtsp地址
  78.         this.webRtcServer.connect(this.rtsp)
  79.       } catch (error) {
  80.         console.log(error)
  81.       }
  82.     },
  83.     /* 处理双击 单机 */
  84.     dbClick() {
  85.       this.clickCount++
  86.       if (this.clickCount === 2) {
  87.         this.btnFull() // 双击全屏
  88.         this.clickCount = 0
  89.       }
  90.       setTimeout(() => {
  91.         if (this.clickCount === 1) {
  92.           this.clickCount = 0
  93.         }
  94.       }, 250)
  95.     },
  96.     /* 视频全屏 */
  97.     btnFull() {
  98.       const elVideo = this.$refs.video
  99.       if (elVideo.webkitRequestFullScreen) {
  100.         elVideo.webkitRequestFullScreen()
  101.       } else if (elVideo.mozRequestFullScreen) {
  102.         elVideo.mozRequestFullScreen()
  103.       } else if (elVideo.requestFullscreen) {
  104.         elVideo.requestFullscreen()
  105.       }
  106.     },
  107.     /*
  108.     ison用来判断是否需要更换视频流
  109.     dbclick函数用来双击放大全屏方法
  110.     */
  111.     handleClickVideo() {
  112.       if (this.isOn) {
  113.         this.$emit('selectVideo', this.spareId)
  114.         this.dbClick()
  115.       } else {
  116.         this.btnFull()
  117.       }
  118.     },
  119.   },
  120. }
  121. </script>
  122. <style scoped lang="scss">
  123. .active-video-border {
  124.   border: 2px salmon solid;
  125. }
  126. #video-contianer {
  127.   position: relative;
  128.   // width: 100%;
  129.   // height: 100%;
  130.   .video {
  131.     // width: 100%;
  132.     // height: 100%;
  133.     // object-fit: cover;
  134.   }
  135.   .mask {
  136.     position: absolute;
  137.     top: 0;
  138.     left: 0;
  139.     width: 100%;
  140.     height: 100%;
  141.     cursor: pointer;
  142.   }
  143. }
  144. </style>
复制代码
这里要留意两个地方
第一个是

第二个是

不会查看本机端口的看这里(起首使用 Win + R打开运行 输入cmd)



4.使用video封装组件播放rtsp视频流

起首我们在要使用video封装组件的地方引入并且注册video组件

之后在页面中使用video组件 并且定义了两个变量将rtsp流传给封装的video组件

效果图如下

5.使用此种方法播放的时候会默认带声音播放,如何取消(看这里)


之后声明一个方法

然后在created里面调用就静音了

四.其他功能

1.截图功能

rtsp流引入海康威视摄像头——截图功能-CSDN博客
到此为止海康摄像头引入vue的方法就完美完结了
如果同砚们有什么好的意见或者有什么题目可以私信我
最后祝各人事业蒸蒸日上,心想事成!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

祗疼妳一个

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表