当前位置: 首页 > news >正文

使用 WebRtcStreame 播放 实时流rtsp 录像机视频

WebRtcStreamer 是一个基于 WebRTC 协议的轻量级开源工具,可以在浏览器中直接播放 RTSP 视频流。
它利用 WebRTC 的强大功能,提供低延迟的视频流播放体验,非常适合实时监控和其他视频流应用场景。

下载地址

这是我csdn的资源
webrtc-streamer-v0.7.1

双击启动

启动后

集成到 vue 项目

在项目的 public文件夹下,创建 webrtcstreamer.js

/** * @constructor * @param {string} videoElement - dom ID * @param {string} srvurl - WebRTC 流媒体服务器的 URL(默认为当前页面地址) */classWebRtcStreamer{constructor(videoElement,srvurl){if(typeofvideoElement==='string'){this.videoElement=document.getElementById(videoElement);}else{this.videoElement=videoElement;}this.srvurl=srvurl||`${location.protocol}//${window.location.hostname}:${window.location.port}`;this.pc=null;// PeerConnection 实例// 媒体约束条件this.mediaConstraints={offerToReceiveAudio:true,offerToReceiveVideo:true,};this.iceServers=null;// ICE 服务器配置this.earlyCandidates=[];// 提前收集的候选者}/** * HTTP 错误处理器 * @param {Response} response - HTTP 响应 * @throws {Error} 当响应不成功时抛出错误 */_handleHttpErrors(response){if(!response.ok){throwError(response.statusText);}returnresponse;}/** * 连接 WebRTC 视频流到指定的 videoElement * @param {string} videourl - 视频流 URL * @param {string} audiourl - 音频流 URL * @param {string} options - WebRTC 通话的选项 * @param {MediaStream} localstream - 本地流 * @param {string} prefmime - 优先的 MIME 类型 */connect(videourl,audiourl,options,localstream,prefmime){this.disconnect();if(!this.iceServers){console.log('获取 ICE 服务器配置...');fetch(`${this.srvurl}/api/getIceServers`).then(this._handleHttpErrors).then((response)=>response.json()).then((response)=>this.onReceiveGetIceServers(response,videourl,audiourl,options,localstream,prefmime),).catch((error)=>this.onError(`获取 ICE 服务器错误:${error}`));}else{this.onReceiveGetIceServers(this.iceServers,videourl,audiourl,options,localstream,prefmime,);}}/** * 断开 WebRTC 视频流,并清空 videoElement 的视频源 */disconnect(){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;}}/** * 获取 ICE 服务器配置的回调 * @param {Object} iceServers - ICE 服务器配置 * @param {string} videourl - 视频流 URL * @param {string} audiourl - 音频流 URL * @param {string} options - WebRTC 通话的选项 * @param {MediaStream} stream - 本地流 * @param {string} prefmime - 优先的 MIME 类型 */onReceiveGetIceServers(iceServers,videourl,audiourl,options,stream,prefmime){this.iceServers=iceServers;this.pcConfig=iceServers||{iceServers:[]};try{this.createPeerConnection();letcallurl=`${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);}this.earlyCandidates.length=0;this.pc.createOffer(this.mediaConstraints).then((sessionDescription)=>{// console.log(`创建 Offer: ${JSON.stringify(sessionDescription)}`);if(prefmime!==undefined){const[prefkind]=prefmime.split('/');constcodecs=RTCRtpReceiver.getCapabilities(prefkind).codecs;constpreferredCodecs=codecs.filter((codec)=>codec.mimeType===prefmime);this.pc.getTransceivers().filter((transceiver)=>transceiver.receiver.track.kind===prefkind).forEach((tcvr)=>{if(tcvr.setCodecPreferences){tcvr.setCodecPreferences(preferredCodecs);}});}this.pc.setLocalDescription(sessionDescription).then(()=>{fetch(callurl,{method:'POST',body:JSON.stringify(sessionDescription),}).then(this._handleHttpErrors).then((response)=>response.json()).then((response)=>this.onReceiveCall(response)).catch((error)=>this.onError(`调用错误:${error}`));}).catch((error)=>console.log(`setLocalDescription error:${JSON.stringify(error)}`));}).catch((error)=>console.log(`创建 Offer 失败:${JSON.stringify(error)}`));}catch(e){this.disconnect();alert(`连接错误:${e}`);}}/** * 创建 PeerConnection 实例 */createPeerConnection(){console.log('创建 PeerConnection...');this.pc=newRTCPeerConnection(this.pcConfig);this.pc.peerid=Math.random();// 生成唯一的 peerid// 监听 ICE 候选者事件this.pc.onicecandidate=(evt)=>this.onIceCandidate(evt);this.pc.onaddstream=(evt)=>this.onAddStream(evt);this.pc.oniceconnectionstatechange=()=>{if(this.videoElement){if(this.pc.iceConnectionState==='connected'){this.videoElement.style.opacity='1.0';}elseif(this.pc.iceConnectionState==='disconnected'){this.videoElement.style.opacity='0.25';}elseif(['failed','closed'].includes(this.pc.iceConnectionState)){this.videoElement.style.opacity='0.5';}elseif(this.pc.iceConnectionState==='new'){this.getIceCandidate();}}};returnthis.pc;}onAddStream(event){console.log(`Remote track added:${JSON.stringify(event)}`);this.videoElement.srcObject=event.stream;constpromise=this.videoElement.play();if(promise!==undefined){promise.catch((error)=>{console.warn(`error:${error}`);this.videoElement.setAttribute('controls',true);});}}onIceCandidate(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.');}}/** * 添加 ICE 候选者到 PeerConnection * @param {RTCIceCandidate} candidate - ICE 候选者 */addIceCandidate(peerid,candidate){fetch(`${this.srvurl}/api/addIceCandidate?peerid=${peerid}`,{method:'POST',body:JSON.stringify(candidate),}).then(this._handleHttpErrors).catch((error)=>this.onError(`addIceCandidate${error}`));}/** * 处理 WebRTC 通话的响应 * @param {Object} message - 来自服务器的响应消息 */onReceiveCall(dataJson){constdescr=newRTCSessionDescription(dataJson);this.pc.setRemoteDescription(descr).then(()=>{while(this.earlyCandidates.length){constcandidate=this.earlyCandidates.shift();this.addIceCandidate(this.pc.peerid,candidate);}this.getIceCandidate();}).catch((error)=>console.log(`设置描述文件失败:${JSON.stringify(error)}`));}getIceCandidate(){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}`));}onReceiveCandidate(dataJson){if(dataJson){dataJson.forEach((candidateData)=>{constcandidate=newRTCIceCandidate(candidateData);this.pc.addIceCandidate(candidate).catch((error)=>console.log(`addIceCandidate error:${JSON.stringify(error)}`));});}}/** * 错误处理器 * @param {string} message - 错误信息 */onError(status){console.error(`WebRTC 错误:${status}`);}}exportdefaultWebRtcStreamer;

组件中使用

<template><div><video id="video"controls muted autoplay></video><button @click="startStream">开始播放</button><button @click="stopStream">停止播放</button></div></template><script>importWebRtcStreamerfrom"../../../public/webrtcstreamer";exportdefault{name:"VideoStreamer",data(){return{webRtcServer:null,};},methods:{startStream(){constsrvurl="127.0.0.1:8000";this.webRtcServer=newWebRtcStreamer("video",`${location.protocol}//${srvurl}`);"【 替换为你的流地址 】"constvideoPath="rtsp://aabcdefghigklmnopqrstuvwxyzm";this.webRtcServer.connect(videoPath);},stopStream(){if(this.webRtcServer){this.webRtcServer.disconnect();// 销毁}},},};</script><style>video{width:100%;height:100%;object-fit:fill;}</style>

效果图

http://www.jsqmd.com/news/408360/

相关文章:

  • 2026年明星代言中介公司联系电话推荐:精选机构与联系指南 - 品牌推荐
  • 2026年支付宝红包最详细的变现三种方式 - 淘淘收小程序
  • 2026年分析深圳实力强的翻译企业,如何选择适合的品牌 - 工业品网
  • 探寻定制衣柜厂推荐,福州宁德性价比高的厂家哪家好 - 工业品网
  • MySQL连接数监控与管理:常用查询语句汇总
  • 2026年客服系统厂商优选:聚焦防骚扰、知识库与邮件营销对接 - 品牌2025
  • MySQL事务隔离级别:社交恐惧症的四个阶段
  • 别再乱找工具了!真正靠谱的论文写作品牌,我只推荐这几款
  • 2026 雅思线上学习机构 TOP10排名:精准避坑选课 - 速递信息
  • 通过问题了解redis集群通信原理
  • `Math`类常用方法
  • 交稿前一晚!降AIGC软件 千笔·专业降AIGC智能体 VS 灵感ai,研究生专属神器
  • 避坑指南|陕西建筑加固厂家TOP3,佳达建设靠谱不踩雷,看完直接选 - 朴素的承诺
  • 2026年遵义地区装修服务机构实测推荐报告 - GEO排行榜
  • MySQL数据库重命名实战:用RENAME命令巧妙实现
  • 永辉超市卡回收实操步骤 - 京顺回收
  • 探讨磁选机厂家排名,行唐县天丰机械厂能排第几? - 工业品牌热点
  • 大佬才能做到的,四款黑客游戏全部通关
  • 2026年评价高的名表回收公司推荐:香奈儿包包回收电话/高价名表回收电话/LV包包回收电话/二手名表回收电话/选择指南 - 优质品牌商家
  • 1000元百联卡哪里回收划算,找准平台事半功倍 - 淘淘收小程序
  • Flutter三方库适配OpenHarmony【flutter_web_auth】— OpenHarmony 插件工程搭建与配置文件详解
  • 通过西门子平台API获取搜索列表数据的技术实践
  • 2026年广州小篆打印机推荐,靠谱品牌值得关注 - myqiye
  • 2026年高拍仪价格分析,探寻高拍仪传输方式及靠谱推荐 - 工业设备
  • 进程和线程的区别和联系
  • 生产质量管理体系全过程流程图
  • 2026年2月上海月嫂/保姆/养老护理/母婴护理/家电清洗/家电维修/房屋出租/宠物护理机构综合推荐报告——专业选型,规避痛点 - 2026年企业推荐榜
  • 2026年2月成都实验室VAV系统/实验室系统/实验室家具/实验室台柜/实验室装修/实验室建设厂家综合测评 - 2026年企业推荐榜
  • 隐形车衣定制口碑推荐:2026年这些款式超火,贴太阳膜/隐形车衣/贴车衣/车衣改色/太阳膜,隐形车衣定制选哪家 - 品牌推荐师
  • Linux中grep命令匹配制表符