vue视频直接播放rtsp流;vue视频延迟问题解决;webRTC占cpu太大卡死问题解决;解决webRTC播放卡花屏问题:
播放多个视频
<div class="video-box"><div class="video"><iframe style="width:100%;height:100%;" name="ddddd" id="iframes" scrolling="auto" :src="videoLeftUrl"></iframe></div><div class="video"><iframe style="width:100%;height:100%;" name="ddddd" id="iframes" scrolling="auto" :src="videoRightUrl"></iframe></div><div class="video"><iframe style="width:100%;height:100%;" name="ddddd" id="iframes" scrolling="auto" :src="videoRtspUrl"></iframe></div></div>
js部分其中的item就是rtsp视频流
getShareVideoLeftUrl(item) {this.videoLeftUrl = `/static/test.html?data=${item}`},getShareVideoRightUrl(item) {this.videoRightUrl = `/static/test.html?data=${item}`},getShareVideoRtspUrl(item) {this.videoRtspUrl = `/static/test.html?data=${item}`},
public/static/test.html内容
<html><head><script src="js/webrtcstreamer.js"></script><script>// 接受从vue组件中传过来的参数let url = location.search; //这一条语句获取了包括问号开始到参数的最后,不包括前面的路径let params = url.substr(1); //去掉问号let pa = params.split("&");let s = new Object();// 设置后端服务地址let VIDEOURL = "http://172.18.127.7:8000" //服务视频webrtcfor (let i = 0; i < pa.length; i++) {s[pa[i].split("=")[0]] = unescape(pa[i].split("=")[1]);}console.log(s.data)window.onload = function() {webRtcServer = new WebRtcStreamer("video", VIDEOURL);webRtcServer.connect(s.data);}window.onbeforeunload = function() {webRtcServer.disconnect();}</script></head><body><h1 value="da3"></h1><video id="video" style="width: 100%;height: 100%;" controls autoplay muted /></body>
</html>
其中public/static/js/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.pcOptions = { "optional": [{"DtlsSrtpKeyAgreement": true} ] };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.call(this,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) {this.videoElement.src = "";}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 Offervar bind = this;this.pc.createOffer(this.mediaConstraints).then(function(sessionDescription) {console.log("Create offer:" + JSON.stringify(sessionDescription));bind.pc.setLocalDescription(sessionDescription, function() {fetch(callurl, { method: "POST", body: JSON.stringify(sessionDescription) }).then(bind._handleHttpErrors).then( (response) => (response.json()) ).catch( (error) => bind.onError("call " + error )).then( (response) => bind.onReceiveCall.call(bind,response) ).catch( (error) => bind.onError("call " + error ))}, function(error) {console.log ("setLocalDescription error:" + JSON.stringify(error)); } );}, function(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.call(this, response)).catch( (error) => bind.onError("getIceCandidate " + error ))
}/*
* create RTCPeerConnection
*/
WebRtcStreamer.prototype.createPeerConnection = function() {console.log("createPeerConnection config: " + JSON.stringify(this.pcConfig) + " option:"+ JSON.stringify(this.pcOptions));this.pc = new RTCPeerConnection(this.pcConfig, this.pcOptions);var pc = this.pc;pc.peerid = Math.random(); var bind = this;pc.onicecandidate = function(evt) { bind.onIceCandidate.call(bind, evt); };pc.onaddstream = function(evt) { bind.onAddStream.call(bind,evt); };pc.oniceconnectionstatechange = function(evt) { console.log("oniceconnectionstatechange state: " + pc.iceConnectionState);if (bind.videoElement) {if (pc.iceConnectionState === "connected") {bind.videoElement.style.opacity = "1.0";} else if (pc.iceConnectionState === "disconnected") {bind.videoElement.style.opacity = "0.25";} else if ( (pc.iceConnectionState === "failed") || (pc.iceConnectionState === "closed") ) {bind.videoElement.style.opacity = "0.5";} else if (pc.iceConnectionState === "new") {bind.getIceCandidate.call(bind)}}}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) + "option:"+ JSON.stringify(this.pcOptions) );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) {var bind = this;promise.catch(function(error) {console.warn("error:"+error);bind.videoElement.setAttribute("controls", true);});}
}/*
* AJAX /call callback
*/
WebRtcStreamer.prototype.onReceiveCall = function(dataJson) {var bind = this;console.log("offer: " + JSON.stringify(dataJson));var descr = new RTCSessionDescription(dataJson);this.pc.setRemoteDescription(descr, function() { console.log ("setRemoteDescription ok");while (bind.earlyCandidates.length) {var candidate = bind.earlyCandidates.shift();bind.addIceCandidate.call(bind, bind.pc.peerid, candidate); }bind.getIceCandidate.call(bind)}, function(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, function() { console.log ("addIceCandidate OK"); }, function(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 module !== 'undefined' && typeof module.exports !== 'undefined')module.exports = WebRtcStreamer;
elsewindow.WebRtcStreamer = WebRtcStreamer;
这里启用需要下载webRTC
https://github.com/mpromonet/webrtc-streamer/releases
需要注意的是这里启动不要直接双击而是使用cmd命令启动

start 应用名 -o
一定加上-o否则webRTC占cpu太大 容易卡死
解决卡花屏问题:
在html页面中的webRtcServer.connect(s.data,"","rtptransport=tcp");加上"","rtptransport=tcp"就搞定
<html><head><script src="js/webrtcstreamer.js"></script><script>// 接受从vue组件中传过来的参数let url = location.search; //这一条语句获取了包括问号开始到参数的最后,不包括前面的路径let params = url.substr(1); //去掉问号let pa = params.split("&");let s = new Object();// 设置后端服务地址let VIDEOURL = "http://172.18.127.7:8000" //服务视频webrtcfor (let i = 0; i < pa.length; i++) {s[pa[i].split("=")[0]] = unescape(pa[i].split("=")[1]);}console.log(s.data)window.onload = function() {webRtcServer = new WebRtcStreamer("video", VIDEOURL);webRtcServer.connect(s.data,"","rtptransport=tcp");}window.onbeforeunload = function() {webRtcServer.disconnect();}</script></head><body><h1 value="da3"></h1><video id="video" style="width: 100%;height: 100%;" controls autoplay muted /></body>
</html>
相关文章:
vue视频直接播放rtsp流;vue视频延迟问题解决;webRTC占cpu太大卡死问题解决;解决webRTC播放卡花屏问题:
播放多个视频 <div class"video-box"><div class"video"><iframe style"width:100%;height:100%;" name"ddddd" id"iframes" scrolling"auto" :src"videoLeftUrl"></iframe>&l…...
leetcode_2316 统计无向图中无法互相到达点对数
1. 题意 给定一个无向图, 统计无法互相到达的点对数。 统计无法互相到达点对数 2. 题解 其实还是求联通块,求联通块可以使用搜索进行标记。还要求得联通块中元素的大小。 联通块其实也就是不相交集合,也可以用并查集来做。 每求得一个联…...
数据结构知识点总结
一、常见的数据结构 数组,栈,队列,链表,散列表,二叉树,堆,跳表,图,树。 1. 数组: 数组的元素在内存中存储是连续存放的,占有连续的存储单元&am…...
【经济研究】数字技术创新与中国企业高质量发展—来自企业数字专利的证据
数据简介:在当前数字经济时代,数字技术创新已成为驱动中国经济发展的核心要素,中国经济由高速增长转向高质量发展的“新常态”发展阶段,开启了革新经济增长方式,优化产业结构,寻找新的经济增长动能关键期。…...
Windows运维相关经验技巧
常用工具 在线PS Photoshop在线 FAQ 电脑能上网,浏览器上不了网 # 错误原因: 设置了网络代理,浏览器无法通过网络代理上网# 解决办法 关闭网络代理 (1)wini,打开设置 (2)网络和I…...
AYIT嵌入式实验室2023级C语言训练1-4章训练题
文章目录 前言1. 判断闰年2.(ab-c)*d的计算问题3.计算三角形的周长和面积4.牛牛的等差数列5.判断字母6.网购7. 牛牛的通勤8.获得月份天数9.大小写转换10.KiKi说祝福语11.小乐乐求和12.奇偶统计13.KiKi求质数个数14.乘法表15.牛牛学数列16.牛牛学数列217.数位之和18.魔法数字变换…...
trino tpcds测试
先下载tpcds-kit(有Linux和macOS),根据其文档生成数据和查询的sql。 然后hive-testbench,在ddl-tpcds/text/alltables.sql中有建表语句(用hive建表)。 建完表后LOAD DATA local INPATH "/Users/ding…...
SpringCloud学习笔记(上):服务注册与发现:Eureka、Zookeeper、Consul+负载均衡服务调用:Ribbon
壹、零基础 一、微服务架构零基础理论入门 SpringCloud分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶。 二、从2.2.x和H版开始说起 springboot版本选择: git源码地址:https://github.…...
JavaPTA练习题 7-3 身体质量指数(BMI)测算
体重是反映和衡量一个人健康状况的重要标志之一,过胖和过瘦都不利于健康,BMI(身体质量指数)计算方法:体重(以千克为单位)除以身高(以米为单位)的平方。中国成人正常的BMI…...
类的属性和方法(java)
类和对象的使用 创建类,设计类的成员创建类的对象通过“对象.属性”或“对象.方法”调用对象的结构 代码 public class Per {public static void main(String[] args) {// TODO Auto-generated method stub//创建Person类的对象Person p1 new Person();//Scanne…...
C++模拟实现——list
一、成员变量及其基本结构 1.基本结构模型 本质是一个带头双向循环列表,将节点进行封装,并且为了方便使用,进行重定义 2.节点的封装定义 template<class T>//定义节点struct list_node{list_node<T>* _prev;list_node<T>…...
FPGA的音乐彩灯VHDL流水灯LED花样,源码和视频
名称:FPGA的音乐彩灯VHDL流水灯LED 软件:Quartus 语言:VHDL 代码功能: (1)设计一彩灯控制电路,按要求控制8路(彩灯由发光 二极管代替,受实验箱限制,多路同…...
企业知识库软件,快速构建企业知识分享与团队协同的软件
企业知识库是一种特殊的在线协同文档工具,支持包括FAQ、文档、视频、知识图谱等。从本质上讲,它是基于企业知识库软件从而实现内部或外部知识的沉淀、集合、更新、共享等,能为员工或客户提供常见问题的标准回答。 今天我就基于HelpLook &…...
Java,输出一个10行的杨辉三角
据图可以发现,杨辉三角是每行的首元素和末元素都为1,中间的元素都是等于它上面的元素加上左上角的元素。 首先,先完成二数组的创建和初始化,第一行的长度为一,第二行的长度为二……以此类推。所以,外元素的…...
Java版Http请求post和get两种调用实现
在实际项目中常涉及到相互调用,对于http接口的调用,需要经过建立连接,拼接参数,调用等步骤,记录下来,方便查看。 第一步、引入jar包 pom中引入apache的httpclient包 <dependency><groupId>c…...
yjs demo: 多人在线协作画板
基于 yjs 实现实时在线多人协作的绘画功能 支持多客户端实时共享编辑自动同步,离线支持自动合并,自动冲突处理 1. 客户端代码(基于Vue3) 实现绘画功能 <template><div style"{width: 100vw; height: 100vh; over…...
虹科分享 | 赋能物流机器人:CANopen通信如何发挥重要作用?
现代物流领域迅速融入了技术进步,特别是随着自主机器人的兴起,这一趋势越发明显。确保这些机器人在复杂的仓库环境中精确运行的一个关键方面是CANopen通信协议。该协议集成了各种组件(电机、传感器、摄像头和先进的电池系统)&…...
南丁格尔玫瑰图
目录 由来 效果图 echarts官网找相似图 将南丁格尔玫瑰图引进html页面中 引入echarts 准备容器 初始化echarts实例对象 指定配置项和数据(官网给的option) 将配置项给echarts 自定义南格丁尔玫瑰图 修改颜色 修改玫瑰图大小 修改图的模式为半…...
vue 大文件切片下载
前提是你上传的时候也是切片上传,下载的时候后端给你返回的是一个文件id的数组,如果是你就可以用下面的方法 // 循环下载文件 // id是每个文件的id type 是一个类型,我传入是应为给不同的组件赋值getFile(id, type) {// 通过wen文件id去获取…...
2023年“绿盟杯”四川省大学生信息安全技术大赛
pyfile 先check源码,没什么发现,接着进行目录扫描,扫到路径 /download 下载备份文件得到 www.zip,解压得到app.py 大致审一下代码: 在read目录下给file传参进行请求,如果这个东西存在就会读取出来 这里…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
