• vue视频直接播放rtsp流;vue视频延迟问题解决;webRTC占cpu太大卡死问题解决;解决webRTC播放卡花屏问题:


    播放多个视频

    1. <div class="video-box">
    2. <div class="video">
    3. <iframe style="width:100%;height:100%;" name="ddddd" id="iframes" scrolling="auto" :src="videoLeftUrl">iframe>
    4. div>
    5. <div class="video">
    6. <iframe style="width:100%;height:100%;" name="ddddd" id="iframes" scrolling="auto" :src="videoRightUrl">iframe>
    7. div>
    8. <div class="video">
    9. <iframe style="width:100%;height:100%;" name="ddddd" id="iframes" scrolling="auto" :src="videoRtspUrl">iframe>
    10. div>
    11. div>

    js部分其中的item就是rtsp视频流

    1. getShareVideoLeftUrl(item) {
    2. this.videoLeftUrl = `/static/test.html?data=${item}`
    3. },
    4. getShareVideoRightUrl(item) {
    5. this.videoRightUrl = `/static/test.html?data=${item}`
    6. },
    7. getShareVideoRtspUrl(item) {
    8. this.videoRtspUrl = `/static/test.html?data=${item}`
    9. },

    public/static/test.html内容

    1. <html>
    2. <head>
    3. <script src="js/webrtcstreamer.js">script>
    4. <script>
    5. // 接受从vue组件中传过来的参数
    6. let url = location.search; //这一条语句获取了包括问号开始到参数的最后,不包括前面的路径
    7. let params = url.substr(1); //去掉问号
    8. let pa = params.split("&");
    9. let s = new Object();
    10. // 设置后端服务地址
    11. let VIDEOURL = "http://172.18.127.7:8000" //服务视频webrtc
    12. for (let i = 0; i < pa.length; i++) {
    13. s[pa[i].split("=")[0]] = unescape(pa[i].split("=")[1]);
    14. }
    15. console.log(s.data)
    16. window.onload = function() {
    17. webRtcServer = new WebRtcStreamer("video", VIDEOURL);
    18. webRtcServer.connect(s.data);
    19. }
    20. window.onbeforeunload = function() {
    21. webRtcServer.disconnect();
    22. }
    23. script>
    24. head>
    25. <body>
    26. <h1 value="da3">h1>
    27. <video id="video" style="width: 100%;height: 100%;" controls autoplay muted />
    28. body>
    29. html>

    其中public/static/js/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.pcOptions = { "optional": [{"DtlsSrtpKeyAgreement": true} ] };
    17. this.mediaConstraints = { offerToReceiveAudio: true, offerToReceiveVideo: true };
    18. this.iceServers = null;
    19. this.earlyCandidates = [];
    20. }
    21. WebRtcStreamer.prototype._handleHttpErrors = function (response) {
    22. if (!response.ok) {
    23. throw Error(response.statusText);
    24. }
    25. return response;
    26. }
    27. /**
    28. * Connect a WebRTC Stream to videoElement
    29. * @param {string} videourl - id of WebRTC video stream
    30. * @param {string} audiourl - id of WebRTC audio stream
    31. * @param {string} options - options of WebRTC call
    32. * @param {string} stream - local stream to send
    33. */
    34. WebRtcStreamer.prototype.connect = function(videourl, audiourl, options, localstream) {
    35. this.disconnect();
    36. // getIceServers is not already received
    37. if (!this.iceServers) {
    38. console.log("Get IceServers");
    39. fetch(this.srvurl + "/api/getIceServers")
    40. .then(this._handleHttpErrors)
    41. .then( (response) => (response.json()) )
    42. .then( (response) => this.onReceiveGetIceServers.call(this,response, videourl, audiourl, options, localstream))
    43. .catch( (error) => this.onError("getIceServers " + error ))
    44. } else {
    45. this.onReceiveGetIceServers(this.iceServers, videourl, audiourl, options, localstream);
    46. }
    47. }
    48. /**
    49. * Disconnect a WebRTC Stream and clear videoElement source
    50. */
    51. WebRtcStreamer.prototype.disconnect = function() {
    52. if (this.videoElement) {
    53. this.videoElement.src = "";
    54. }
    55. if (this.pc) {
    56. fetch(this.srvurl + "/api/hangup?peerid="+this.pc.peerid)
    57. .then(this._handleHttpErrors)
    58. .catch( (error) => this.onError("hangup " + error ))
    59. try {
    60. this.pc.close();
    61. }
    62. catch (e) {
    63. console.log ("Failure close peer connection:" + e);
    64. }
    65. this.pc = null;
    66. }
    67. }
    68. /*
    69. * GetIceServers callback
    70. */
    71. WebRtcStreamer.prototype.onReceiveGetIceServers = function(iceServers, videourl, audiourl, options, stream) {
    72. this.iceServers = iceServers;
    73. this.pcConfig = iceServers || {"iceServers": [] };
    74. try {
    75. this.createPeerConnection();
    76. var callurl = this.srvurl + "/api/call?peerid="+ this.pc.peerid+"&url="+encodeURIComponent(videourl);
    77. if (audiourl) {
    78. callurl += "&audiourl="+encodeURIComponent(audiourl);
    79. }
    80. if (options) {
    81. callurl += "&options="+encodeURIComponent(options);
    82. }
    83. if (stream) {
    84. this.pc.addStream(stream);
    85. }
    86. // clear early candidates
    87. this.earlyCandidates.length = 0;
    88. // create Offer
    89. var bind = this;
    90. this.pc.createOffer(this.mediaConstraints).then(function(sessionDescription) {
    91. console.log("Create offer:" + JSON.stringify(sessionDescription));
    92. bind.pc.setLocalDescription(sessionDescription
    93. , function() {
    94. fetch(callurl, { method: "POST", body: JSON.stringify(sessionDescription) })
    95. .then(bind._handleHttpErrors)
    96. .then( (response) => (response.json()) )
    97. .catch( (error) => bind.onError("call " + error ))
    98. .then( (response) => bind.onReceiveCall.call(bind,response) )
    99. .catch( (error) => bind.onError("call " + error ))
    100. }
    101. , function(error) {
    102. console.log ("setLocalDescription error:" + JSON.stringify(error));
    103. } );
    104. }, function(error) {
    105. alert("Create offer error:" + JSON.stringify(error));
    106. });
    107. } catch (e) {
    108. this.disconnect();
    109. alert("connect error: " + e);
    110. }
    111. }
    112. WebRtcStreamer.prototype.getIceCandidate = function() {
    113. fetch(this.srvurl + "/api/getIceCandidate?peerid=" + this.pc.peerid)
    114. .then(this._handleHttpErrors)
    115. .then( (response) => (response.json()) )
    116. .then( (response) => this.onReceiveCandidate.call(this, response))
    117. .catch( (error) => bind.onError("getIceCandidate " + error ))
    118. }
    119. /*
    120. * create RTCPeerConnection
    121. */
    122. WebRtcStreamer.prototype.createPeerConnection = function() {
    123. console.log("createPeerConnection config: " + JSON.stringify(this.pcConfig) + " option:"+ JSON.stringify(this.pcOptions));
    124. this.pc = new RTCPeerConnection(this.pcConfig, this.pcOptions);
    125. var pc = this.pc;
    126. pc.peerid = Math.random();
    127. var bind = this;
    128. pc.onicecandidate = function(evt) { bind.onIceCandidate.call(bind, evt); };
    129. pc.onaddstream = function(evt) { bind.onAddStream.call(bind,evt); };
    130. pc.oniceconnectionstatechange = function(evt) {
    131. console.log("oniceconnectionstatechange state: " + pc.iceConnectionState);
    132. if (bind.videoElement) {
    133. if (pc.iceConnectionState === "connected") {
    134. bind.videoElement.style.opacity = "1.0";
    135. }
    136. else if (pc.iceConnectionState === "disconnected") {
    137. bind.videoElement.style.opacity = "0.25";
    138. }
    139. else if ( (pc.iceConnectionState === "failed") || (pc.iceConnectionState === "closed") ) {
    140. bind.videoElement.style.opacity = "0.5";
    141. } else if (pc.iceConnectionState === "new") {
    142. bind.getIceCandidate.call(bind)
    143. }
    144. }
    145. }
    146. pc.ondatachannel = function(evt) {
    147. console.log("remote datachannel created:"+JSON.stringify(evt));
    148. evt.channel.onopen = function () {
    149. console.log("remote datachannel open");
    150. this.send("remote channel openned");
    151. }
    152. evt.channel.onmessage = function (event) {
    153. console.log("remote datachannel recv:"+JSON.stringify(event.data));
    154. }
    155. }
    156. pc.onicegatheringstatechange = function() {
    157. if (pc.iceGatheringState === "complete") {
    158. const recvs = pc.getReceivers();
    159. recvs.forEach((recv) => {
    160. if (recv.track && recv.track.kind === "video") {
    161. console.log("codecs:" + JSON.stringify(recv.getParameters().codecs))
    162. }
    163. });
    164. }
    165. }
    166. try {
    167. var dataChannel = pc.createDataChannel("ClientDataChannel");
    168. dataChannel.onopen = function() {
    169. console.log("local datachannel open");
    170. this.send("local channel openned");
    171. }
    172. dataChannel.onmessage = function(evt) {
    173. console.log("local datachannel recv:"+JSON.stringify(evt.data));
    174. }
    175. } catch (e) {
    176. console.log("Cannor create datachannel error: " + e);
    177. }
    178. console.log("Created RTCPeerConnnection with config: " + JSON.stringify(this.pcConfig) + "option:"+ JSON.stringify(this.pcOptions) );
    179. return pc;
    180. }
    181. /*
    182. * RTCPeerConnection IceCandidate callback
    183. */
    184. WebRtcStreamer.prototype.onIceCandidate = function (event) {
    185. if (event.candidate) {
    186. if (this.pc.currentRemoteDescription) {
    187. this.addIceCandidate(this.pc.peerid, event.candidate);
    188. } else {
    189. this.earlyCandidates.push(event.candidate);
    190. }
    191. }
    192. else {
    193. console.log("End of candidates.");
    194. }
    195. }
    196. WebRtcStreamer.prototype.addIceCandidate = function(peerid, candidate) {
    197. fetch(this.srvurl + "/api/addIceCandidate?peerid="+peerid, { method: "POST", body: JSON.stringify(candidate) })
    198. .then(this._handleHttpErrors)
    199. .then( (response) => (response.json()) )
    200. .then( (response) => {console.log("addIceCandidate ok:" + response)})
    201. .catch( (error) => this.onError("addIceCandidate " + error ))
    202. }
    203. /*
    204. * RTCPeerConnection AddTrack callback
    205. */
    206. WebRtcStreamer.prototype.onAddStream = function(event) {
    207. console.log("Remote track added:" + JSON.stringify(event));
    208. this.videoElement.srcObject = event.stream;
    209. var promise = this.videoElement.play();
    210. if (promise !== undefined) {
    211. var bind = this;
    212. promise.catch(function(error) {
    213. console.warn("error:"+error);
    214. bind.videoElement.setAttribute("controls", true);
    215. });
    216. }
    217. }
    218. /*
    219. * AJAX /call callback
    220. */
    221. WebRtcStreamer.prototype.onReceiveCall = function(dataJson) {
    222. var bind = this;
    223. console.log("offer: " + JSON.stringify(dataJson));
    224. var descr = new RTCSessionDescription(dataJson);
    225. this.pc.setRemoteDescription(descr
    226. , function() {
    227. console.log ("setRemoteDescription ok");
    228. while (bind.earlyCandidates.length) {
    229. var candidate = bind.earlyCandidates.shift();
    230. bind.addIceCandidate.call(bind, bind.pc.peerid, candidate);
    231. }
    232. bind.getIceCandidate.call(bind)
    233. }
    234. , function(error) {
    235. console.log ("setRemoteDescription error:" + JSON.stringify(error));
    236. });
    237. }
    238. /*
    239. * AJAX /getIceCandidate callback
    240. */
    241. WebRtcStreamer.prototype.onReceiveCandidate = function(dataJson) {
    242. console.log("candidate: " + JSON.stringify(dataJson));
    243. if (dataJson) {
    244. for (var i=0; ilength; i++) {
    245. var candidate = new RTCIceCandidate(dataJson[i]);
    246. console.log("Adding ICE candidate :" + JSON.stringify(candidate) );
    247. this.pc.addIceCandidate(candidate
    248. , function() { console.log ("addIceCandidate OK"); }
    249. , function(error) { console.log ("addIceCandidate error:" + JSON.stringify(error)); } );
    250. }
    251. this.pc.addIceCandidate();
    252. }
    253. }
    254. /*
    255. * AJAX callback for Error
    256. */
    257. WebRtcStreamer.prototype.onError = function(status) {
    258. console.log("onError:" + status);
    259. }
    260. return WebRtcStreamer;
    261. })();
    262. if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
    263. module.exports = WebRtcStreamer;
    264. else
    265. window.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"就搞定
    1. <html>
    2. <head>
    3. <script src="js/webrtcstreamer.js">script>
    4. <script>
    5. // 接受从vue组件中传过来的参数
    6. let url = location.search; //这一条语句获取了包括问号开始到参数的最后,不包括前面的路径
    7. let params = url.substr(1); //去掉问号
    8. let pa = params.split("&");
    9. let s = new Object();
    10. // 设置后端服务地址
    11. let VIDEOURL = "http://172.18.127.7:8000" //服务视频webrtc
    12. for (let i = 0; i < pa.length; i++) {
    13. s[pa[i].split("=")[0]] = unescape(pa[i].split("=")[1]);
    14. }
    15. console.log(s.data)
    16. window.onload = function() {
    17. webRtcServer = new WebRtcStreamer("video", VIDEOURL);
    18. webRtcServer.connect(s.data,"","rtptransport=tcp");
    19. }
    20. window.onbeforeunload = function() {
    21. webRtcServer.disconnect();
    22. }
    23. script>
    24. head>
    25. <body>
    26. <h1 value="da3">h1>
    27. <video id="video" style="width: 100%;height: 100%;" controls autoplay muted />
    28. body>
    29. html>

  • 相关阅读:
    【leetcode常见面试题】1. 两数之和
    简单好用的CHM文件阅读器 CHM Viewer Star最新 for mac
    perl对目录的操作
    linux本地yum源配置
    Centos 8 安装 nginx
    为什么IDEA不推荐你使用@Autowired ?
    [SWPUCTF 2023 秋季新生赛]——Web方向 详细Writeup
    WordPress初学者入门教程-附录一搜索引擎优化(SEO)
    AIGC|从革新内容创作到社会共识建立,迎接全新技术维度
    DSPE-PEG-Silane,磷脂-聚乙二醇-硅烷,修饰二氧化硅颗粒用科研试剂
  • 原文地址:https://blog.csdn.net/killerdoubie/article/details/133884070